chiark / gitweb /
move syslog wrapper to libudev
[elogind.git] / udev / udev-node.c
index 1a189c5aae7c078371f9d9c9be429f45085d84d8..89b674e4c481a30b13a87e680310efe182271415 100644 (file)
 #define TMP_FILE_EXT           ".udev-tmp"
 
 /* reverse mapping from the device file name to the devpath */
 #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 devpath_enc[UTIL_PATH_SIZE];
+       char name_enc[UTIL_PATH_SIZE];
        char filename[UTIL_PATH_SIZE * 2];
        char filename[UTIL_PATH_SIZE * 2];
-       size_t devlen = strlen(udev_get_dev_path(udev))+1;
-       size_t start;
        int fd;
 
        int fd;
 
-       /* directory with device name */
-       util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename));
-       start = util_strlcat(filename, "/.udev/names/", sizeof(filename));
-       util_strlcat(filename, &name[devlen], sizeof(filename));
-       util_path_encode(&filename[start], sizeof(filename) - start);
-       /* entry with the devpath */
-       util_strlcpy(device, devpath, sizeof(device));
-       util_path_encode(device, sizeof(device));
-       util_strlcat(filename, "/", sizeof(filename));
-       util_strlcat(filename, device, sizeof(filename));
+       util_path_encode(&name[strlen(udev_get_dev_path(udev))+1], name_enc, sizeof(name_enc));
+       util_path_encode(devpath, devpath_enc, sizeof(devpath_enc));
+       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev),
+                     "/.udev/names/", name_enc, "/", devpath_enc, NULL);
 
        if (add) {
                dbg(udev, "creating index: '%s'\n", filename);
 
        if (add) {
                dbg(udev, "creating index: '%s'\n", filename);
@@ -68,7 +61,6 @@ static int name_index(struct udev *udev, const char *devpath, const char *name,
 int udev_node_mknod(struct udev_device *dev, const char *file, dev_t devnum, mode_t mode, uid_t uid, gid_t gid)
 {
        struct udev *udev = udev_device_get_udev(dev);
 int udev_node_mknod(struct udev_device *dev, const char *file, dev_t devnum, mode_t mode, uid_t uid, gid_t gid)
 {
        struct udev *udev = udev_device_get_udev(dev);
-       char file_tmp[UTIL_PATH_SIZE + sizeof(TMP_FILE_EXT)];
        struct stat stats;
        int preserve = 0;
        int err = 0;
        struct stat stats;
        int preserve = 0;
        int err = 0;
@@ -90,9 +82,10 @@ int udev_node_mknod(struct udev_device *dev, const char *file, dev_t devnum, mod
                        preserve = 1;
                        udev_selinux_lsetfilecon(udev, file, mode);
                } else {
                        preserve = 1;
                        udev_selinux_lsetfilecon(udev, file, mode);
                } else {
+                       char file_tmp[UTIL_PATH_SIZE + sizeof(TMP_FILE_EXT)];
+
                        info(udev, "atomically replace existing file '%s'\n", file);
                        info(udev, "atomically replace existing file '%s'\n", file);
-                       util_strlcpy(file_tmp, file, sizeof(file_tmp));
-                       util_strlcat(file_tmp, TMP_FILE_EXT, sizeof(file_tmp));
+                       util_strscpyl(file_tmp, sizeof(file_tmp), file, TMP_FILE_EXT, NULL);
                        unlink(file_tmp);
                        udev_selinux_setfscreatecon(udev, file_tmp, mode);
                        err = mknod(file_tmp, mode, devnum);
                        unlink(file_tmp);
                        udev_selinux_setfscreatecon(udev, file_tmp, mode);
                        err = mknod(file_tmp, mode, devnum);
@@ -144,10 +137,11 @@ static int node_symlink(struct udev *udev, const char *node, const char *slink)
 {
        struct stat stats;
        char target[UTIL_PATH_SIZE];
 {
        struct stat stats;
        char target[UTIL_PATH_SIZE];
+       char *s;
+       size_t l;
        char slink_tmp[UTIL_PATH_SIZE + sizeof(TMP_FILE_EXT)];
        int i = 0;
        int tail = 0;
        char slink_tmp[UTIL_PATH_SIZE + sizeof(TMP_FILE_EXT)];
        int i = 0;
        int tail = 0;
-       int len;
        int err = 0;
 
        /* use relative link */
        int err = 0;
 
        /* use relative link */
@@ -157,12 +151,18 @@ static int node_symlink(struct udev *udev, const char *node, const char *slink)
                        tail = i+1;
                i++;
        }
                        tail = i+1;
                i++;
        }
+       s = target;
+       l = sizeof(target);
        while (slink[i] != '\0') {
                if (slink[i] == '/')
        while (slink[i] != '\0') {
                if (slink[i] == '/')
-                       util_strlcat(target, "../", sizeof(target));
+                       l = util_strpcpy(&s, l, "../");
                i++;
        }
                i++;
        }
-       util_strlcat(target, &node[tail], sizeof(target));
+       l = util_strscpy(s, l, &node[tail]);
+       if (l == 0) {
+               err = -EINVAL;
+               goto exit;
+       }
 
        /* preserve link with correct target, do not replace node of other device */
        if (lstat(slink, &stats) == 0) {
 
        /* preserve link with correct target, do not replace node of other device */
        if (lstat(slink, &stats) == 0) {
@@ -184,6 +184,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];
                        }
                } else if (S_ISLNK(stats.st_mode)) {
                        char buf[UTIL_PATH_SIZE];
+                       int len;
 
                        dbg(udev, "found existing symlink '%s'\n", slink);
                        len = readlink(slink, buf, sizeof(buf));
 
                        dbg(udev, "found existing symlink '%s'\n", slink);
                        len = readlink(slink, buf, sizeof(buf));
@@ -207,8 +208,7 @@ static int node_symlink(struct udev *udev, const char *node, const char *slink)
        }
 
        info(udev, "atomically replace '%s'\n", slink);
        }
 
        info(udev, "atomically replace '%s'\n", slink);
-       util_strlcpy(slink_tmp, slink, sizeof(slink_tmp));
-       util_strlcat(slink_tmp, TMP_FILE_EXT, sizeof(slink_tmp));
+       util_strscpyl(slink_tmp, sizeof(slink_tmp), slink, TMP_FILE_EXT, NULL);
        unlink(slink_tmp);
        udev_selinux_setfscreatecon(udev, slink, S_IFLNK);
        err = symlink(target, slink_tmp);
        unlink(slink_tmp);
        udev_selinux_setfscreatecon(udev, slink, S_IFLNK);
        err = symlink(target, slink_tmp);
@@ -221,7 +221,6 @@ static int node_symlink(struct udev *udev, const char *node, const char *slink)
        if (err != 0) {
                err(udev, "rename(%s, %s) failed: %m\n", slink_tmp, slink);
                unlink(slink_tmp);
        if (err != 0) {
                err(udev, "rename(%s, %s) failed: %m\n", slink_tmp, slink);
                unlink(slink_tmp);
-               goto exit;
        }
 exit:
        return err;
        }
 exit:
        return err;
@@ -229,16 +228,16 @@ exit:
 
 static int name_index_get_devices(struct udev *udev, const char *name, struct udev_list_node *dev_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;
-       size_t start;
+       char dirname[UTIL_PATH_SIZE];
+       char *s;
+       size_t l;
        DIR *dir;
        int count = 0;
 
        DIR *dir;
        int count = 0;
 
-       util_strlcpy(dirname, udev_get_dev_path(udev), sizeof(dirname));
-       start = util_strlcat(dirname, "/.udev/names/", sizeof(dirname));
-       util_strlcat(dirname, &name[devlen], sizeof(dirname));
-       util_path_encode(&dirname[start], sizeof(dirname) - start);
+       s = dirname;
+       l = util_strpcpyl(&s, sizeof(dirname), udev_get_dev_path(udev),
+                     "/.udev/names/", NULL);
+       util_path_encode(&name[strlen(udev_get_dev_path(udev))+1], s, l);
        dir = opendir(dirname);
        if (dir == NULL) {
                dbg(udev, "no index directory '%s': %m\n", dirname);
        dir = opendir(dirname);
        if (dir == NULL) {
                dbg(udev, "no index directory '%s': %m\n", dirname);
@@ -257,8 +256,7 @@ static int name_index_get_devices(struct udev *udev, const char *name, struct ud
                if (ent->d_name[0] == '.')
                        continue;
 
                if (ent->d_name[0] == '.')
                        continue;
 
-               util_strlcpy(device, udev_get_sys_path(udev), sizeof(device));
-               util_strlcat(device, ent->d_name, sizeof(device));
+               util_strscpyl(device, sizeof(device), udev_get_sys_path(udev), ent->d_name, NULL);
                util_path_decode(device);
                udev_list_entry_add(udev, dev_list, device, NULL, 1, 0);
                count++;
                util_path_decode(device);
                udev_list_entry_add(udev, dev_list, device, NULL, 1, 0);
                count++;
@@ -268,7 +266,7 @@ out:
        return count;
 }
 
        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);
        struct udev_list_node dev_list;
 {
        struct udev *udev = udev_device_get_udev(dev);
        struct udev_list_node dev_list;
@@ -288,10 +286,8 @@ static int update_link(struct udev_device *dev, const char *slink, int test)
        /* if we don't have a reference, delete it */
        if (count <= 0) {
                info(udev, "no reference left, remove '%s'\n", 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);
-                       util_delete_path(udev, slink);
-               }
+               unlink(slink);
+               util_delete_path(udev, slink);
                goto out;
        }
 
                goto out;
        }
 
@@ -314,7 +310,7 @@ static int update_link(struct udev_device *dev, const char *slink, int test)
                                     udev_device_get_devnode(dev));
                        } else if (target[0] == '\0' || udev_device_get_devlink_priority(dev) >= priority) {
                                priority = udev_device_get_devlink_priority(dev);
                                     udev_device_get_devnode(dev));
                        } else if (target[0] == '\0' || udev_device_get_devlink_priority(dev) >= priority) {
                                priority = udev_device_get_devlink_priority(dev);
-                               util_strlcpy(target, udev_device_get_devnode(dev), sizeof(target));
+                               util_strscpy(target, sizeof(target), udev_device_get_devnode(dev));
                        }
                        continue;
                }
                        }
                        continue;
                }
@@ -335,7 +331,7 @@ static int update_link(struct udev_device *dev, const char *slink, int test)
                                    priority);
                                if (target[0] == '\0' || udev_device_get_devlink_priority(dev_db) > priority) {
                                        priority = 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));
+                                       util_strscpy(target, sizeof(target), devnode);
                                }
                        }
                }
                                }
                        }
                }
@@ -351,15 +347,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);
 
        /* 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) {
-               util_create_path(udev, slink);
-               node_symlink(udev, target, slink);
-       }
+       util_create_path(udev, slink);
+       node_symlink(udev, target, slink);
 out:
        return rc;
 }
 
 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;
 {
        struct udev *udev = udev_device_get_udev(dev);
        struct udev_list_entry *list_entry;
@@ -371,37 +365,46 @@ void udev_node_update_old_links(struct udev_device *dev, struct udev_device *dev
                struct udev_list_entry *list_entry_current;
                int found;
 
                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)) {
                        const char *name_current = udev_list_entry_get_name(list_entry_current);
 
                found = 0;
                udev_list_entry_foreach(list_entry_current, udev_device_get_devlinks_list_entry(dev)) {
                        const char *name_current = udev_list_entry_get_name(list_entry_current);
 
-                       if (strcmp(name_current, name) == 0) {
+                       if (strcmp(name, name_current) == 0) {
                                found = 1;
                                break;
                        }
                }
                if (found)
                        continue;
                                found = 1;
                                break;
                        }
                }
                if (found)
                        continue;
-               /* link does no longer belong to this device */
-               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, test);
-               update_link(dev, name, test);
+
+               info(udev, "update old name, '%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);
        }
 
        /*
         * if the node name has changed, delete the node,
        }
 
        /*
         * if the node name has changed, delete the node,
-        * and possibly restore a symlink of another device
+        * and possibly restore a symlink of a different device
         */
        devnode_old = udev_device_get_devnode(dev_old);
        if (devnode_old != NULL) {
                const char *devnode = udev_device_get_devnode(dev);
 
         */
        devnode_old = udev_device_get_devnode(dev_old);
        if (devnode_old != NULL) {
                const char *devnode = udev_device_get_devnode(dev);
 
-               if (devnode != NULL && strcmp(devnode_old, devnode) != 0)
-                       update_link(dev, devnode_old, test);
+               if (devnode != NULL && strcmp(devnode_old, devnode) != 0) {
+                       info(udev, "node has changed from '%s' to '%s'\n", devnode_old, devnode);
+                       name_index(udev, udev_device_get_devpath(dev), devnode_old, 0);
+                       update_link(dev, devnode_old);
+               }
        }
 }
 
        }
 }
 
-int udev_node_add(struct udev_device *dev, mode_t mode, uid_t uid, gid_t gid, 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);
        int i;
 {
        struct udev *udev = udev_device_get_udev(dev);
        int i;
@@ -415,44 +418,41 @@ int udev_node_add(struct udev_device *dev, mode_t mode, uid_t uid, gid_t gid, in
             mode, uid, gid);
 
        util_create_path(udev, udev_device_get_devnode(dev));
             mode, uid, gid);
 
        util_create_path(udev, udev_device_get_devnode(dev));
-       if (!test)
-               if (udev_node_mknod(dev, NULL, makedev(0,0), mode, uid, gid) != 0) {
-                       err = -1;
-                       goto exit;
-               }
+       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);
 
        /* 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 to name index */
                }
        }
 
        /* add node to name index */
-       name_index(udev, udev_device_get_devpath(dev), udev_device_get_devnode(dev), 1, test);
+       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)) {
 
        /* 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;
 }
 
        }
 exit:
        return err;
 }
 
-extern int udev_node_remove(struct udev_device *dev, int test)
+int udev_node_remove(struct udev_device *dev)
 {
        struct udev *udev = udev_device_get_udev(dev);
        struct udev_list_entry *list_entry;
 {
        struct udev *udev = udev_device_get_udev(dev);
        struct udev_list_entry *list_entry;
@@ -463,12 +463,12 @@ extern int udev_node_remove(struct udev_device *dev, int test)
        int num;
 
        /* remove node from name index */
        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)) {
 
        /* 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);
        }
 
        devnode = udev_device_get_devnode(dev);
@@ -484,8 +484,7 @@ extern int udev_node_remove(struct udev_device *dev, int test)
        }
 
        info(udev, "removing device node '%s'\n", devnode);
        }
 
        info(udev, "removing device node '%s'\n", devnode);
-       if (!test)
-               err = util_unlink_secure(udev, devnode);
+       err = util_unlink_secure(udev, devnode);
        if (err)
                return err;
 
        if (err)
                return err;
 
@@ -499,8 +498,7 @@ 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';
                for (i = 1; i <= num; i++) {
                        snprintf(partitionname, sizeof(partitionname), "%s%d", devnode, i);
                        partitionname[sizeof(partitionname)-1] = '\0';
-                       if (!test)
-                               util_unlink_secure(udev, partitionname);
+                       util_unlink_secure(udev, partitionname);
                }
        }
        util_delete_path(udev, devnode);
                }
        }
        util_delete_path(udev, devnode);