diff options
Diffstat (limited to 'config.c')
-rw-r--r-- | config.c | 423 |
1 files changed, 241 insertions, 182 deletions
@@ -30,6 +30,8 @@ #include "mdctl.h" #include "dlink.h" #include <glob.h> +#include <fnmatch.h> + /* * Read the config file * @@ -74,15 +76,15 @@ char *keywords[] = { "device", "array", NULL }; int match_keyword(char *word) { - int len = strlen(word); - int n; + int len = strlen(word); + int n; - if (len < 3) return -1; - for (n=0; keywords[n]; n++) { - if (strncasecmp(word, keywords[n], len)==0) - return n; - } - return -1; + if (len < 3) return -1; + for (n=0; keywords[n]; n++) { + if (strncasecmp(word, keywords[n], len)==0) + return n; + } + return -1; } /* conf_word gets one word from the conf file. @@ -94,60 +96,60 @@ int match_keyword(char *word) char *conf_word(FILE *file, int allow_key) { - int wsize = 100; - int len = 0; - int c; - int quote; - int wordfound = 0; - char *word = malloc(wsize); - - if (!word) abort(); - - while (wordfound==0) { - /* at the end of a word.. */ - c = getc(file); - if (c == '#') - while (c != EOF && c != '\n') - c = getc(file); - if (c == EOF) break; - if (c == '\n') continue; + int wsize = 100; + int len = 0; + int c; + int quote; + int wordfound = 0; + char *word = malloc(wsize); - if (c != ' ' && c != '\t' && ! allow_key) { - ungetc(c, file); - break; - } - /* looks like it is safe to get a word here, if there is one */ - quote = 0; - /* first, skip any spaces */ - while (c == ' ' || c == '\t') - c = getc(file); - if (c != EOF && c != '\n' && c != '#') { - /* we really have a character of a word, so start saving it */ - while (c != EOF && c != '\n' && (quote || (c!=' ' && c != '\t'))) { - wordfound = 1; - if (quote && c == quote) quote = 0; - else if (quote == 0 && (c == '\'' || c == '"')) - quote = c; - else { - if (len == wsize-1) { - wsize += 100; - word = realloc(word, wsize); - if (!word) abort(); - } - word[len++] = c; - } + if (!word) abort(); + + while (wordfound==0) { + /* at the end of a word.. */ c = getc(file); - } + if (c == '#') + while (c != EOF && c != '\n') + c = getc(file); + if (c == EOF) break; + if (c == '\n') continue; + + if (c != ' ' && c != '\t' && ! allow_key) { + ungetc(c, file); + break; + } + /* looks like it is safe to get a word here, if there is one */ + quote = 0; + /* first, skip any spaces */ + while (c == ' ' || c == '\t') + c = getc(file); + if (c != EOF && c != '\n' && c != '#') { + /* we really have a character of a word, so start saving it */ + while (c != EOF && c != '\n' && (quote || (c!=' ' && c != '\t'))) { + wordfound = 1; + if (quote && c == quote) quote = 0; + else if (quote == 0 && (c == '\'' || c == '"')) + quote = c; + else { + if (len == wsize-1) { + wsize += 100; + word = realloc(word, wsize); + if (!word) abort(); + } + word[len++] = c; + } + c = getc(file); + } + } + if (c != EOF) ungetc(c, file); } - if (c != EOF) ungetc(c, file); - } - word[len] = 0; + word[len] = 0; /* printf("word is <%s>\n", word); */ - if (!wordfound) { - free(word); - word = NULL; - } - return word; + if (!wordfound) { + free(word); + word = NULL; + } + return word; } /* @@ -160,33 +162,33 @@ char *conf_word(FILE *file, int allow_key) char *conf_line(FILE *file) { - char *w; - char *list; + char *w; + char *list; - w = conf_word(file, 1); - if (w == NULL) return NULL; + w = conf_word(file, 1); + if (w == NULL) return NULL; - list = dl_strdup(w); - free(w); - dl_init(list); - - while ((w = conf_word(file,0))){ - char *w2 = dl_strdup(w); + list = dl_strdup(w); free(w); - dl_add(list, w2); - } + dl_init(list); + + while ((w = conf_word(file,0))){ + char *w2 = dl_strdup(w); + free(w); + dl_add(list, w2); + } /* printf("got a line\n");*/ - return list; + return list; } void free_line(char *line) { - char *w; - for (w=dl_next(line); w != line; w=dl_next(line)) { - dl_del(w); - dl_free(w); - } - dl_free(line); + char *w; + for (w=dl_next(line); w != line; w=dl_next(line)) { + dl_del(w); + dl_free(w); + } + dl_free(line); } @@ -199,141 +201,198 @@ struct conf_dev { int devline(char *line) { - char *w; - struct conf_dev *cd; - - for (w=dl_next(line); w != line; w=dl_next(w)) { - if (w[0] == '/') { - cd = malloc(sizeof(*cd)); - cd->name = strdup(w); - cd->next = cdevlist; - cdevlist = cd; - } else { - fprintf(stderr, Name ": unreconised word on DEVICE line: %s\n", - w); + char *w; + struct conf_dev *cd; + + for (w=dl_next(line); w != line; w=dl_next(w)) { + if (w[0] == '/') { + cd = malloc(sizeof(*cd)); + cd->name = strdup(w); + cd->next = cdevlist; + cdevlist = cd; + } else { + fprintf(stderr, Name ": unreconised word on DEVICE line: %s\n", + w); + } } - } } -mddev_uuid_t uuidlist = NULL; -mddev_uuid_t *uidlp = &uuidlist; +mddev_ident_t mddevlist = NULL; +mddev_ident_t *mddevlp = &mddevlist; void arrayline(char *line) { - char *w; - char *dev = NULL; - __u32 uuid[4]; - int uidset=0; - mddev_uuid_t mu; - - for (w=dl_next(line); w!=line; w=dl_next(w)) { - if (w[0] == '/') { - if (dev) - fprintf(stderr, Name ": only give one device per ARRAY line: %s and %s\n", - dev, w); - else dev = w; - } else if (strncasecmp(w, "uuid=", 5)==0 ) { - if (uidset) - fprintf(stderr, Name ": only specify uuid once, %s ignored.\n", - w); - else { - if (parse_uuid(w+5, uuid)) - uidset = 1; - else - fprintf(stderr, Name ": bad uuid: %s\n", w); - } - } else { - fprintf(stderr, Name ": unrecognised word on ARRAY line: %s\n", - w); + char *w; + + struct mddev_ident_s mis; + mddev_ident_t mi; + + mis.uuid_set = 0; + mis.super_minor = -1; + mis.devices = NULL; + mis.devname = NULL; + + for (w=dl_next(line); w!=line; w=dl_next(w)) { + if (w[0] == '/') { + if (mis.devname) + fprintf(stderr, Name ": only give one device per ARRAY line: %s and %s\n", + mis.devname, w); + else mis.devname = w; + } else if (strncasecmp(w, "uuid=", 5)==0 ) { + if (mis.uuid_set) + fprintf(stderr, Name ": only specify uuid once, %s ignored.\n", + w); + else { + if (parse_uuid(w+5, mis.uuid)) + mis.uuid_set = 1; + else + fprintf(stderr, Name ": bad uuid: %s\n", w); + } + } else if (strncasecmp(w, "super-minor=", 12)==0 ) { + if (mis.super_minor >= 0) + fprintf(stderr, Name ": only specify super-minor once, %s ignored.\n", + w); + else { + char *endptr; + mis.super_minor= strtol(w+12, &endptr, 10); + if (w[12]==0 || endptr[0]!=0 || mis.super_minor < 0) { + fprintf(stderr, Name ": invalid super-minor number: %s\n", + w); + mis.super_minor = -1; + } + } + } else if (strncasecmp(w, "devices=", 8 ) == 0 ) { + if (mis.devices) + fprintf(stderr, Name ": only specify devices once (use a comma separated list). %s ignored\n", + w); + else + mis.devices = strdup(w+8); + } else if (strncasecmp(w, "spare-group=", 12) == 0 ) { + if (mis.spare_group) + fprintf(stderr, Name ": only specify one spare group per array. %s ignored.\n", + w); + else + mis.spare_group = strdup(w+12); + } else { + fprintf(stderr, Name ": unrecognised word on ARRAY line: %s\n", + w); + } + } + if (mis.devname == NULL) + fprintf(stderr, Name ": ARRAY line with a device\n"); + else if (mis.uuid_set == 0 && mis.devices == NULL && mis.super_minor < 0) + fprintf(stderr, Name ": ARRAY line %s has no identity information.\n", mis.devname); + else { + mi = malloc(sizeof(*mi)); + *mi = mis; + mi->devname = strdup(mis.devname); + mi->next = NULL; + *mddevlp = mi; + mddevlp = &mi->next; } - } - if (dev == NULL) - fprintf(stderr, Name ": ARRAY line with a device\n"); - else if (uidset == 0) - fprintf(stderr, Name ": ARRAY line %s has no uuid\n", dev); - else { - mu = malloc(sizeof(*mu)); - mu->devname = strdup(dev); - memcpy(mu->uuid, uuid, sizeof(uuid)); - mu->next = NULL; - *uidlp = mu; - uidlp = &mu->next; - } } int loaded = 0; void load_conffile(char *conffile) { - FILE *f; - char *line; - - if (loaded) return; - if (conffile == NULL) - conffile = DefaultConfFile; - - f = fopen(conffile, "r"); - if (f ==NULL) - return; - - loaded = 1; - while ((line=conf_line(f))) { - switch(match_keyword(line)) { - case 0: /* DEVICE */ - devline(line); - break; - case 1: - arrayline(line); - break; - default: - fprintf(stderr, Name ": Unknown keyword %s\n", line); + FILE *f; + char *line; + + if (loaded) return; + if (conffile == NULL) + conffile = DefaultConfFile; + + f = fopen(conffile, "r"); + if (f ==NULL) + return; + + loaded = 1; + while ((line=conf_line(f))) { + switch(match_keyword(line)) { + case 0: /* DEVICE */ + devline(line); + break; + case 1: + arrayline(line); + break; + default: + fprintf(stderr, Name ": Unknown keyword %s\n", line); + } + free_line(line); } - free_line(line); - } /* printf("got file\n"); */ } -mddev_uuid_t conf_get_uuids(char *conffile) +mddev_ident_t conf_get_ident(char *conffile, char *dev) { - load_conffile(conffile); - return uuidlist; + mddev_ident_t rv; + load_conffile(conffile); + rv = mddevlist; + while (dev && rv && strcmp(dev, rv->devname)!=0) + rv = rv->next; + return rv; } mddev_dev_t conf_get_devs(char *conffile) { - glob_t globbuf; - struct conf_dev *cd; - int flags = 0; - static mddev_dev_t dlist = NULL; - int i; - - while (dlist) { - mddev_dev_t t = dlist; - dlist = dlist->next; - free(t->devname); - free(t); - } + glob_t globbuf; + struct conf_dev *cd; + int flags = 0; + static mddev_dev_t dlist = NULL; + int i; + + while (dlist) { + mddev_dev_t t = dlist; + dlist = dlist->next; + free(t->devname); + free(t); + } - load_conffile(conffile); + load_conffile(conffile); - for (cd=cdevlist; cd; cd=cd->next) { - glob(cd->name, flags, NULL, &globbuf); - flags |= GLOB_APPEND; - } + for (cd=cdevlist; cd; cd=cd->next) { + glob(cd->name, flags, NULL, &globbuf); + flags |= GLOB_APPEND; + } - for (i=0; i<globbuf.gl_pathc; i++) { - mddev_dev_t t = malloc(sizeof(*t)); - t->devname = strdup(globbuf.gl_pathv[i]); - t->next = dlist; - dlist = t; + for (i=0; i<globbuf.gl_pathc; i++) { + mddev_dev_t t = malloc(sizeof(*t)); + t->devname = strdup(globbuf.gl_pathv[i]); + t->next = dlist; + dlist = t; /* printf("one dev is %s\n", t->devname);*/ - } - globfree(&globbuf); + } + globfree(&globbuf); - return dlist; + return dlist; } +int match_oneof(char *devices, char *devname) +{ + /* check if one of the comma separated patterns in devices + * matches devname + */ + + + while (devices && *devices) { + char patn[1024]; + char *p = devices; + devices = strchr(devices, ','); + if (!devices) + devices = p + strlen(p); + if (devices-p < 1024) { + strncpy(patn, p, devices-p); + patn[devices-p] = 0; + if (fnmatch(patn, devname, FNM_PATHNAME)==0) + return 1; + } + if (*devices == ',') + devices++; + } + return 0; +} |