[DRBD-cvs] user by phil; LGE's big change to the drbdadm's scanne...
drbd-user@lists.linbit.com
drbd-user@lists.linbit.com
Mon, 26 Apr 2004 10:36:34 +0200 (CEST)
DRBD CVS committal
Author : phil
Project : drbd
Module : user
Dir : drbd/user
Modified Files:
Tag: rel-0_7-branch
Makefile drbdadm.h drbdadm_adjust.c drbdadm_main.c
drbdadm_parser.y drbdadm_scanner.fl drbdsetup.c
Log Message:
LGE's big change to the drbdadm's scanner and other internals
of the drbdadm.
* Improves error reporting a lot!
ATTENTION: Changes the syntax of the configuration file! -- This is
the last time we change it before 0.7
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/user/Makefile,v
retrieving revision 1.7.2.16
retrieving revision 1.7.2.17
diff -u -3 -r1.7.2.16 -r1.7.2.17
--- Makefile 5 Apr 2004 11:56:00 -0000 1.7.2.16
+++ Makefile 26 Apr 2004 08:36:29 -0000 1.7.2.17
@@ -27,7 +27,9 @@
drbdadm_adjust.o
drbdadm_scanner.c: drbdadm_scanner.fl drbdadm_parser.h
- flex -odrbdadm_scanner.c drbdadm_scanner.fl
+ flex -s -odrbdadm_scanner.c drbdadm_scanner.fl
+
+# for debug: flex -d -s -odrbdadm_scanner.c drbdadm_scanner.fl
drbdadm_parser.h: drbdadm_parser.y
bison -d -o drbdadm_parser.c drbdadm_parser.y
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/user/Attic/drbdadm.h,v
retrieving revision 1.1.2.21
retrieving revision 1.1.2.22
diff -u -3 -r1.1.2.21 -r1.1.2.22
--- drbdadm.h 21 Apr 2004 21:36:53 -0000 1.1.2.21
+++ drbdadm.h 26 Apr 2004 08:36:29 -0000 1.1.2.22
@@ -2,6 +2,20 @@
#define DRBDADM_H
#include <linux/drbd_config.h>
+#include <sys/utsname.h>
+
+#define E_syntax 2
+#define E_usage 3
+#define E_config_invalid 10
+#define E_exec_error 20
+#define E_thinko 42 /* :) */
+
+/* for check_uniq(): Check for uniqueness of certain values...
+ * comment out if you want to NOT choke on the first conflict */
+#define EXIT_ON_CONFLICT
+
+/* for verify_ips(): make not verifyable ips fatal */
+//#define INVALID_IP_IS_INVALID_CONF
struct d_globals
{
@@ -34,7 +48,7 @@
char* protocol;
char* ind_cmd;
struct d_host_info* me;
- struct d_host_info* partner;
+ struct d_host_info* peer;
struct d_option* net_options;
struct d_option* disk_options;
struct d_option* sync_options;
@@ -48,16 +62,22 @@
extern int adm_syncer(struct d_resource* ,char* );
extern int m_system(int,char** );
extern struct d_option* find_opt(struct d_option*,char*);
+extern void validate_resource(struct d_resource *);
+extern int check_uniq(const char* what, const char *fmt, ...);
+extern void verify_ips(struct d_resource* res);
+
extern char* config_file;
extern int config_valid;
extern struct d_resource* config;
extern struct d_globals global_options;
-extern int line;
+extern int line, fline, c_resource_start;
extern int dry_run;
extern char* drbdsetup;
extern char ss_buffer[255];
+extern struct utsname nodeinfo;
+
/* ssprintf() places the result of the printf in the current stack
frame and sets ptr to the resulting string. If the current stack
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/user/Attic/drbdadm_adjust.c,v
retrieving revision 1.1.2.13
retrieving revision 1.1.2.14
diff -u -3 -r1.1.2.13 -r1.1.2.14
--- drbdadm_adjust.c 8 Apr 2004 13:58:54 -0000 1.1.2.13
+++ drbdadm_adjust.c 26 Apr 2004 08:36:29 -0000 1.1.2.14
@@ -21,6 +21,8 @@
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define _GNU_SOURCE
+
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
@@ -46,13 +48,13 @@
if(pipe(pipes)) {
perror("Creation of pipes failed");
- exit(20);
+ exit(E_exec_error);
}
mpid = fork();
if(mpid == -1) {
fprintf(stderr,"Can not fork");
- exit(20);
+ exit(E_exec_error);
}
if(mpid == 0) {
close(pipes[0]); // close reading end
@@ -60,7 +62,7 @@
close(pipes[1]);
execv(argv[0],argv);
fprintf(stderr,"Can not exec");
- exit(20);
+ exit(E_exec_error);
}
close(pipes[1]); // close writing end
@@ -90,7 +92,7 @@
return r*1024*1024*(1024/def_mult);
default:
fprintf(stderr,"%s is not a valid number\n",s);
- exit(20);
+ exit(E_config_invalid);
}
}
@@ -264,8 +266,8 @@
}
rv=m_fscanf(in,"Remote address: %[0-9.]:%s\n",str1,str2);
- if(rv!=2 || strcmp(str1,res->partner->address) ||
- strcmp(str2,res->partner->port) ) {
+ if(rv!=2 || strcmp(str1,res->peer->address) ||
+ strcmp(str2,res->peer->port) ) {
do_connect=1;
}
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/user/Attic/drbdadm_main.c,v
retrieving revision 1.1.2.44
retrieving revision 1.1.2.45
diff -u -3 -r1.1.2.44 -r1.1.2.45
--- drbdadm_main.c 21 Apr 2004 21:36:53 -0000 1.1.2.44
+++ drbdadm_main.c 26 Apr 2004 08:36:29 -0000 1.1.2.45
@@ -25,31 +25,38 @@
*/
+#define _GNU_SOURCE
+
#include <stdio.h>
+#include <stdarg.h>
#include <string.h>
+#include <ctype.h>
#include <stdlib.h>
+#include <search.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
-#define _GNU_SOURCE
#include <getopt.h>
#include <signal.h>
#include "drbdadm.h"
-// basic format
-#define INDENT " "
-#define FMT INDENT "%-14s"
-#define BFMT INDENT FMT "\n"
-// assignment format
-#define AFMT0 FMT INDENT " = %s\n"
-#define AFMT INDENT FMT " = %s\n"
-
+static int indent = 0;
+#define INDENT_WIDTH 4
+#define BFMT "%s;\n"
+#define IPFMT "%-16s %s:%s;\n"
+#define MDISK "%-16s %s [%s];\n"
+#define printI(fmt, args... ) printf("%*s" fmt,INDENT_WIDTH * indent,"" , ## args )
+#define printA(name, val ) \
+ printf("%*s%*s %3s;\n", \
+ INDENT_WIDTH * indent,"" , \
+ -24+INDENT_WIDTH * indent, \
+ name, val )
-char* basename;
+char* progname;
struct adm_cmd {
const char* name;
@@ -78,7 +85,9 @@
static int sh_md_idx(struct d_resource* ,char* );
char ss_buffer[255];
+struct utsname nodeinfo;
int line=1;
+int fline, c_resource_start;
struct d_globals global_options = { 0, 0 };
char *config_file = NULL;
struct d_resource* config = NULL;
@@ -127,9 +136,23 @@
static char* esc(char* str)
{
static char buffer[1024];
+ char *ue = str, *e = buffer;
- if(strchr(str,' ')) {
- snprintf(buffer,1024,"\"%s\"",str);
+ if (!str || !str[0]) {
+ return "\"\"";
+ }
+ if(strchr(str,' ')||strchr(str,'\t')||strchr(str,'\\')) {
+ *e++ = '"';
+ while(*ue) {
+ if (*ue == '"' || *ue == '\\') {
+ *e++ = '\\';
+ }
+ if (e-buffer >= 1022) { fprintf(stderr,"string too long.\n"); exit(E_syntax); }
+ *e++ = *ue++;
+ if (e-buffer >= 1022) { fprintf(stderr,"string too long.\n"); exit(E_syntax); }
+ }
+ *e++ = '"';
+ *e++ = '\0';
return buffer;
}
return str;
@@ -139,58 +162,60 @@
{
if(!opts) return;
- printf(INDENT "%s {\n",name);
+ printI("%s {\n",name); ++indent;
while(opts) {
- if(opts->value) printf(AFMT,opts->name,opts->value);
- else printf(BFMT,opts->name);
+ if(opts->value) printA(opts->name,opts->value);
+ else printI(BFMT,opts->name);
opts=opts->next;
}
- printf(INDENT "}\n");
+ --indent;
+ printI("}\n");
}
static void dump_global_info()
{
if (global_options.minor_count || global_options.disable_io_hints)
{
- printf("global {\n");
+ printI("global {\n"); ++indent;
if (global_options.disable_io_hints)
- printf(INDENT "disable_io_hints\n");
+ printI("disable_io_hints;\n");
if (global_options.minor_count)
- printf(INDENT "minor_count = %i\n", global_options.minor_count);
- printf("}\n\n");
+ printI("minor_count = %i;\n", global_options.minor_count);
+ --indent; printI("}\n\n");
}
}
static void dump_host_info(struct d_host_info* hi)
{
if(!hi) {
- printf(" # No host section data available.\n");
+ printI(" # No host section data available.\n");
return;
}
- printf(INDENT "on %s {\n",esc(hi->name));
- printf(AFMT, "device" , esc(hi->device));
- printf(AFMT, "disk" , esc(hi->disk));
- printf(AFMT, "address" , hi->address);
- printf(AFMT, "port" , hi->port);
- printf(AFMT, "meta-disk" , esc(hi->meta_disk));
- printf(AFMT, "meta-index", esc(hi->meta_index));
- printf(INDENT "}\n");
+ printI("on %s {\n",esc(hi->name)); ++indent;
+ printA("device", esc(hi->device));
+ printA("disk" , esc(hi->disk));
+ printI(IPFMT,"address" , hi->address, hi->port);
+ if (!strcmp(hi->meta_index,"-1"))
+ printA("meta-disk", "internal");
+ else
+ printI(MDISK,"meta-disk", esc(hi->meta_disk), hi->meta_index);
+ --indent; printI("}\n");
}
static int adm_dump(struct d_resource* res,char* unused)
{
- printf("resource %s {\n",esc(res->name));
- printf(AFMT0,"protocol",res->protocol);
+ printI("resource %s {\n",esc(res->name)); ++indent;
+ printA("protocol",res->protocol);
if(res->ind_cmd)
- printf(AFMT0,"incon-degr-cmd",esc(res->ind_cmd));
+ printA("incon-degr-cmd",esc(res->ind_cmd));
dump_host_info(res->me);
- dump_host_info(res->partner);
+ dump_host_info(res->peer);
dump_options("net",res->net_options);
dump_options("disk",res->disk_options);
dump_options("syncer",res->sync_options);
dump_options("startup",res->startup_options);
- printf("}\n\n");
+ --indent; printf("}\n\n");
return 0;
}
@@ -219,7 +244,7 @@
if(strcmp("internal",res->me->meta_disk)==0) r = res->me->disk;
else r = res->me->meta_disk;
-
+
printf("%s\n",r);
return 0;
@@ -275,7 +300,7 @@
free(f->protocol);
free(f->ind_cmd);
free_host_info(f->me);
- free_host_info(f->partner);
+ free_host_info(f->peer);
free_options(f->net_options);
free_options(f->disk_options);
free_options(f->sync_options);
@@ -299,7 +324,7 @@
}
fprintf(stderr,"Can not find drbdsetup");
- exit(20);
+ exit(E_exec_error);
}
static void alarm_handler(int signo)
@@ -331,12 +356,12 @@
pid = fork();
if(pid == -1) {
fprintf(stderr,"Can not fork");
- exit(20);
+ exit(E_exec_error);
}
if(pid == 0) {
execv(argv[0],argv);
fprintf(stderr,"Can not exec");
- exit(20);
+ exit(E_exec_error);
}
if( !may_sleep ) {
@@ -350,10 +375,10 @@
if (errno != EINTR) break;
if (alarm_raised) {
fprintf(stderr,"Child process does not terminate!\nExiting.\n");
- exit(20);
+ exit(E_exec_error);
} else {
fprintf(stderr,"logic bug in %s:%d\n",__FILE__,__LINE__);
- exit(20);
+ exit(E_exec_error);
}
} else {
if(WIFEXITED(status)) {
@@ -385,7 +410,7 @@
while(OPT) { \
if (argc>=20) {\
fprintf(stderr,"logic bug in %s:%d\n",__FILE__,__LINE__); \
- exit(20); \
+ exit(E_thinko); \
} \
if(OPT->value) { \
ssprintf(argv[argc++],"--%s=%s",OPT->name,OPT->value); \
@@ -468,7 +493,7 @@
argv[argc++]=res->me->device;
argv[argc++]="net";
ssprintf(argv[argc++],"%s:%s",res->me->address,res->me->port);
- ssprintf(argv[argc++],"%s:%s",res->partner->address,res->partner->port);
+ ssprintf(argv[argc++],"%s:%s",res->peer->address,res->peer->port);
argv[argc++]=res->protocol;
opt=res->net_options;
make_options(opt);
@@ -544,7 +569,7 @@
printf("\nUSAGE: %s [OPTION...] [-- DRBDSETUP-OPTION...] COMMAND "
"{all|RESOURCE...}\n\n"
- "OPTIONS:\n",basename);
+ "OPTIONS:\n",progname);
opt=admopt;
while(opt->name) {
@@ -568,7 +593,98 @@
printf("\nVersion: "REL_VERSION" (api:%d)\n",API_VERSION);
- exit(20);
+ exit(E_usage);
+}
+
+int m_shell_match(const char *subcmd, const char *pattern)
+{
+ int ex, pid;
+ char *cmd = NULL;
+
+#ifdef DEBUG
+ ex = asprintf(&cmd, "[[ `%s` == %s ]]", subcmd, pattern);
+#else
+ ex = asprintf(&cmd, "[[ `%s` == %s ]] &>/dev/null", subcmd, pattern);
+#endif
+ if (ex < 0) { perror("asprintf"); exit(E_thinko); }
+
+ pid = fork();
+ if (pid == -1) { fprintf(stderr, "Can not fork"); exit(E_exec_error); }
+ if (pid == 0) {
+ execl("/bin/bash", progname,
+#ifdef DEBUG
+ "-vxc",
+#else
+ "-c",
+#endif
+ cmd, NULL);
+ fprintf(stderr, "Can not exec");
+ exit(E_exec_error);
+ }
+ waitpid(pid, &ex, 0);
+ free(cmd);
+ return ex;
+}
+
+/* if not verifyable, prints a message to stderr,
+ * and sets config_valid = 0 if INVALID_IP_IS_INVALID_CONF is defined */
+void verify_ips(struct d_resource* res)
+{
+ char *cmd = NULL;
+ char *pat = NULL;
+ char *my_ip = NULL;
+ char *his_ip = NULL;
+ int ex;
+
+ if (!(res && res->me && res->me->address
+ && res->peer && res->peer->address)) {
+ fprintf(stderr, "OOPS, no resource info in verify_ips!\n");
+ exit(E_config_invalid);
+ }
+ my_ip = res->me->address;
+ his_ip = res->peer->address;
+ ex = asprintf(&cmd, "/sbin/ip -o addr show scope global to %s", my_ip);
+ if (ex < 0) { perror("asprintf"); exit(E_thinko); }
+ ex = asprintf(&pat, "*inet\\ %s/*", my_ip);
+ if (ex < 0) { perror("asprintf"); exit(E_thinko); }
+ ex = m_shell_match(cmd, pat);
+ free(cmd); cmd = NULL;
+ free(pat); pat = NULL;
+ if (ex != 0) {
+ ENTRY e, *ep;
+ e.key = e.data = ep = NULL;
+ asprintf(&e.key,"%s:%s",my_ip,res->me->port);
+ ep = hsearch(e, FIND);
+ fprintf(stderr, "%s:%d: in resource %s, on %s:\n\t"
+ "IP %s not found on this host.\n",
+ config_file,(int) ep->data,res->name, res->me->name,my_ip);
+#ifdef INVALID_IP_IS_INVALID_CONF
+ config_valid = 0;
+#endif
+ free(e.key);
+ return;
+ }
+ asprintf(&cmd, "/sbin/ip -o route get to %s", his_ip);
+ if (ex < 0) { perror("asprintf"); exit(E_thinko); }
+ asprintf(&pat, "%s\\ dev*src\\ %s\\ \\\\*", his_ip, my_ip);
+ if (ex < 0) { perror("asprintf"); exit(E_thinko); }
+ ex = m_shell_match(cmd, pat);
+ free(cmd); cmd = NULL;
+ free(pat); pat = NULL;
+ if (ex != 0) {
+ ENTRY e, *ep;
+ e.key = e.data = ep = NULL;
+ asprintf(&e.key,"%s:%s",his_ip,res->peer->port);
+ ep = hsearch(e, FIND);
+ fprintf(stderr, "%s:%d: in resource %s:\n\tNo route from me (%s) to peer (%s).\n",
+ config_file,(int) ep->data,res->name, my_ip, his_ip);
+#ifdef INVALID_IP_IS_INVALID_CONF
+ config_valid = 0;
+#endif
+ return;
+ }
+
+ return;
}
static char* conf_file[] = {
@@ -577,6 +693,86 @@
0
};
+/* FIXME
+ * strictly speaking we don't need to check for uniqueness of disk and device names,
+ * but for uniqueness of their major:minor numbers ;-)
+ */
+
+int check_uniq(const char* what, const char *fmt, ...)
+{
+ va_list ap;
+ int rv;
+ ENTRY e, *ep;
+ e.key = e.data = ep = NULL;
+
+ va_start(ap, fmt);
+ rv=vasprintf(&e.key,fmt,ap);
+ va_end(ap);
+
+ if (rv < 0) { perror("vasprintf"); exit(E_thinko); }
+
+#ifdef EXIT_ON_CONFLICT
+ if (!what) {
+ fprintf(stderr,"Oops, unset argument in %s:%d.\n", __FILE__ , __LINE__ );
+ exit(E_thinko);
+ }
+#endif
+ e.data = (void*)fline;
+ ep = hsearch(e, FIND);
+ // fprintf(stderr,"%s: FIND %s: %p\n",res->name,e.key,ep);
+ if (ep) {
+ if (what) {
+ fprintf(stderr,
+ "%s:%d: conflicting use of %s '%s' ...\n"
+ "%s:%d: %s '%s' first used here.\n",
+ config_file, line, what, ep->key,
+ config_file, (int) ep->data, what, ep->key );
+ }
+ free(e.key);
+ config_valid = 0;
+ } else {
+ ep = hsearch(e, ENTER);
+ // fprintf(stderr,"%s: ENTER %s as %s: %p\n",res->name,e.key,ep->key,ep);
+ if (!ep) {
+ fprintf(stderr, "entry failed.\n");
+ exit(E_thinko);
+ }
+ ep = NULL;
+ }
+#ifdef EXIT_ON_CONFLICT
+ if (ep) exit(E_config_invalid);
+#endif
+ return !ep;
+}
+
+void validate_resource(struct d_resource * res)
+{
+ if (!res->protocol) {
+ fprintf(stderr,
+ "%s:%d: in resource %s:\n\tprotocol definition missing.\n",
+ config_file, c_resource_start, res->name);
+ config_valid = 0;
+ } else {
+ res->protocol[0] = toupper(res->protocol[0]);
+ }
+ if (!res->me) {
+ fprintf(stderr,
+ "%s:%d: in resource %s:\n\tmissing section 'on %s { ... }'.\n",
+ config_file, c_resource_start, res->name, nodeinfo.nodename);
+ config_valid = 0;
+ }
+ if (!res->peer) {
+ fprintf(stderr,
+ "%s:%d: in resource %s:\n\t"
+ "missing section 'on <PEER> { ... }'.\n",
+ config_file, c_resource_start, res->name);
+ config_valid = 0;
+ }
+ if (res->me && res->peer)
+ verify_ips(res);
+}
+
+
int main(int argc, char** argv)
{
int i,rv;
@@ -586,11 +782,12 @@
drbdsetup=NULL;
dry_run=0;
yyin=NULL;
+ uname(&nodeinfo); /* FIXME maybe fold to lower case ? */
- if( (basename=strrchr(argv[0],'/')) )
- argv[0] = ++basename;
+ if( (progname=strrchr(argv[0],'/')) )
+ argv[0] = ++progname;
else
- basename=argv[0];
+ progname=argv[0];
if(argc == 1) print_usage(); // arguments missing.
opterr=1;
@@ -614,7 +811,7 @@
yyin=fopen(optarg,"r");
if(!yyin) {
fprintf(stderr,"Can not open '%s'.\n.",optarg);
- exit(20);
+ exit(E_exec_error);
}
ssprintf(config_file,"%s",optarg);
}
@@ -653,7 +850,7 @@
if(cmd==NULL) {
fprintf(stderr,"Unknown command '%s'.\n",argv[optind]);
- exit(20);
+ exit(E_usage);
}
optind++;
@@ -672,28 +869,32 @@
} while (conf_file[++i]);
}
if(!config_file) {
- exit(20);
+ exit(E_config_invalid);
}
- yyparse();
+ /*
+ * for check_uniq: check uniqueness of
+ * resource names, ip:port, node:disk and node:device combinations
+ * as well as resource:section ...
+ * hash table to test for uniqness of these values...
+ * 256 (max minors)
+ * *(
+ * 2 (host sections) * 4 (res ip:port node:disk node:device)
+ * + 4 (other sections)
+ * + some more,
+ * if we want to check for scoped uniqueness of *every* option
+ * )
+ * since nobody (?) will actually use more than a dozend minors,
+ * this should be more than enough.
+ */
+ if (!hcreate(256*((2*4)+4))) {
+ fprintf(stderr,"Insufficient memory.\n");
+ exit(E_exec_error);
+ };
- { // check uniqueness of resource names.
- struct d_resource *res2,*tmp2;
- char *name;
-
- for_each_resource(res,tmp,config) {
- name = res->name;
- for_each_resource(res2,tmp2,config) {
- if( res != res2 && !strcmp(res2->name, name) ) {
- fprintf(stderr,"Multiple definitions of resource '%s' found.\n",
- name);
- exit(10);
- }
- }
- }
- }
+ yyparse();
- if(!config_valid) exit(10);
+ if(!config_valid) exit(E_config_invalid);
{
int mc=global_options.minor_count;
@@ -703,7 +904,7 @@
if( mc && mc<nr_resources ) {
fprintf(stderr,"You have %d resources but a minor_count of %d in your"
" config!\n",nr_resources,mc);
- exit(20);
+ exit(E_usage);
}
}
@@ -721,7 +922,7 @@
for_each_resource(res,tmp,config) {
if( (rv=cmd->function(res,cmd->arg)) ) {
fprintf(stderr,"drbdsetup exited with code %d\n",rv);
- exit(20);
+ exit(E_exec_error);
}
}
} else {
@@ -731,18 +932,18 @@
if(!strcmp(argv[i],res->name)) goto found;
}
fprintf(stderr,"'%s' not defined in your config.\n",argv[i]);
- exit(20);
+ exit(E_usage);
found:
if( (rv=cmd->function(res,cmd->arg)) ) {
fprintf(stderr,"drbdsetup exited with code %d\n",rv);
- exit(20);
+ exit(E_exec_error);
}
}
}
- } else { // Commands which does not need a resource name
+ } else { // Commands which do not need a resource name
if( (rv=cmd->function(config,cmd->arg)) ) {
fprintf(stderr,"drbdsetup exited with code %d\n",rv);
- exit(20);
+ exit(E_exec_error);
}
}
@@ -754,5 +955,5 @@
void yyerror(char* text)
{
fprintf(stderr,"%s:%d: %s\n",config_file,line,text);
- exit(20);
+ exit(E_syntax);
}
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/user/Attic/drbdadm_parser.y,v
retrieving revision 1.1.2.21
retrieving revision 1.1.2.22
diff -u -3 -r1.1.2.21 -r1.1.2.22
--- drbdadm_parser.y 5 Apr 2004 11:47:01 -0000 1.1.2.21
+++ drbdadm_parser.y 26 Apr 2004 08:36:29 -0000 1.1.2.22
@@ -1,5 +1,4 @@
%{
-#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
@@ -8,28 +7,31 @@
#include "drbdadm.h"
extern void yyerror(char* text);
-extern int yylex();
+extern int yylex(void);
-#define APPEND(LIST,ITEM) ({ \
- typeof((LIST)) _l = (LIST); \
- typeof((ITEM)) _i = (ITEM); \
- typeof((ITEM)) _t; \
- _i->next = NULL; \
- if (_l == NULL) { _l = _i; } \
- else { \
+#define APPEND(LIST,ITEM) ({ \
+ typeof((LIST)) _l = (LIST); \
+ typeof((ITEM)) _i = (ITEM); \
+ typeof((ITEM)) _t; \
+ _i->next = NULL; \
+ if (_l == NULL) { _l = _i; } \
+ else { \
for (_t = _l; _t->next; _t = _t->next); \
- _t->next = _i; \
- }; \
- _l; \
+ _t->next = _i; \
+ }; \
+ _l; \
})
static struct d_resource* c_res;
static struct d_host_info* c_host;
+static char* c_hostname;
+static int c_section_start, n_hosts;
static struct d_option* new_opt(char* name,char* value)
{
struct d_option* cn = malloc(sizeof(struct d_option));
+ /* fprintf(stderr,"%s:%d: %s = %s\n",config_file,line,name,value); */
cn->name=name;
cn->value=value;
cn->mentioned=0;
@@ -40,46 +42,33 @@
static void derror(char* text)
{
config_valid=0;
- fprintf(stderr,
- "%s:%d:\n\t'%s' keyword missing from host section ending here.\n"
- "\t(Host sections are those beginning with the 'on' keyword)\n\n",
- config_file,line,text);
+ fprintf(stderr, "%s:%d: in resource %s, on %s { ... }:"
+ " '%s' keyword missing.\n",
+ config_file,c_section_start,c_res->name,c_hostname,text);
}
-static void derror2(char* text)
+static void host_sec(char *name)
{
- config_valid=0;
- fprintf(stderr,
- "%s:%d:\n\t%s\n\tDetected at host section ending here.\n"
- "\t(Host sections are those beginning with the 'on' keyword)\n\n",
- config_file,line,text);
-}
-
-static void host_sec(char* name)
-{
- char hostname[255];
-
- gethostname(hostname,255);
-
- c_host->name=name;
- if(c_host->device==0) derror("device");
- if(c_host->disk==0) derror("disk");
- if(c_host->address==0) derror("address");
- if(c_host->port==0) derror("port");
- if(c_host->meta_disk==0) derror("meta-disk");
- if(c_host->meta_disk) {
- if( !strcmp(c_host->meta_disk,"internal") && c_host->meta_index==0)
- c_host->meta_index=strdup("-1");
- }
- if(c_host->meta_index==0) derror("meta-index");
+ c_host->name = name;
+ if (!c_host->device) derror("device");
+ if (!c_host->disk) derror("disk");
+ if (!c_host->address) derror("address");
+ if (!c_host->meta_disk) derror("meta-disk");
- if(strcmp(name,hostname)==0) {
- if(c_res->me) derror2("Thre are multiple host sections for this host.");
+ if (strcmp(name, nodeinfo.nodename) == 0) {
+ // if (c_res->me) error(...); -- already done by check_uniq in the rules.
c_res->me = c_host;
} else {
- if(c_res->partner) derror2("There are multiple host sections for the peer."
- "\n\t(Maybe misspelled local host name?)");
- c_res->partner = c_host;
+ if (c_res->peer) {
+ config_valid = 0;
+ fprintf(stderr,
+ "%s:%d: in resource %s, on %s { ... } ... on %s { ... }:\n"
+ "\tThere are multiple host sections for the peer.\n"
+ "\tMaybe misspelled local host name '%s'?\n",
+ config_file, c_section_start, c_res->name,
+ c_res->peer->name, c_hostname, nodeinfo.nodename);
+ }
+ c_res->peer = c_host;
}
}
@@ -93,6 +82,30 @@
return res;
}
+void check_meta_disk()
+{
+ if (strcmp(c_host->meta_disk, "internal")) {
+ if (c_host->meta_index == NULL) {
+ fprintf(stderr, "%s:%d: expected 'meta-disk = %s [index]'.\n",
+ config_file, fline, c_host->meta_disk);
+ }
+ check_uniq("meta-disk", "%s:%s[%s]", c_hostname,
+ c_host->meta_disk, c_host->meta_index);
+ } else if (c_host->meta_index) {
+ fprintf(stderr,
+ "%s:%d: no index allowed with 'meta-disk = internal'.\n",
+ config_file, fline);
+ } else {
+ c_host->meta_index = strdup("-1");
+ }
+}
+
+#define CHKU(what,val) \
+ c_host->what = val; \
+ check_uniq( #what, "%s:%s",c_hostname,val)
+
+#define CHKS(sname) \
+ check_uniq(sname " section","%s:" sname, c_res->name)
%}
%union {
@@ -101,117 +114,159 @@
struct d_resource* d_resource;
}
-%token TK_RESOURCE TK_DISK TK_NET TK_SYNCER TK_ON
-%token TK_PORT TK_DEVICE TK_ADDRESS TK_GLOBAL TK_STARTUP
-%token TK_META_DISK TK_META_INDEX
-%token <txt> TK_PROTOCOL TK_ON_IO_ERROR
-%token <txt> TK_SIZE TK_TIMEOUT TK_CONNECT_INT
-%token <txt> TK_RATE TK_USE_CSUMS TK_SKIP_SYNC TK_PING_INT
-%token <txt> TK_INTEGER TK_STRING TK_IPADDR TK_INCON_DEGR_CMD
-%token <txt> TK_DISABLE_IO_HINTS TK_MINOR_COUNT
+%token TK_GLOBAL TK_RESOURCE
+%token TK_ON TK_NET TK_DISK_S TK_SYNCER TK_STARTUP
+%token TK_MINOR_COUNT TK_DISABLE_IO_HINTS
+%token TK_PROTOCOL TK_INCON_DEGR_CMD
+%token TK_ADDRESS TK_DISK TK_DEVICE TK_META_DISK
+%token <txt> TK_INTEGER TK_STRING
+%token <txt> TK_ON_IO_ERROR TK_SIZE
+%token <txt> TK_TIMEOUT TK_CONNECT_INT TK_PING_INT TK_MAX_BUFFERS TK_IPADDR
+%token <txt> TK_MAX_EPOCH_SIZE TK_SNDBUF_SIZE
+%token <txt> TK_SKIP_SYNC TK_USE_CSUMS TK_RATE TK_SYNC_GROUP TK_AL_EXTENTS
%token <txt> TK_WFC_TIMEOUT TK_DEGR_WFC_TIMEOUT
-%token <txt> TK_MAX_BUFFERS TK_MAX_EPOCH_SIZE
-%token <txt> TK_SNDBUF_SIZE TK_SYNC_GROUP TK_AL_EXTENTS
-%token <txt> TK_SINTEGER
+
+%type <txt> hostname resource_name
%type <d_option> disk_stmts disk_stmt
%type <d_option> net_stmts net_stmt
%type <d_option> sync_stmts sync_stmt
%type <d_option> startup_stmts startup_stmt
%type <d_resource> resources resource
-%type <txt> signed_int
%%
-config: global_sec resources { config=$2; }
+config: global_sec resources { config=$2; }
;
-global_sec: /* empty */
- | TK_GLOBAL '{' glob_stmts '}'
+global_sec: /* empty */
+ | TK_GLOBAL glob_stmts
;
-glob_stmts: /* empty */
+glob_stmts: /* empty */
| glob_stmts glob_stmt
;
-glob_stmt: TK_DISABLE_IO_HINTS { global_options.disable_io_hints=1; }
- | TK_MINOR_COUNT '=' TK_INTEGER { global_options.minor_count=atoi($3); }
- ;
+glob_stmt: TK_DISABLE_IO_HINTS
+ { global_options.disable_io_hints=1; }
+ | TK_MINOR_COUNT TK_INTEGER
+ { global_options.minor_count=atoi($2); }
+ ;
+
+resources: /* empty */ { $$ = 0; }
+ | resources resource { $$=APPEND($1,$2); }
+ ;
-resources: /* empty */ { $$ = 0; }
- | resources resource { $$=APPEND($1,$2); }
+resource: TK_RESOURCE { n_hosts = 0; } resource_name res_stmts
+ { $$ = c_res; validate_resource(c_res); }
;
-resource: TK_RESOURCE TK_STRING { c_res = new_resource($2); }
- '{' res_stmts '}' { $$ = c_res; }
+resource_name: TK_STRING
+ {
+ int uniq;
+ c_resource_start = line;
+ c_res = new_resource($1);
+ uniq = check_uniq("resource","%s",$1);
+ if (!uniq) exit(E_config_invalid);
+ }
;
-res_stmts: /* empty */
+res_stmts: /* empty */
| res_stmts res_stmt
| res_stmts section
;
-res_stmt: TK_PROTOCOL '=' TK_STRING { c_res->protocol=$3; }
- | TK_INCON_DEGR_CMD '=' TK_STRING { c_res->ind_cmd=$3; }
+res_stmt: TK_PROTOCOL TK_STRING { c_res->protocol=$2; }
+ | TK_INCON_DEGR_CMD TK_STRING { c_res->ind_cmd=$2; }
;
-section: TK_DISK '{' disk_stmts '}' { c_res->disk_options=$3; }
- | TK_NET '{' net_stmts '}' { c_res->net_options=$3; }
- | TK_ON TK_STRING '{' host_stmts '}' { host_sec($2); }
- | TK_SYNCER '{' sync_stmts '}' { c_res->sync_options=$3; }
- | TK_STARTUP '{' startup_stmts '}' {c_res->startup_options=$3;}
+section: TK_DISK_S disk_stmts
+ { CHKS("disk"); c_res->disk_options=$2; }
+ | TK_NET net_stmts
+ { CHKS("net"); c_res->net_options=$2; }
+ | TK_SYNCER sync_stmts
+ { CHKS("syncer"); c_res->sync_options=$2; }
+ | TK_STARTUP startup_stmts
+ { CHKS("startup"); c_res->startup_options=$2; }
+ | TK_ON hostname host_stmts { host_sec($2); }
;
-disk_stmts: /* empty */ { $$ = 0; }
- | disk_stmts disk_stmt { $$=APPEND($1,$2); }
+hostname: TK_STRING
+ {
+ int uniq;
+ c_section_start = line;
+ c_hostname = $1;
+ uniq = check_uniq("host section", "%s: on %s",
+ c_res->name, c_hostname);
+ if (!uniq)
+ exit(E_config_invalid);
+ if (++n_hosts > 2) {
+ fprintf(stderr,
+ "%s:%d: in resource %s, "
+ "unsupported third host section on %s { ... }.\n",
+ config_file, c_section_start, c_res->name,
+ c_hostname);
+ exit(E_config_invalid);
+ }
+ }
;
-disk_stmt: TK_ON_IO_ERROR '=' TK_STRING { $$=new_opt($1,$3); }
- | TK_SIZE '=' TK_INTEGER { $$=new_opt($1,$3); }
+disk_stmts: /* empty */ { $$ = 0; }
+ | disk_stmts disk_stmt { $$=APPEND($1,$2); }
;
-net_stmts: /* empty */ { $$ = 0; }
- | net_stmts net_stmt { $$=APPEND($1,$2); }
+disk_stmt: TK_ON_IO_ERROR TK_STRING { $$=new_opt($1,$2); }
+ | TK_SIZE TK_INTEGER { $$=new_opt($1,$2); }
;
-net_stmt: TK_TIMEOUT '=' TK_INTEGER { $$=new_opt($1,$3); }
- | TK_CONNECT_INT '=' TK_INTEGER { $$=new_opt($1,$3); }
- | TK_PING_INT '=' TK_INTEGER { $$=new_opt($1,$3); }
- | TK_MAX_BUFFERS '=' TK_INTEGER { $$=new_opt($1,$3); }
- | TK_MAX_EPOCH_SIZE '=' TK_INTEGER { $$=new_opt($1,$3); }
- | TK_SNDBUF_SIZE '=' TK_INTEGER { $$=new_opt($1,$3); }
+net_stmts: /* empty */ { $$ = 0; }
+ | net_stmts net_stmt { $$=APPEND($1,$2); }
;
-sync_stmts: /* empty */ { $$ = 0; }
- | sync_stmts sync_stmt { $$=APPEND($1,$2); }
+net_stmt: TK_TIMEOUT TK_INTEGER { $$=new_opt($1,$2); }
+ | TK_CONNECT_INT TK_INTEGER { $$=new_opt($1,$2); }
+ | TK_PING_INT TK_INTEGER { $$=new_opt($1,$2); }
+ | TK_MAX_BUFFERS TK_INTEGER { $$=new_opt($1,$2); }
+ | TK_MAX_EPOCH_SIZE TK_INTEGER { $$=new_opt($1,$2); }
+ | TK_SNDBUF_SIZE TK_INTEGER { $$=new_opt($1,$2); }
;
-sync_stmt: TK_SKIP_SYNC { $$=new_opt($1,0); }
- | TK_USE_CSUMS { $$=new_opt($1,0); }
- | TK_RATE '=' TK_INTEGER { $$=new_opt($1,$3); }
- | TK_SYNC_GROUP '=' TK_INTEGER { $$=new_opt($1,$3); }
- | TK_AL_EXTENTS '=' TK_INTEGER { $$=new_opt($1,$3); }
+sync_stmts: /* empty */ { $$ = 0; }
+ | sync_stmts sync_stmt { $$=APPEND($1,$2); }
;
-host_stmts: /* empty */ { c_host=calloc(1,sizeof(struct d_host_info)); }
+sync_stmt: TK_SKIP_SYNC { $$=new_opt($1,0); }
+ | TK_USE_CSUMS { $$=new_opt($1,0); }
+ | TK_RATE TK_INTEGER { $$=new_opt($1,$2); }
+ | TK_SYNC_GROUP TK_INTEGER { $$=new_opt($1,$2); }
+ | TK_AL_EXTENTS TK_INTEGER { $$=new_opt($1,$2); }
+ ;
+
+host_stmts: /* empty */ { c_host=calloc(1,sizeof(struct d_host_info)); }
| host_stmts host_stmt
;
-host_stmt: TK_DISK '=' TK_STRING { c_host->disk=$3; }
- | TK_DEVICE '=' TK_STRING { c_host->device=$3; }
- | TK_ADDRESS '=' TK_IPADDR { c_host->address=$3; }
- | TK_PORT '=' TK_INTEGER { c_host->port=$3; }
- | TK_META_DISK '=' TK_STRING { c_host->meta_disk=$3; }
- | TK_META_INDEX '=' signed_int { c_host->meta_index=$3; }
+host_stmt: TK_DISK TK_STRING { CHKU(disk,$2); }
+ | TK_DEVICE TK_STRING { CHKU(device,$2); }
+ | TK_ADDRESS ip_and_port
+ { check_uniq("IP","%s:%s", c_host->address,c_host->port); }
+ | TK_META_DISK meta_disk_and_index { check_meta_disk(); }
;
-signed_int: TK_SINTEGER
- | TK_INTEGER
- ;
-startup_stmts: /* empty */ { $$ = 0; }
+ip_and_port: TK_IPADDR TK_INTEGER
+ { c_host->address=$1; c_host->port = $2; }
+ ;
+
+meta_disk_and_index:
+ TK_STRING TK_INTEGER
+ { c_host->meta_disk = $1; c_host->meta_index = $2; }
+ | TK_STRING { c_host->meta_disk = $1; }
+ ;
+
+startup_stmts: /* empty */ { $$ = 0; }
| startup_stmts startup_stmt { $$=APPEND($1,$2); }
;
-startup_stmt: TK_WFC_TIMEOUT '=' TK_INTEGER { $$=new_opt($1,$3); }
- | TK_DEGR_WFC_TIMEOUT '=' TK_INTEGER { $$=new_opt($1,$3); }
+startup_stmt: TK_WFC_TIMEOUT TK_INTEGER { $$=new_opt($1,$2); }
+ | TK_DEGR_WFC_TIMEOUT TK_INTEGER { $$=new_opt($1,$2); }
;
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/user/Attic/drbdadm_scanner.fl,v
retrieving revision 1.1.2.20
retrieving revision 1.1.2.21
diff -u -3 -r1.1.2.20 -r1.1.2.21
--- drbdadm_scanner.fl 11 Feb 2004 13:25:20 -0000 1.1.2.20
+++ drbdadm_scanner.fl 26 Apr 2004 08:36:29 -0000 1.1.2.21
@@ -1,87 +1,382 @@
%{
-#include <stdio.h>
-#include <stdlib.h>
+/*
+*/
+
#include <string.h>
-#include "drbdadm_parser.h"
+#include <ctype.h>
#include "drbdadm.h"
+#include "drbdadm_parser.h"
-void syntax_error(char*);
-
-#if 0
-#define DP printf("'%s' ",yytext)
-#else
-#define DP
-#endif
-
-#define CP yylval.txt = strdup(yytext)
+static void update_lcnt(void);
+static void section(int);
+static void named_section(int);
+static void do_assign(int);
+static void unescape(void);
+static void unescape_midx(void);
+/* static char* const escape(char* const str); */
+static void syntax_error(char*);
+static void expect_error(char*);
+
+#define CP yylval.txt = strdup(yytext);
+
+#define YY_NO_UNPUT
+static int yy_top_state(void) __attribute((unused)); /* no unused warning */
+
+#define PRINTF(fmt, args...) \
+ fprintf(stderr, "%s:%d: " fmt, config_file, line , ## args )
+
+/* This is an "unusual" scanner. If someone tells me how to do this in
+ * the parser instead, tell me. I just was not able to make the error
+ * handling of yacc do what I want.
+ * -- lge
+ */
+
+/*
+ * Philipp dislikes syntax diversity, and wants terminating semicolons.
+ * So I drop what I thought would be nice to have: plain English and
+ * punctuation...
+ASSIGN {LS}*[:=]{LS}*|{LS}(is{LS})?
+DISK disk|"on top of"
+IGNORE ({WSC}*(use|with)*)+
+NDELIM [^ \t\n#=:;{}]+
+*/
%}
%option noyywrap
+%option stack
-NUM [0-9][0-9]*[MKG]?
-SNUMB [0-9]{1,3}
-IPV4ADDR ({SNUMB}"."){3}{SNUMB}
-WS [ \t]
-OPCHAR [{}=]
-%x in_string id
+%x RESOURCE GLOBAL
+%x STARTUP DISK NET SYNCER HOST
+%x SEMICOLON ASSIGN NUM NUM_U NAME STRING PROTO IO_ERROR
+%x IP_AND_PORT PORT META_DISK META_IDX
+%x LS LBRACE IGNORE_SECTION
+
+LS [ \t]+
+WS [ \t\n]+
+COMMENT \#[^\n]*
+WSC ({WS}|{COMMENT}\n)+
+ASSIGN {LS}
+NUM [0-9]+
+NUM_U [0-9]+[kmgKMG]?
+NAME [/_.A-Za-z0-9-]+
+STRING ({NAME}|\"([^\"\\\n]*|\\.)*\")+
+USTRING \"([^\"\\\n]*|\\.)*
+DISK disk
+INTERN internal|\"internal\"
+META_IDX {LS}*\[{LS}*{NUM}{LS}*\]
+O_IDX {WSC}meta-index{ASSIGN}
+IGNORE {WSC}
+SKIP skip({LS}[^{\n]*)?
+NDELIM [^ \t\n#;{}]+
+_1_254 [1-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]|25[0-4]
+_0_255 0|[1-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]|25[0-5]
+IPV4ADDR {_1_254}\.{_0_255}\.{_0_255}\.{_1_254}
+PORT {WSC}port{ASSIGN}{NUM}
%%
-<in_string>[^\"]* { DP; CP; return TK_STRING; }
-<in_string>\" BEGIN(INITIAL);
-
-<id>\" BEGIN(in_string);
-<id>[a-zA-Z/][a-zA-Z0-9_/.-]* { DP; CP; BEGIN(INITIAL); return TK_STRING; }
-<id>[{}] { DP; BEGIN(INITIAL); return yytext[0]; }
-<id>= { DP; return yytext[0]; }
-<id>{WS}+ /* ignore whitespaces */
-
-\" BEGIN(in_string);
-\n { line++; }
-#[^\n]* /* ignore comments */
-{OPCHAR} { DP; return yytext[0]; }
-on { DP; BEGIN(id); return TK_ON; }
-net { DP; return TK_NET; }
-disk { DP; BEGIN(id); return TK_DISK; }
-port { DP; return TK_PORT; }
-syncer { DP; return TK_SYNCER; }
-device { DP; BEGIN(id); return TK_DEVICE; }
-global { DP; return TK_GLOBAL; }
-address { DP; return TK_ADDRESS; }
-startup { DP; return TK_STARTUP; }
-resource { DP; BEGIN(id); return TK_RESOURCE; }
-meta-disk { DP; BEGIN(id); return TK_META_DISK; }
-meta-index { DP; return TK_META_INDEX; }
-rate { DP; CP; return TK_RATE; }
-size { DP; CP; return TK_SIZE; }
-group { DP; CP; return TK_SYNC_GROUP; }
-timeout { DP; CP; return TK_TIMEOUT; }
-ping-int { DP; CP; return TK_PING_INT; }
-protocol { DP; CP; BEGIN(id); return TK_PROTOCOL;}
-on-io-error { DP; CP; BEGIN(id); return TK_ON_IO_ERROR;}
-use-csums { DP; CP; return TK_USE_CSUMS; }
-skip-sync { DP; CP; return TK_SKIP_SYNC; }
-al-extents { DP; CP; return TK_AL_EXTENTS; }
-minor_count { DP; CP; return TK_MINOR_COUNT; }
-connect-int { DP; CP; return TK_CONNECT_INT; }
-wfc-timeout { DP; CP; return TK_WFC_TIMEOUT; }
-max-buffers { DP; CP; return TK_MAX_BUFFERS; }
-incon-degr-cmd { DP; CP; return TK_INCON_DEGR_CMD; }
-max-epoch-size { DP; CP; return TK_MAX_EPOCH_SIZE; }
-sndbuf-size { DP; CP; return TK_SNDBUF_SIZE; }
-degr-wfc-timeout { DP; CP; return TK_DEGR_WFC_TIMEOUT; }
-disable_io_hints { DP; CP; return TK_DISABLE_IO_HINTS; }
-{IPV4ADDR} { DP; CP; return TK_IPADDR; }
-{NUM} { DP; CP; return TK_INTEGER; }
--{NUM} { DP; CP; return TK_SINTEGER; }
-{WS}+ /* ignore whitespaces */
-[^ \n\t={}"]+ { syntax_error(yytext); }
+<INITIAL,RESOURCE>{
+ {SKIP} section(IGNORE_SECTION);
+}
+
+<INITIAL>{
+ {COMMENT} /* discard last comment if no eol at eof */
+ {WSC} update_lcnt();
+ global section(GLOBAL); return TK_GLOBAL;
+ resource named_section(RESOURCE); return TK_RESOURCE;
+ \} syntax_error("unmached closing brace.");
+ {NDELIM} expect_error("one of 'global|resource'");
+}
+
+<RESOURCE,GLOBAL,IGNORE_SECTION,STARTUP,DISK,NET,SYNCER,HOST>{
+ {IGNORE} update_lcnt();
+ \} yy_pop_state();
+}
+
+<NAME>{
+ {NAME} yy_pop_state(); CP; return TK_STRING;
+ [^ \t\n#]+ expect_error("name"); /* not referenced currently */
+}
+
+<SEMICOLON>{
+ {LS} /* ignore */
+ ; yy_pop_state();
+ \n yy_pop_state(); PRINTF("missing ';'\n"); line++;
+ {NDELIM} expect_error("';'");
+}
+
+<ASSIGN>{
+ {ASSIGN} yy_pop_state(); fline = line;
+ = syntax_error("don't use '=' signs anymore!");
+ {WSC} syntax_error("linebreak between option and value not allowed.\n");
+ {NDELIM} expect_error("whitespace");
+}
+
+<NUM>{
+ {NUM} yy_pop_state(); CP; return TK_INTEGER;
+ {NDELIM} expect_error("integer"); yy_pop_state();
+}
+
+<NUM_U>{
+ {NUM_U} yy_pop_state(); CP; return TK_INTEGER;
+ {NDELIM} expect_error("[0-9]+[KMG]?"); yy_pop_state();
+}
+
+<STRING>{
+ {STRING} yy_pop_state(); unescape(); CP; return TK_STRING;
+ {USTRING} syntax_error("string terminator missing.\n");
+ {NDELIM} expect_error("string"); yy_pop_state();
+}
+
+<PROTO>{
+ \"[abcABC]\" yy_pop_state(); unescape(); CP; return TK_STRING;
+ [abcABC] yy_pop_state(); CP; return TK_STRING;
+ {NDELIM} expect_error("one of 'A|B|C'"); yy_pop_state();
+}
+
+<PORT>{
+ : BEGIN(NUM); /* this is only reached when I have a colon */
+ {WSC}port{ASSIGN} {
+ /* or a 'port = ' following the 'address = ' */
+ update_lcnt(); BEGIN(NUM);
+ PRINTF("'port=<port>' deprecated, "
+ "please use 'IP:port' instead.\n");
+ }
+}
+
+<IP_AND_PORT>{
+ {IPV4ADDR}/:{NUM} BEGIN(PORT); CP; return TK_IPADDR;
+ {IPV4ADDR}/{PORT} BEGIN(PORT); CP; return TK_IPADDR;
+ {IPV4ADDR} syntax_error("':PORT' missing from IP:PORT.\n");
+ \"{IPV4ADDR}[^ \t\n]+ syntax_error("please do not quote IP:PORT.\n");
+ [0-9.:]+ expect_error("valid IP");
+ {NDELIM} expect_error("IP and port 'XXX.XXX.XXX.XXX:PORT'");
+}
+
+<META_IDX>{
+ {META_IDX} unescape_midx(); yy_pop_state(); CP; return TK_INTEGER;
+ {O_IDX} {
+ update_lcnt(); BEGIN(NUM);
+ PRINTF("'meta-index=<idx>' deprecated, "
+ "please use 'meta-disk /di/sk [idx]' instead.\n");
+ }
+}
+
+<META_DISK>{
+ {INTERN} unescape(); yy_pop_state(); CP; return TK_STRING;
+ {INTERN}{META_IDX} |
+ {INTERN}{O_IDX} syntax_error("don't give an index for internal meta-data.");
+ {STRING}/{META_IDX} |
+ {STRING}/{O_IDX}{NUM} unescape(); BEGIN(META_IDX); CP; return TK_STRING;
+ {STRING}{LS}*{NDELIM} expect_error("meta-disk: index missing; either 'internal' or '/dev/ice/name [index]'");
+ {NDELIM} expect_error("either 'internal' or '/dev/ice/name [index]'");
+}
+
+<LS>{
+ {LS} update_lcnt(); yy_pop_state();
+ {NDELIM} expect_error("whitespace"); yy_pop_state();
+}
+
+<LBRACE>{
+ {WSC}*\{{WSC}* update_lcnt(); yy_pop_state();
+ {WSC}*[^{ \t\n]+ expect_error("'{'");
+}
+
+<IGNORE_SECTION>{
+ [^{}]+ update_lcnt(); /* no ECHO */
+ \{ yy_push_state(IGNORE_SECTION);
+}
+
+<GLOBAL>{
+ minor_count do_assign(NUM); CP; return TK_MINOR_COUNT;
+ disable_io_hints yy_push_state(SEMICOLON); return TK_DISABLE_IO_HINTS;
+ {NDELIM} expect_error("'minor_count|disable_io_hints'");
+}
+
+<RESOURCE>{
+ on named_section(HOST); return TK_ON;
+ startup section(STARTUP); return TK_STARTUP;
+ syncer section(SYNCER); return TK_SYNCER;
+ disk section(DISK); return TK_DISK_S;
+ net section(NET); return TK_NET;
+
+ protocol do_assign(PROTO); CP; return TK_PROTOCOL;
+ incon-degr-cmd do_assign(STRING); CP; return TK_INCON_DEGR_CMD;
+ {NDELIM} {
+ expect_error(
+ "one of 'protocol|incon-degr-cmd|"
+ "startup|disk|net|syncer|on <HOSTNAME>'");
+ }
+}
+
+<STARTUP>{
+ wfc-timeout do_assign(NUM); CP; return TK_WFC_TIMEOUT;
+ degr-wfc-timeout do_assign(NUM); CP; return TK_DEGR_WFC_TIMEOUT;
+ {NDELIM} expect_error("one of 'wfc-timeout|degr-wfc-timeout'");
+}
+
+<DISK>{
+ on-io-error do_assign(IO_ERROR); CP; return TK_ON_IO_ERROR;
+ {NDELIM} expect_error("'on-io-error'");
+}
+
+<IO_ERROR>{
+ pass_on |
+ panic |
+ detach yy_pop_state(); CP; return TK_STRING;
+ {NDELIM} expect_error("one of 'pass_on|panic|detach'");
+}
+
+
+<NET>{
+ sndbuf-size do_assign(NUM_U); CP; return TK_SNDBUF_SIZE;
+ timeout do_assign(NUM); CP; return TK_TIMEOUT;
+ ping-int do_assign(NUM); CP; return TK_PING_INT;
+ connect-int do_assign(NUM); CP; return TK_CONNECT_INT;
+ max-buffers do_assign(NUM); CP; return TK_MAX_BUFFERS;
+ max-epoch-size do_assign(NUM); CP; return TK_MAX_EPOCH_SIZE;
+ {NDELIM} expect_error("one of 'sndbuf-size|timeout|ping-int|connect-int|max-buffers|max-epoch-size'");
+}
+
+<SYNCER>{
+ rate do_assign(NUM_U); CP; return TK_RATE;
+ group do_assign(NUM); CP; return TK_SYNC_GROUP;
+ al-extents do_assign(NUM); CP; return TK_AL_EXTENTS;
+ {NDELIM} expect_error("one of 'rate|group|al-extents'");
+}
+
+<HOST>{
+ address do_assign(IP_AND_PORT); CP; return TK_ADDRESS;
+ device do_assign(STRING); CP; return TK_DEVICE;
+ {DISK} do_assign(STRING); CP; return TK_DISK;
+ meta-disk do_assign(META_DISK); CP; return TK_META_DISK;
+ {NDELIM} expect_error("one of 'address|device|disk|meta-disk'");
+}
+
+<*>{
+ \{ syntax_error("unexpected opening brace.");
+ \n syntax_error("unexpected end of line, maybe missing ';' ? ");
+ . expect_error("something else");
+ <<EOF>> {
+ if (YY_START != INITIAL)
+ syntax_error("unexpected end of file. Maybe missing closing brace?.");
+ /* else
+ fprintf(stderr,"\n--- End of File. OK\n");
+ */
+ yyterminate();
+ }
+}
%%
-void syntax_error(char* text)
+static void syntax_error(char *err)
+{
+ PRINTF("%s\n", err);
+ exit(E_syntax);
+}
+
+static void expect_error(char *err)
+{
+ PRINTF("%s expected, not '%s'.\n", err, yytext);
+ exit(E_syntax);
+}
+
+static void update_lcnt(void)
+{
+ char *p = yytext;
+ while (*p) {
+ if (*p++ == '\n')
+ ++line;
+ }
+}
+
+static void section(int sect)
{
- fprintf(stderr,"Unknown token '%s' in line %d.\n",text,line);
- exit(2);
+ static int s = 0;
+ static int g = 0;
+ if (sect != IGNORE_SECTION) {
+ ++s;
+ if (sect == GLOBAL) {
+ if (s != 1) {
+ if (g)
+ syntax_error("only one global { ... } section allowed.\n");
+ syntax_error("global { ... } section must be first.\n");
+ }
+ ++g;
+ }
+ }
+ yy_push_state(sect);
+ yy_push_state(LBRACE);
+ fline = line;
+}
+
+static void named_section(int sect)
+{
+ section(sect);
+ yy_push_state(STRING);
+ yy_push_state(LS);
+}
+
+static void do_assign(int what)
+{
+ yy_push_state(SEMICOLON);
+ yy_push_state(what);
+ yy_push_state(ASSIGN);
+}
+
+/*
+static char* const escape(char* const str)
+{
+ static char buffer[1024];
+ char *ue = str, *e = buffer;
+
+ if (!str || !str[0]) {
+ return "\"\"";
+ }
+ *e++ = '"';
+ while(*ue) {
+ if (*ue == '"' || *ue == '\\') {
+ *e++ = '\\';
+ }
+ if (e-buffer >= 1021) { PRINTF("string too long.\n"); exit(E_syntax); }
+ *e++ = *ue++;
+ }
+ *e++ = '"';
+ *e++ = '\0';
+ return buffer;
+}
+*/
+
+static void unescape(void)
+{
+ /* backslash escapes from string */
+ char *ue, *e;
+ e = ue = yytext;
+ for (;;) {
+ if (*ue == '"')
+ ue++;
+ if (*ue == '\\')
+ ue++;
+ if (!*ue)
+ break;
+ *e++ = *ue++;
+ }
+ *e = '\0';
+}
+
+static void unescape_midx(void)
+{
+ char *b;
+ int n;
+
+ b = strrchr(yytext, '[');
+ if (b) {
+ n = atoi(b + 1);
+ n = snprintf(yytext, yyleng, "%d", n);
+ if (0 < n && n < yyleng)
+ return; /* ok */
+ }
+ fprintf(stderr, "Oops, thinko in %s:%d.\n", __FILE__, __LINE__);
+ exit(E_thinko);
}
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/user/drbdsetup.c,v
retrieving revision 1.54.2.29
retrieving revision 1.54.2.30
diff -u -3 -r1.54.2.29 -r1.54.2.30
--- drbdsetup.c 21 Apr 2004 21:36:53 -0000 1.54.2.29
+++ drbdsetup.c 26 Apr 2004 08:36:29 -0000 1.54.2.30
@@ -39,6 +39,7 @@
#include <stdio.h>
#include <string.h>
#include <linux/drbd.h>
+#include <linux/drbd_config.h>
#define _GNU_SOURCE
#include <getopt.h>
#include <stdlib.h>
@@ -50,21 +51,21 @@
#define ARRY_SIZE(A) (sizeof(A)/sizeof(A[0]))
/* Default values */
-#define DEF_NET_TIMEOUT 60 // 6 seconds
-#define DEF_NET_TRY_CON_I 10 // 10 seconds
-#define DEF_NET_PING_I 10 // 10 seconds
-#define DEF_SYNC_RATE 250
-#define DEF_SYNC_GROUP 0
-#define DEF_WFC_TIMEOUT 0 // forever
-#define DEF_DEGR_WFC_TIMEOUT 60 // 60 Seconds
-#define DEF_SYNC_WFC_TIMEOUT 8 // 8 seconds
-#define DEF_SYNC_DEGR_WFC_TIMEOUT 4 // 4 seconds
-#define DEF_SYNC_AL_EXTENTS 128
-#define DEF_MAX_EPOCH_SIZE 2048 // entries
-#define DEF_MAX_BUFFERS 2048 // entries
-#define DEF_SNDBUF_SIZE (2*65535) // ~128KB
-#define DEF_DISK_SIZE 0
-#define DEF_ON_IO_ERROR PassOn
+#define DEF_NET_TIMEOUT 60 // 6 seconds
+#define DEF_NET_TRY_CON_I 10 // 10 seconds
+#define DEF_NET_PING_I 10 // 10 seconds
+#define DEF_SYNC_RATE 250
+#define DEF_SYNC_GROUP 0
+#define DEF_WFC_TIMEOUT 0 // forever
+#define DEF_DEGR_WFC_TIMEOUT 60 // 60 Seconds
+#define DEF_SYNC_WFC_TIMEOUT 8 // 8 seconds
+#define DEF_SYNC_DEGR_WFC_TIMEOUT 4 // 4 seconds
+#define DEF_SYNC_AL_EXTENTS 128
+#define DEF_MAX_EPOCH_SIZE 2048 // entries
+#define DEF_MAX_BUFFERS 2048 // entries
+#define DEF_SNDBUF_SIZE (2*65535) // ~128KB
+#define DEF_DISK_SIZE 0
+#define DEF_ON_IO_ERROR PassOn
#if 0
# define ioctl(X...) (fprintf(stderr,"ioctl(%s)\n",#X),0);
@@ -348,7 +349,7 @@
printf(" %s",eh_names[i]);
if(i < ARRY_SIZE(eh_names)-1) printf(",");
}
-
+
printf("\n\nVersion: "REL_VERSION" (api:%d)\n",API_VERSION);
if (addinfo)
printf("\n%s\n",addinfo);