X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=namedev_parse.c;h=fba32a4983b12ed756cd577ace40aa5a60553ee2;hb=d1fb871d99db38c7704d8e583ff5e0a00e713837;hp=d5d2181cb68bb427ba34c84f187aff12187e0202;hpb=50e5de03d16be3e35e65cdf65f552807ad24e996;p=elogind.git diff --git a/namedev_parse.c b/namedev_parse.c index d5d2181cb..fba32a498 100644 --- a/namedev_parse.c +++ b/namedev_parse.c @@ -33,12 +33,17 @@ #include #include #include +#include +#include #include #include "udev.h" #include "logging.h" #include "namedev.h" +LIST_HEAD(file_list); + + static int add_config_dev(struct config_device *new_dev) { struct config_device *tmp_dev; @@ -54,13 +59,14 @@ static int add_config_dev(struct config_device *new_dev) void dump_config_dev(struct config_device *dev) { - /*FIXME dump all sysfs's */ dbg_parse("name='%s', symlink='%s', bus='%s', place='%s', id='%s', " "sysfs_file[0]='%s', sysfs_value[0]='%s', " "kernel='%s', program='%s', result='%s'", + "owner='%s', group='%s', mode=%#o", dev->name, dev->symlink, dev->bus, dev->place, dev->id, dev->sysfs_pair[0].file, dev->sysfs_pair[0].value, - dev->kernel, dev->program, dev->result); + dev->kernel, dev->program, dev->result,; + dev->owner, dev->group, dev->mode); } void dump_config_dev_list(void) @@ -71,6 +77,31 @@ void dump_config_dev_list(void) dump_config_dev(dev); } +static int add_perm_dev(struct perm_device *new_dev) +{ + struct perm_device *dev; + struct perm_device *tmp_dev; + + /* update the values if we already have the device */ + list_for_each_entry(dev, &perm_device_list, node) { + if (strcmp(new_dev->name, dev->name) != 0) + continue; + + set_empty_perms(dev, new_dev->mode, new_dev->owner, new_dev->group); + return 0; + } + + /* not found, add new structure to the perm list */ + tmp_dev = malloc(sizeof(*tmp_dev)); + if (!tmp_dev) + return -ENOMEM; + + memcpy(tmp_dev, new_dev, sizeof(*tmp_dev)); + list_add_tail(&tmp_dev->node, &perm_device_list); + //dump_perm_dev(tmp_dev); + return 0; +} + void dump_perm_dev(struct perm_device *dev) { dbg_parse("name='%s', owner='%s', group='%s', mode=%#o", @@ -114,7 +145,7 @@ static char *get_key_attribute(char *str) return NULL; } -int namedev_init_rules(void) +static int namedev_parse_rules(char *filename) { char line[255]; int lineno; @@ -127,11 +158,11 @@ int namedev_init_rules(void) int retval = 0; struct config_device dev; - fd = fopen(udev_rules_filename, "r"); + fd = fopen(filename, "r"); if (fd != NULL) { - dbg("reading '%s' as rules file", udev_rules_filename); + dbg("reading '%s' as rules file", filename); } else { - dbg("can't open '%s' as a rules file", udev_rules_filename); + dbg("can't open '%s' as a rules file", filename); return -ENODEV; } @@ -237,12 +268,26 @@ int namedev_init_rules(void) continue; } + if (strcasecmp(temp2, FIELD_OWNER) == 0) { + strfieldcpy(dev.owner, temp3); + continue; + } + + if (strcasecmp(temp2, FIELD_GROUP) == 0) { + strfieldcpy(dev.group, temp3); + continue; + } + + if (strcasecmp(temp2, FIELD_MODE) == 0) { + dev.mode = strtol(temp3, NULL, 8); + continue; + } + dbg("unknown type of field '%s'", temp2); - dbg("You might be using a rules file in the old format, please fix."); goto error; } - /* simple plausibility check for given keys */ + /* simple plausibility checks for given keys */ if ((dev.sysfs_pair[0].file[0] == '\0') ^ (dev.sysfs_pair[0].value[0] == '\0')) { dbg("inconsistency in " FIELD_SYSFS " key"); @@ -256,13 +301,14 @@ int namedev_init_rules(void) } dev.config_line = lineno; + strfieldcpy(dev.config_file, filename); retval = add_config_dev(&dev); if (retval) { dbg("add_config_dev returned with error %d", retval); continue; error: dbg("%s:%d:%d: parse error, rule skipped", - udev_rules_filename, lineno, temp - line); + filename, lineno, temp - line); } } exit: @@ -270,7 +316,7 @@ exit: return retval; } -int namedev_init_permissions(void) +static int namedev_parse_permissions(char *filename) { char line[255]; char *temp; @@ -279,11 +325,11 @@ int namedev_init_permissions(void) int retval = 0; struct perm_device dev; - fd = fopen(udev_permissions_filename, "r"); + fd = fopen(filename, "r"); if (fd != NULL) { - dbg("reading '%s' as permissions file", udev_permissions_filename); + dbg("reading '%s' as permissions file", filename); } else { - dbg("can't open '%s' as permissions file", udev_permissions_filename); + dbg("can't open '%s' as permissions file", filename); return -ENODEV; } @@ -315,31 +361,31 @@ int namedev_init_permissions(void) dbg("cannot parse line '%s'", line); continue; } - strncpy(dev.name, temp2, sizeof(dev.name)); + strfieldcpy(dev.name, temp2); temp2 = strsep(&temp, ":"); if (!temp2) { dbg("cannot parse line '%s'", line); continue; } - strncpy(dev.owner, temp2, sizeof(dev.owner)); + strfieldcpy(dev.owner, temp2); temp2 = strsep(&temp, ":"); if (!temp2) { dbg("cannot parse line '%s'", line); continue; } - strncpy(dev.group, temp2, sizeof(dev.group)); + strfieldcpy(dev.group, temp2); if (!temp) { - dbg("cannot parse line: %s", line); + dbg("cannot parse line '%s'", line); continue; } dev.mode = strtol(temp, NULL, 8); dbg_parse("name='%s', owner='%s', group='%s', mode=%#o", - dev.name, dev.owner, dev.group, - dev.mode); + dev.name, dev.owner, dev.group, dev.mode); + retval = add_perm_dev(&dev); if (retval) { dbg("add_perm_dev returned with error %d", retval); @@ -352,3 +398,88 @@ exit: return retval; } +struct files { + struct list_head list; + char name[NAME_SIZE]; +}; + +/* sort files in lexical order */ +static int file_list_insert(char *filename) +{ + struct files *loop_file; + struct files *new_file; + + list_for_each_entry(loop_file, &file_list, list) { + if (strcmp(loop_file->name, filename) > 0) { + break; + } + } + + new_file = malloc(sizeof(struct files)); + if (new_file == NULL) { + dbg("error malloc"); + return -ENOMEM; + } + + strfieldcpy(new_file->name, filename); + list_add_tail(&new_file->list, &loop_file->list); + return 0; +} + +/* calls function for file or every file found in directory */ +static int call_foreach_file(int parser (char *f) , char *filename, char *extension) +{ + struct dirent *ent; + DIR *dir; + char *ext; + char file[NAME_SIZE]; + struct stat stats; + struct files *loop_file; + struct files *tmp_file; + + /* look if we have a plain file or a directory to scan */ + stat(filename, &stats); + if ((stats.st_mode & S_IFMT) != S_IFDIR) + return parser(filename); + + /* sort matching filename into list */ + dbg("open config as directory '%s'", filename); + dir = opendir(filename); + while (1) { + ent = readdir(dir); + if (ent == NULL || ent->d_name[0] == '\0') + break; + + dbg("found file '%s'", ent->d_name); + ext = strrchr(ent->d_name, '.'); + if (ext == NULL) + continue; + + if (strcmp(ext, extension) == 0) { + dbg("put file in list '%s'", ent->d_name); + file_list_insert(ent->d_name); + } + } + + /* parse every file in the list */ + list_for_each_entry_safe(loop_file, tmp_file, &file_list, list) { + strfieldcpy(file, filename); + strfieldcat(file, loop_file->name); + parser(file); + list_del(&loop_file->list); + free(loop_file); + } + + closedir(dir); + return 0; +} + +int namedev_init_rules() +{ + return call_foreach_file(namedev_parse_rules, udev_rules_filename, RULEFILE_EXT); +} + +int namedev_init_permissions() +{ + return call_foreach_file(namedev_parse_permissions, udev_permissions_filename, PERMFILE_EXT); +}