chiark / gitweb /
update IMPORT= file/stdout property parsing
authorKay Sievers <kay.sievers@vrfy.org>
Thu, 16 Oct 2008 20:41:52 +0000 (22:41 +0200)
committerKay Sievers <kay.sievers@vrfy.org>
Thu, 16 Oct 2008 20:41:52 +0000 (22:41 +0200)
udev/udev-rules.c

index 0bad2171fac554d12340195ac53917733abce937..6f53b6a88be6da2a8992bc9a9588d9daec98092c 100644 (file)
@@ -76,46 +76,6 @@ static int get_format_len(struct udev *udev, char **str)
        return -1;
 }
 
-static int get_key(char **line, char **key, char **value)
-{
-       char *linepos;
-       char *temp;
-
-       linepos = *line;
-       if (linepos == NULL)
-               return -1;
-
-       /* skip whitespace */
-       while (isspace(linepos[0]))
-               linepos++;
-
-       /* get the key */
-       temp = strchr(linepos, '=');
-       if (temp == NULL || temp == linepos)
-               return -1;
-       temp[0] = '\0';
-       *key = linepos;
-       linepos = &temp[1];
-
-       /* get a quoted value */
-       if (linepos[0] == '"' || linepos[0] == '\'') {
-               temp = strchr(&linepos[1], linepos[0]);
-               if (temp != NULL) {
-                       temp[0] = '\0';
-                       *value = &linepos[1];
-                       goto out;
-               }
-       }
-
-       /* get the value*/
-       temp = strchr(linepos, '\n');
-       if (temp != NULL)
-               temp[0] = '\0';
-       *value = linepos;
-out:
-       return 0;
-}
-
 static int run_program(struct udev_device *dev, const char *command,
                       char *result, size_t ressize, size_t *reslen)
 {
@@ -333,106 +293,132 @@ static int run_program(struct udev_device *dev, const char *command,
        return err;
 }
 
-static int import_keys_into_env(struct udev_event *event, const char *buf, size_t bufsize)
+static int import_property_from_string(struct udev_device *dev, char *line)
 {
-       struct udev_device *dev = event->dev;
-       char line[UTIL_LINE_SIZE];
-       const char *bufline;
-       char *linepos;
-       char *variable;
-       char *value;
-       size_t cur;
-       size_t count;
-       int lineno;
-
-       /* loop through the whole buffer */
-       lineno = 0;
-       cur = 0;
-       while (cur < bufsize) {
-               count = buf_get_line(buf, bufsize, cur);
-               bufline = &buf[cur];
-               cur += count+1;
-               lineno++;
-
-               /* eat the whitespace */
-               while ((count > 0) && isspace(bufline[0])) {
-                       bufline++;
-                       count--;
-               }
-               if (count == 0)
-                       continue;
+       struct udev *udev = udev_device_get_udev(dev);
+       char *key;
+       char *val;
+       size_t len;
 
-               /* see if this is a comment */
-               if (bufline[0] == '#')
-                       continue;
+       /* find key */
+       key = line;
+       while (isspace(key[0]))
+               key++;
 
-               if (count >= sizeof(line)) {
-                       err(event->udev, "line too long, skipped\n");
-                       continue;
-               }
+       /* comment or empty line */
+       if (key[0] == '#' || key[0] == '\0')
+               return -1;
 
-               memcpy(line, bufline, count);
-               line[count] = '\0';
-
-               linepos = line;
-               if (get_key(&linepos, &variable, &value) == 0) {
-                       char syspath[UTIL_PATH_SIZE];
-
-                       dbg(event->udev, "import '%s=%s'\n", variable, value);
-                       /* handle device, renamed by external tool, returning new path */
-                       if (strcmp(variable, "DEVPATH") == 0) {
-                               info(event->udev, "updating devpath from '%s' to '%s'\n",
-                                    udev_device_get_devpath(dev), value);
-                               util_strlcpy(syspath, udev_get_sys_path(event->udev), sizeof(syspath));
-                               util_strlcat(syspath, value, sizeof(syspath));
-                               udev_device_set_syspath(dev, syspath);
-                       } else {
-                               struct udev_list_entry *entry;
+       /* split key/value */
+       val = strchr(key, '=');
+       if (val == NULL)
+               return -1;
+       val[0] = '\0';
+       val++;
 
-                               entry = udev_device_add_property(dev, variable, value);
-                               /* store in db */
-                               udev_list_entry_set_flag(entry, 1);
-                       }
+       /* find value */
+       while (isspace(val[0]))
+               val++;
+
+       /* terminate key */
+       len = strlen(key);
+       if (len == 0)
+               return -1;
+       while (isspace(key[len-1]))
+               len--;
+       key[len] = '\0';
+
+       /* terminate value */
+       len = strlen(val);
+       if (len == 0)
+               return -1;
+       while (isspace(val[len-1]))
+               len--;
+       val[len] = '\0';
+
+       if (len == 0)
+               return -1;
+
+       /* unquote */
+       if (val[0] == '"' || val[0] == '\'') {
+               if (val[len-1] != val[0]) {
+                       info(udev, "inconsistent quoting: '%s', skip\n", line);
+                       return -1;
                }
+               val[len-1] = '\0';
+               val++;
+       }
+
+       info(udev, "adding '%s'='%s'\n", key, val);
+
+       /* handle device, renamed by external tool, returning new path */
+       if (strcmp(key, "DEVPATH") == 0) {
+               char syspath[UTIL_PATH_SIZE];
+
+               info(udev, "updating devpath from '%s' to '%s'\n",
+                    udev_device_get_devpath(dev), val);
+               util_strlcpy(syspath, udev_get_sys_path(udev), sizeof(syspath));
+               util_strlcat(syspath, val, sizeof(syspath));
+               udev_device_set_syspath(dev, syspath);
+       } else {
+               struct udev_list_entry *entry;
+
+               entry = udev_device_add_property(dev, key, val);
+               /* store in db */
+               udev_list_entry_set_flag(entry, 1);
        }
        return 0;
 }
 
-static int import_file_into_env(struct udev_event *event, const char *filename)
+static int import_file_into_env(struct udev_device *dev, const char *filename)
 {
-       char *buf;
-       size_t bufsize;
+       FILE *f;
+       char line[UTIL_LINE_SIZE];
 
-       if (file_map(filename, &buf, &bufsize) != 0) {
-               err(event->udev, "can't open '%s': %m\n", filename);
+       f = fopen(filename, "r");
+       if (f == NULL)
                return -1;
-       }
-       import_keys_into_env(event, buf, bufsize);
-       file_unmap(buf, bufsize);
-
+       while (fgets(line, sizeof(line), f))
+               import_property_from_string(dev, line);
+       fclose(f);
        return 0;
 }
 
-static int import_program_into_env(struct udev_event *event, const char *program)
+static int import_program_into_env(struct udev_device *dev, const char *program)
 {
        char result[2048];
        size_t reslen;
+       char *line;
 
-       if (run_program(event->dev, program, result, sizeof(result), &reslen) != 0)
+       if (run_program(dev, program, result, sizeof(result), &reslen) != 0)
                return -1;
-       return import_keys_into_env(event, result, reslen);
+
+       line = result;
+       while (line != NULL) {
+               char *pos;
+
+               pos = strchr(line, '\n');
+               if (pos != NULL) {
+                       pos[0] = '\0';
+                       pos = &pos[1];
+               }
+               import_property_from_string(dev, line);
+               line = pos;
+       }
+       return 0;
 }
 
-static int import_parent_into_env(struct udev_event *event, const char *filter)
+static int import_parent_into_env(struct udev_device *dev, const char *filter)
 {
+       struct udev *udev = udev_device_get_udev(dev);
        struct udev_device *dev_parent;
        struct udev_list_entry *list_entry;
 
-       dev_parent = udev_device_get_parent(event->dev);
+       dev_parent = udev_device_get_parent(dev);
        if (dev_parent == NULL)
                return -1;
 
-       dbg(event->udev, "found parent '%s', get the node name\n", udev_device_get_syspath(dev_parent));
+       dbg(udev, "found parent '%s', get the node name\n", udev_device_get_syspath(dev_parent));
        udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(dev_parent)) {
                const char *key = udev_list_entry_get_name(list_entry);
                const char *val = udev_list_entry_get_value(list_entry);
@@ -440,8 +426,8 @@ static int import_parent_into_env(struct udev_event *event, const char *filter)
                if (fnmatch(filter, key, 0) == 0) {
                        struct udev_list_entry *entry;
 
-                       dbg(event->udev, "import key '%s=%s'\n", key, val);
-                       entry = udev_device_add_property(event->dev, key, val);
+                       dbg(udev, "import key '%s=%s'\n", key, val);
+                       entry = udev_device_add_property(dev, key, val);
                        /* store in db */
                        udev_list_entry_set_flag(entry, 1);
                }
@@ -1270,13 +1256,13 @@ try_parent:
                udev_rules_apply_format(event, import, sizeof(import));
                dbg(event->udev, "check for IMPORT import='%s'\n", import);
                if (rule->import_type == IMPORT_PROGRAM) {
-                       rc = import_program_into_env(event, import);
+                       rc = import_program_into_env(event->dev, import);
                } else if (rule->import_type == IMPORT_FILE) {
                        dbg(event->udev, "import file import='%s'\n", import);
-                       rc = import_file_into_env(event, import);
+                       rc = import_file_into_env(event->dev, import);
                } else if (rule->import_type == IMPORT_PARENT) {
                        dbg(event->udev, "import parent import='%s'\n", import);
-                       rc = import_parent_into_env(event, import);
+                       rc = import_parent_into_env(event->dev, import);
                }
                if (rc != 0) {
                        dbg(event->udev, "IMPORT failed\n");