X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=namedev_parse.c;h=3be408932bc93edbc82485357b86928dbe9ff793;hp=7e3783320256818948a547d744e0062bd5fe3c2e;hb=882af735ec18cb4e6ba6f59ca60f8266cc96c330;hpb=3db7fa27027110fde92a1b6061fab434fe708e9f diff --git a/namedev_parse.c b/namedev_parse.c index 7e3783320..3be408932 100644 --- a/namedev_parse.c +++ b/namedev_parse.c @@ -4,6 +4,7 @@ * Userspace devfs * * Copyright (C) 2003,2004 Greg Kroah-Hartman + * Copyright (C) 2003-2005 Kay Sievers * * * This program is free software; you can redistribute it and/or modify it @@ -35,11 +36,13 @@ #include #include +#include "udev_libc_wrapper.h" #include "udev.h" -#include "udev_lib.h" +#include "udev_utils.h" #include "logging.h" #include "namedev.h" +LIST_HEAD(config_device_list); static int add_config_dev(struct config_device *new_dev) { @@ -56,11 +59,11 @@ static int add_config_dev(struct config_device *new_dev) void dump_config_dev(struct config_device *dev) { - dbg_parse("name='%s', symlink='%s', bus='%s', place='%s', id='%s', " + dbg_parse("name='%s', symlink='%s', bus='%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->name, dev->symlink, dev->bus, dev->id, dev->sysfs_pair[0].file, dev->sysfs_pair[0].value, dev->kernel, dev->program, dev->result, dev->owner, dev->group, dev->mode); @@ -74,46 +77,7 @@ 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", - dev->name, dev->owner, dev->group, dev->mode); -} - -void dump_perm_dev_list(void) -{ - struct perm_device *dev; - - list_for_each_entry(dev, &perm_device_list, node) - dump_perm_dev(dev); -} - -/* extract possible KEY{attr} or KEY_attr */ +/* extract possible KEY{attr} */ static char *get_key_attribute(char *str) { char *pos; @@ -132,17 +96,10 @@ static char *get_key_attribute(char *str) return attr; } - attr = strchr(str, '_'); - if (attr != NULL) { - attr++; - dbg("attribute='%s'", attr); - return attr; - } - return NULL; } -static int namedev_parse_rules(char *filename) +static int namedev_parse(struct udevice *udev, const char *filename) { char line[LINE_SIZE]; char *bufline; @@ -171,14 +128,15 @@ static int namedev_parse_rules(char *filename) cur = 0; lineno = 0; while (cur < bufsize) { + unsigned int i, j; + count = buf_get_line(buf, bufsize, cur); bufline = &buf[cur]; cur += count+1; lineno++; - if (count >= LINE_SIZE) { - info("line too long, rule skipped %s, line %d", - filename, lineno); + if (count >= sizeof(line)) { + info("line too long, rule skipped %s, line %d", filename, lineno); continue; } @@ -194,8 +152,14 @@ static int namedev_parse_rules(char *filename) if (bufline[0] == COMMENT_CHARACTER) continue; - strncpy(line, bufline, count); - line[count] = '\0'; + /* skip backslash and newline from multi line rules */ + for (i = j = 0; i < count; i++) { + if (bufline[i] == '\\' && bufline[i+1] == '\n') + continue; + + line[j++] = bufline[i]; + } + line[j] = '\0'; dbg_parse("read '%s'", line); /* get all known keys */ @@ -208,20 +172,26 @@ static int namedev_parse_rules(char *filename) if (retval) break; - if (strcasecmp(temp2, FIELD_BUS) == 0) { - strfieldcpy(dev.bus, temp3); + if (strcasecmp(temp2, FIELD_KERNEL) == 0) { + strlcpy(dev.kernel, temp3, sizeof(dev.kernel)); valid = 1; continue; } - if (strcasecmp(temp2, FIELD_ID) == 0) { - strfieldcpy(dev.id, temp3); + if (strcasecmp(temp2, FIELD_SUBSYSTEM) == 0) { + strlcpy(dev.subsystem, temp3, sizeof(dev.subsystem)); + valid = 1; + continue; + } + + if (strcasecmp(temp2, FIELD_BUS) == 0) { + strlcpy(dev.bus, temp3, sizeof(dev.bus)); valid = 1; continue; } - if (strcasecmp(temp2, FIELD_PLACE) == 0) { - strfieldcpy(dev.place, temp3); + if (strcasecmp(temp2, FIELD_ID) == 0) { + strlcpy(dev.id, temp3, sizeof(dev.id)); valid = 1; continue; } @@ -245,57 +215,67 @@ static int namedev_parse_rules(char *filename) dbg("error parsing " FIELD_SYSFS " attribute"); continue; } - strfieldcpy(pair->file, attr); - strfieldcpy(pair->value, temp3); + strlcpy(pair->file, attr, sizeof(pair->file)); + strlcpy(pair->value, temp3, sizeof(pair->value)); valid = 1; } continue; } - if (strcasecmp(temp2, FIELD_KERNEL) == 0) { - strfieldcpy(dev.kernel, temp3); + if (strcasecmp(temp2, FIELD_DRIVER) == 0) { + strlcpy(dev.driver, temp3, sizeof(dev.driver)); valid = 1; continue; } if (strcasecmp(temp2, FIELD_PROGRAM) == 0) { program_given = 1; - strfieldcpy(dev.program, temp3); + strlcpy(dev.program, temp3, sizeof(dev.program)); valid = 1; continue; } if (strcasecmp(temp2, FIELD_RESULT) == 0) { - strfieldcpy(dev.result, temp3); + strlcpy(dev.result, temp3, sizeof(dev.result)); valid = 1; continue; } if (strncasecmp(temp2, FIELD_NAME, sizeof(FIELD_NAME)-1) == 0) { attr = get_key_attribute(temp2 + sizeof(FIELD_NAME)-1); - if (attr != NULL && strcasecmp(attr, ATTR_PARTITIONS) == 0) { + /* FIXME: remove old style options and make OPTIONS= mandatory */ + if (attr != NULL) { + if (strstr(attr, OPTION_PARTITIONS) != NULL) { dbg_parse("creation of partition nodes requested"); - dev.partitions = PARTITIONS_COUNT; + dev.partitions = DEFAULT_PARTITIONS_COUNT; + } + if (strstr(attr, OPTION_IGNORE_REMOVE) != NULL) { + dbg_parse("remove event should be ignored"); + dev.ignore_remove = 1; } - strfieldcpy(dev.name, temp3); + } + if (temp3[0] != '\0') + strlcpy(dev.name, temp3, sizeof(dev.name)); + else + dev.ignore_device = 1; valid = 1; continue; } if (strcasecmp(temp2, FIELD_SYMLINK) == 0) { - strfieldcpy(dev.symlink, temp3); + strlcpy(dev.symlink, temp3, sizeof(dev.symlink)); valid = 1; continue; } if (strcasecmp(temp2, FIELD_OWNER) == 0) { - strfieldcpy(dev.owner, temp3); + strlcpy(dev.owner, temp3, sizeof(dev.owner)); valid = 1; continue; } if (strcasecmp(temp2, FIELD_GROUP) == 0) { - strfieldcpy(dev.group, temp3); + strlcpy(dev.group, temp3, sizeof(dev.group)); valid = 1; continue; } @@ -306,6 +286,23 @@ static int namedev_parse_rules(char *filename) continue; } + if (strcasecmp(temp2, FIELD_OPTIONS) == 0) { + if (strstr(temp3, OPTION_IGNORE_DEVICE) != NULL) { + dbg_parse("device should be ignored"); + dev.ignore_device = 1; + } + if (strstr(temp3, OPTION_IGNORE_REMOVE) != NULL) { + dbg_parse("remove event should be ignored"); + dev.ignore_remove = 1; + } + if (strstr(temp3, OPTION_PARTITIONS) != NULL) { + dbg_parse("creation of partition nodes requested"); + dev.partitions = DEFAULT_PARTITIONS_COUNT; + } + valid = 1; + continue; + } + dbg("unknown type of field '%s'", temp2); goto error; } @@ -328,14 +325,14 @@ static int namedev_parse_rules(char *filename) } dev.config_line = lineno; - strfieldcpy(dev.config_file, filename); + strlcpy(dev.config_file, filename, sizeof(dev.config_file)); retval = add_config_dev(&dev); if (retval) { dbg("add_config_dev returned with error %d", retval); continue; error: info("parse error %s, line %d:%d, rule skipped", - filename, lineno, temp - line); + filename, lineno, (int) (temp - line)); } } @@ -343,124 +340,30 @@ error: return retval; } -static int namedev_parse_permissions(char *filename) +int namedev_init(void) { - char line[LINE_SIZE]; - char *bufline; - char *temp; - char *temp2; - char *buf; - size_t bufsize; - size_t cur; - size_t count; - int retval = 0; - struct perm_device dev; - int lineno; + struct stat stats; + int retval; - if (file_map(filename, &buf, &bufsize) == 0) { - dbg("reading '%s' as permissions file", filename); - } else { - dbg("can't open '%s' as permissions file", filename); + if (stat(udev_rules_filename, &stats) != 0) return -1; - } - - /* loop through the whole file */ - cur = 0; - lineno = 0; - while (cur < bufsize) { - count = buf_get_line(buf, bufsize, cur); - bufline = &buf[cur]; - cur += count+1; - lineno++; - - if (count >= LINE_SIZE) { - info("line too long, rule skipped %s, line %d", - filename, lineno); - continue; - } - - /* eat the whitespace */ - while ((count > 0) && isspace(bufline[0])) { - bufline++; - count--; - } - if (count == 0) - continue; - - /* see if this is a comment */ - if (bufline[0] == COMMENT_CHARACTER) - continue; - - strncpy(line, bufline, count); - line[count] = '\0'; - dbg_parse("read '%s'", line); - - /* parse the line */ - memset(&dev, 0x00, sizeof(struct perm_device)); - temp = line; - temp2 = strsep(&temp, ":"); - if (!temp2) { - dbg("cannot parse line '%s'", line); - continue; - } - strfieldcpy(dev.name, temp2); - - temp2 = strsep(&temp, ":"); - if (!temp2) { - dbg("cannot parse line '%s'", line); - continue; - } - strfieldcpy(dev.owner, temp2); - - temp2 = strsep(&temp, ":"); - if (!temp2) { - dbg("cannot parse line '%s'", line); - continue; - } - strfieldcpy(dev.group, temp2); - - if (!temp) { - 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); - - retval = add_perm_dev(&dev); - if (retval) { - dbg("add_perm_dev returned with error %d", retval); - goto exit; - } - } + if ((stats.st_mode & S_IFMT) != S_IFDIR) + retval = namedev_parse(NULL, udev_rules_filename); + else + retval = call_foreach_file(namedev_parse, NULL, udev_rules_filename, RULEFILE_SUFFIX); -exit: - file_unmap(buf, bufsize); return retval; } -int namedev_init_rules() +void namedev_close(void) { - struct stat stats; + struct config_device *dev; + struct config_device *temp_dev; - stat(udev_rules_filename, &stats); - if ((stats.st_mode & S_IFMT) != S_IFDIR) - return namedev_parse_rules(udev_rules_filename); - else - return call_foreach_file(namedev_parse_rules, - udev_rules_filename, RULEFILE_SUFFIX); + list_for_each_entry_safe(dev, temp_dev, &config_device_list, node) { + list_del(&dev->node); + free(dev); + } } -int namedev_init_permissions() -{ - struct stat stats; - - stat(udev_permissions_filename, &stats); - if ((stats.st_mode & S_IFMT) != S_IFDIR) - return namedev_parse_permissions(udev_permissions_filename); - else - return call_foreach_file(namedev_parse_permissions, - udev_permissions_filename, PERMFILE_SUFFIX); -}