summaryrefslogtreecommitdiffstats
path: root/config.c
diff options
context:
space:
mode:
Diffstat (limited to 'config.c')
-rw-r--r--config.c423
1 files changed, 241 insertions, 182 deletions
diff --git a/config.c b/config.c
index 2feaae3..39ef56b 100644
--- a/config.c
+++ b/config.c
@@ -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;
+}