chiark / gitweb /
udevadm: test - remove --force option
[elogind.git] / udev / udev-node.c
index 9f2b6cf0146d90afa6eccf5b5900a887e78cb117..18a9d11017b3cf3bc2641140f6a6cd094f3c19af 100644 (file)
 #include <sys/types.h>
 
 #include "udev.h"
-#include "udev-rules.h"
 
 #define TMP_FILE_EXT           ".udev-tmp"
 
 /* reverse mapping from the device file name to the devpath */
-static int name_index(struct udev *udev, const char *devpath, const char *name, int add, int test)
+static int name_index(struct udev *udev, const char *devpath, const char *name, int add)
 {
        char device[UTIL_PATH_SIZE];
        char filename[UTIL_PATH_SIZE * 2];
@@ -53,15 +52,15 @@ static int name_index(struct udev *udev, const char *devpath, const char *name,
        util_strlcat(filename, device, sizeof(filename));
 
        if (add) {
-               info(udev, "creating index: '%s'\n", filename);
-               create_path(udev, filename);
+               dbg(udev, "creating index: '%s'\n", filename);
+               util_create_path(udev, filename);
                fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, 0644);
                if (fd > 0)
                        close(fd);
        } else {
-               info(udev, "removing index: '%s'\n", filename);
+               dbg(udev, "removing index: '%s'\n", filename);
                unlink(filename);
-               delete_path(udev, filename);
+               util_delete_path(udev, filename);
        }
        return 0;
 }
@@ -144,7 +143,7 @@ exit:
 static int node_symlink(struct udev *udev, const char *node, const char *slink)
 {
        struct stat stats;
-       char target[UTIL_PATH_SIZE] = "";
+       char target[UTIL_PATH_SIZE];
        char slink_tmp[UTIL_PATH_SIZE + sizeof(TMP_FILE_EXT)];
        int i = 0;
        int tail = 0;
@@ -152,6 +151,7 @@ static int node_symlink(struct udev *udev, const char *node, const char *slink)
        int err = 0;
 
        /* use relative link */
+       target[0] = '\0';
        while (node[i] && (node[i] == slink[i])) {
                if (node[i] == '/')
                        tail = i+1;
@@ -185,7 +185,7 @@ static int node_symlink(struct udev *udev, const char *node, const char *slink)
                } else if (S_ISLNK(stats.st_mode)) {
                        char buf[UTIL_PATH_SIZE];
 
-                       info(udev, "found existing symlink '%s'\n", slink);
+                       dbg(udev, "found existing symlink '%s'\n", slink);
                        len = readlink(slink, buf, sizeof(buf));
                        if (len > 0) {
                                buf[len] = '\0';
@@ -227,7 +227,7 @@ exit:
        return err;
 }
 
-static int get_devices_by_name(struct udev *udev, const char *name, struct list_head *name_list)
+static int name_index_get_devices(struct udev *udev, const char *name, struct udev_list_node *dev_list)
 {
        char dirname[PATH_MAX];
        size_t devlen = strlen(udev_get_dev_path(udev))+1;
@@ -239,15 +239,14 @@ static int get_devices_by_name(struct udev *udev, const char *name, struct list_
        start = util_strlcat(dirname, "/.udev/names/", sizeof(dirname));
        util_strlcat(dirname, &name[devlen], sizeof(dirname));
        util_path_encode(&dirname[start], sizeof(dirname) - start);
-
        dir = opendir(dirname);
        if (dir == NULL) {
-               info(udev, "no index directory '%s': %m\n", dirname);
+               dbg(udev, "no index directory '%s': %m\n", dirname);
                count = -1;
                goto out;
        }
+       dbg(udev, "found index directory '%s'\n", dirname);
 
-       info(udev, "found index directory '%s'\n", dirname);
        while (1) {
                struct dirent *ent;
                char device[UTIL_PATH_SIZE];
@@ -261,7 +260,7 @@ static int get_devices_by_name(struct udev *udev, const char *name, struct list_
                util_strlcpy(device, udev_get_sys_path(udev), sizeof(device));
                util_strlcat(device, ent->d_name, sizeof(device));
                util_path_decode(device);
-               name_list_add(udev, name_list, device, 0);
+               udev_list_entry_add(udev, dev_list, device, NULL, 1, 0);
                count++;
        }
        closedir(dir);
@@ -269,42 +268,45 @@ out:
        return count;
 }
 
-static int update_link(struct udev_device *dev, const char *slink, int test)
+static int update_link(struct udev_device *dev, const char *slink)
 {
        struct udev *udev = udev_device_get_udev(dev);
-       LIST_HEAD(name_list);
-       struct name_entry *device;
-       char target[UTIL_PATH_SIZE] = "";
+       struct udev_list_node dev_list;
+       struct udev_list_entry *dev_entry;
+       char target[UTIL_PATH_SIZE];
        int count;
        int priority = 0;
        int rc = 0;
 
-       info(udev, "update symlink '%s' of '%s'\n", slink, udev_device_get_syspath(dev));
+       dbg(udev, "update symlink '%s' of '%s'\n", slink, udev_device_get_syspath(dev));
 
-       count = get_devices_by_name(udev, slink, &name_list);
-       info(udev, "found %i devices with name '%s'\n", count, slink);
+       udev_list_init(&dev_list);
+       count = name_index_get_devices(udev, slink, &dev_list);
+       if (count > 1)
+               info(udev, "found %i devices with name '%s'\n", count, slink);
 
        /* if we don't have a reference, delete it */
        if (count <= 0) {
                info(udev, "no reference left, remove '%s'\n", slink);
-               if (!test) {
-                       unlink(slink);
-                       delete_path(udev, slink);
-               }
+               unlink(slink);
+               util_delete_path(udev, slink);
                goto out;
        }
 
        /* find the device with the highest priority */
-       list_for_each_entry(device, &name_list, node) {
+       target[0] = '\0';
+       udev_list_entry_foreach(dev_entry, udev_list_get_entry(&dev_list)) {
+               const char *syspath;
                struct udev_device *dev_db;
                const char *devnode;
 
-               info(udev, "found '%s' for '%s'\n", device->name, slink);
+               syspath = udev_list_entry_get_name(dev_entry);
+               dbg(udev, "found '%s' for '%s'\n", syspath, slink);
 
                /* did we find ourself? we win, if we have the same priority */
-               if (strcmp(udev_device_get_syspath(dev), device->name) == 0) {
-                       info(udev, "compare (our own) priority of '%s' %i >= %i\n",
-                            udev_device_get_devpath(dev), udev_device_get_devlink_priority(dev), priority);
+               if (strcmp(udev_device_get_syspath(dev), syspath) == 0) {
+                       dbg(udev, "compare (our own) priority of '%s' %i >= %i\n",
+                           udev_device_get_devpath(dev), udev_device_get_devlink_priority(dev), priority);
                        if (strcmp(udev_device_get_devnode(dev), slink) == 0) {
                                info(udev, "'%s' is our device node, database inconsistent, skip link update\n",
                                     udev_device_get_devnode(dev));
@@ -316,19 +318,19 @@ static int update_link(struct udev_device *dev, const char *slink, int test)
                }
 
                /* another device, read priority from database */
-               dev_db = udev_device_new_from_syspath(udev, device->name);
+               dev_db = udev_device_new_from_syspath(udev, syspath);
                if (dev_db == NULL)
                        continue;
                devnode = udev_device_get_devnode(dev_db);
                if (devnode != NULL) {
                        if (strcmp(devnode, slink) == 0) {
                                info(udev, "'%s' is a device node of '%s', skip link update\n",
-                                    devnode, device->name);
+                                    devnode, syspath);
                        } else {
-                               info(udev, "compare priority of '%s' %i > %i\n",
-                                    udev_device_get_devpath(dev_db),
-                                    udev_device_get_devlink_priority(dev_db),
-                                    priority);
+                               dbg(udev, "compare priority of '%s' %i > %i\n",
+                                   udev_device_get_devpath(dev_db),
+                                   udev_device_get_devlink_priority(dev_db),
+                                   priority);
                                if (target[0] == '\0' || udev_device_get_devlink_priority(dev_db) > priority) {
                                        priority = udev_device_get_devlink_priority(dev_db);
                                        util_strlcpy(target, devnode, sizeof(target));
@@ -337,7 +339,7 @@ static int update_link(struct udev_device *dev, const char *slink, int test)
                }
                udev_device_unref(dev_db);
        }
-       name_list_cleanup(udev, &name_list);
+       udev_list_cleanup_entries(udev, &dev_list);
 
        if (target[0] == '\0') {
                info(udev, "no current target for '%s' found\n", slink);
@@ -347,15 +349,13 @@ static int update_link(struct udev_device *dev, const char *slink, int test)
 
        /* create symlink to the target with the highest priority */
        info(udev, "'%s' with target '%s' has the highest priority %i, create it\n", slink, target, priority);
-       if (!test) {
-               create_path(udev, slink);
-               node_symlink(udev, target, slink);
-       }
+       util_create_path(udev, slink);
+       node_symlink(udev, target, slink);
 out:
        return rc;
 }
 
-void udev_node_update_old_links(struct udev_device *dev, struct udev_device *dev_old, int test)
+void udev_node_update_old_links(struct udev_device *dev, struct udev_device *dev_old)
 {
        struct udev *udev = udev_device_get_udev(dev);
        struct udev_list_entry *list_entry;
@@ -363,17 +363,30 @@ void udev_node_update_old_links(struct udev_device *dev, struct udev_device *dev
 
        /* update possible left-over symlinks */
        udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev_old)) {
+               const char *name = udev_list_entry_get_name(list_entry);
                struct udev_list_entry *list_entry_current;
+               int found;
 
+               /* check if old link name is now our node name */
+               if (strcmp(name, udev_device_get_devnode(dev)) == 0)
+                       continue;
+
+               /* check if old link name still belongs to this device */
+               found = 0;
                udev_list_entry_foreach(list_entry_current, udev_device_get_devlinks_list_entry(dev)) {
-                       if (strcmp(udev_list_entry_get_name(list_entry_current),
-                                  udev_list_entry_get_name(list_entry)) == 0)
-                               continue;
+                       const char *name_current = udev_list_entry_get_name(list_entry_current);
+
+                       if (strcmp(name, name_current) == 0) {
+                               found = 1;
+                               break;
+                       }
                }
-               /* link does no longer belong to this device */
-               info(udev, "update old symlink '%s' no longer belonging to '%s'\n",
-                    udev_list_entry_get_name(list_entry), udev_device_get_devpath(dev));
-               update_link(dev, udev_list_entry_get_name(list_entry), test);
+               if (found)
+                       continue;
+
+               info(udev, "update old symlink '%s' no longer belonging to '%s'\n", name, udev_device_get_devpath(dev));
+               name_index(udev, udev_device_get_devpath(dev), name, 0);
+               update_link(dev, name);
        }
 
        /*
@@ -385,91 +398,59 @@ void udev_node_update_old_links(struct udev_device *dev, struct udev_device *dev
                const char *devnode = udev_device_get_devnode(dev);
 
                if (devnode != NULL && strcmp(devnode_old, devnode) != 0)
-                       update_link(dev, devnode_old, test);
+                       update_link(dev, devnode_old);
        }
 }
 
-int udev_node_add(struct udev_device *dev, mode_t mode, const char *owner, const char *group, int test)
+int udev_node_add(struct udev_device *dev, mode_t mode, uid_t uid, gid_t gid)
 {
        struct udev *udev = udev_device_get_udev(dev);
-       uid_t uid;
-       gid_t gid;
        int i;
        int num;
        struct udev_list_entry *list_entry;
        int err = 0;
 
-       create_path(udev, udev_device_get_devnode(dev));
-
-       if (strcmp(owner, "root") == 0)
-               uid = 0;
-       else {
-               char *endptr;
-               unsigned long id;
-
-               id = strtoul(owner, &endptr, 10);
-               if (endptr[0] == '\0')
-                       uid = (uid_t) id;
-               else
-                       uid = lookup_user(udev, owner);
-       }
-
-       if (strcmp(group, "root") == 0)
-               gid = 0;
-       else {
-               char *endptr;
-               unsigned long id;
-
-               id = strtoul(group, &endptr, 10);
-               if (endptr[0] == '\0')
-                       gid = (gid_t) id;
-               else
-                       gid = lookup_group(udev, group);
-       }
-
        info(udev, "creating device node '%s', devnum=%d:%d, mode=%#o, uid=%d, gid=%d\n",
             udev_device_get_devnode(dev),
             major(udev_device_get_devnum(dev)), minor(udev_device_get_devnum(dev)),
             mode, uid, gid);
 
-       if (!test)
-               if (udev_node_mknod(dev, NULL, makedev(0,0), mode, uid, gid) != 0) {
-                       err = -1;
-                       goto exit;
-               }
+       util_create_path(udev, udev_device_get_devnode(dev));
+       if (udev_node_mknod(dev, NULL, makedev(0,0), mode, uid, gid) != 0) {
+               err = -1;
+               goto exit;
+       }
 
        /* create all_partitions if requested */
        num = udev_device_get_num_fake_partitions(dev);
        if (num > 0) {
                info(udev, "creating device partition nodes '%s[1-%i]'\n", udev_device_get_devnode(dev), num);
-               if (!test) {
-                       for (i = 1; i <= num; i++) {
-                               char partitionname[UTIL_PATH_SIZE];
-                               dev_t part_devnum;
-
-                               snprintf(partitionname, sizeof(partitionname), "%s%d",
-                                        udev_device_get_devnode(dev), i);
-                               partitionname[sizeof(partitionname)-1] = '\0';
-                               part_devnum = makedev(major(udev_device_get_devnum(dev)),
-                                                   minor(udev_device_get_devnum(dev)) + i);
-                               udev_node_mknod(dev, partitionname, part_devnum, mode, uid, gid);
-                       }
+               for (i = 1; i <= num; i++) {
+                       char partitionname[UTIL_PATH_SIZE];
+                       dev_t part_devnum;
+
+                       snprintf(partitionname, sizeof(partitionname), "%s%d",
+                                udev_device_get_devnode(dev), i);
+                       partitionname[sizeof(partitionname)-1] = '\0';
+                       part_devnum = makedev(major(udev_device_get_devnum(dev)),
+                                           minor(udev_device_get_devnum(dev)) + i);
+                       udev_node_mknod(dev, partitionname, part_devnum, mode, uid, gid);
                }
        }
 
-       /* add node and to name index */
-       name_index(udev, udev_device_get_devpath(dev), udev_device_get_devnode(dev), 1, test);
+       /* add node to name index */
+       name_index(udev, udev_device_get_devpath(dev), udev_device_get_devnode(dev), 1);
 
        /* create/update symlinks, add symlinks to name index */
        udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) {
-               name_index(udev, udev_device_get_devpath(dev), udev_list_entry_get_name(list_entry), 1, test);
-               update_link(dev, udev_list_entry_get_name(list_entry), test);
+               name_index(udev, udev_device_get_devpath(dev), udev_list_entry_get_name(list_entry), 1);
+               update_link(dev, udev_list_entry_get_name(list_entry));
        }
 exit:
        return err;
 }
 
-extern int udev_node_remove(struct udev_device *dev, int test)
+extern int udev_node_remove(struct udev_device *dev)
 {
        struct udev *udev = udev_device_get_udev(dev);
        struct udev_list_entry *list_entry;
@@ -480,12 +461,12 @@ extern int udev_node_remove(struct udev_device *dev, int test)
        int num;
 
        /* remove node from name index */
-       name_index(udev, udev_device_get_devpath(dev), udev_device_get_devnode(dev), 0, test);
+       name_index(udev, udev_device_get_devpath(dev), udev_device_get_devnode(dev), 0);
 
        /* remove,update symlinks, remove symlinks from name index */
        udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) {
-               name_index(udev, udev_device_get_devpath(dev), udev_list_entry_get_name(list_entry), 0, test);
-               update_link(dev, udev_list_entry_get_name(list_entry), test);
+               name_index(udev, udev_device_get_devpath(dev), udev_list_entry_get_name(list_entry), 0);
+               update_link(dev, udev_list_entry_get_name(list_entry));
        }
 
        devnode = udev_device_get_devnode(dev);
@@ -501,8 +482,7 @@ extern int udev_node_remove(struct udev_device *dev, int test)
        }
 
        info(udev, "removing device node '%s'\n", devnode);
-       if (!test)
-               err = unlink_secure(udev, devnode);
+       err = util_unlink_secure(udev, devnode);
        if (err)
                return err;
 
@@ -516,10 +496,9 @@ extern int udev_node_remove(struct udev_device *dev, int test)
                for (i = 1; i <= num; i++) {
                        snprintf(partitionname, sizeof(partitionname), "%s%d", devnode, i);
                        partitionname[sizeof(partitionname)-1] = '\0';
-                       if (!test)
-                               unlink_secure(udev, partitionname);
+                       util_unlink_secure(udev, partitionname);
                }
        }
-       delete_path(udev, devnode);
+       util_delete_path(udev, devnode);
        return err;
 }