chiark / gitweb /
delete name_list, move common file functions
[elogind.git] / udev / udev-util.c
index 4623c30caf60eb7b7dc0d0d984acc41a2d05a8b7..59c4d194dd4d1a447a9f29bd5035eb22205ced70 100644 (file)
 #include <fcntl.h>
 #include <errno.h>
 #include <ctype.h>
-#include <dirent.h>
-#include <syslog.h>
 #include <pwd.h>
 #include <grp.h>
-#include <sys/types.h>
-#include <sys/utsname.h>
 
 #include "udev.h"
 
-struct name_entry *name_list_add(struct udev *udev, struct list_head *name_list, const char *name, int sort)
+int create_path(struct udev *udev, const char *path)
 {
-       struct name_entry *name_loop;
-       struct name_entry *name_new;
-
-       /* avoid duplicate entries */
-       list_for_each_entry(name_loop, name_list, node) {
-               if (strcmp(name_loop->name, name) == 0) {
-                       dbg(udev, "'%s' is already in the list\n", name);
-                       return name_loop;
-               }
-       }
-
-       if (sort)
-               list_for_each_entry(name_loop, name_list, node) {
-                       if (strcmp(name_loop->name, name) > 0)
-                               break;
-               }
+       char p[UTIL_PATH_SIZE];
+       char *pos;
+       struct stat stats;
+       int ret;
 
-       name_new = malloc(sizeof(struct name_entry));
-       if (name_new == NULL)
-               return NULL;
-       memset(name_new, 0x00, sizeof(struct name_entry));
-       util_strlcpy(name_new->name, name, sizeof(name_new->name));
-       dbg(udev, "adding '%s'\n", name_new->name);
-       list_add_tail(&name_new->node, &name_loop->node);
+       util_strlcpy(p, path, sizeof(p));
+       pos = strrchr(p, '/');
+       if (pos == p || pos == NULL)
+               return 0;
 
-       return name_new;
-}
+       while (pos[-1] == '/')
+               pos--;
+       pos[0] = '\0';
 
-struct name_entry *name_list_key_add(struct udev *udev, struct list_head *name_list, const char *key, const char *value)
-{
-       struct name_entry *name_loop;
-       struct name_entry *name_new;
-       size_t keylen = strlen(key);
-
-       list_for_each_entry(name_loop, name_list, node) {
-               if (strncmp(name_loop->name, key, keylen) != 0)
-                       continue;
-               if (name_loop->name[keylen] != '=')
-                       continue;
-               dbg(udev, "key already present '%s', replace it\n", name_loop->name);
-               snprintf(name_loop->name, sizeof(name_loop->name), "%s=%s", key, value);
-               name_loop->name[sizeof(name_loop->name)-1] = '\0';
-               return name_loop;
-       }
+       dbg(udev, "stat '%s'\n", p);
+       if (stat(p, &stats) == 0 && (stats.st_mode & S_IFMT) == S_IFDIR)
+               return 0;
 
-       name_new = malloc(sizeof(struct name_entry));
-       if (name_new == NULL)
-               return NULL;
-       memset(name_new, 0x00, sizeof(struct name_entry));
-       snprintf(name_new->name, sizeof(name_new->name), "%s=%s", key, value);
-       name_new->name[sizeof(name_new->name)-1] = '\0';
-       dbg(udev, "adding '%s'\n", name_new->name);
-       list_add_tail(&name_new->node, &name_loop->node);
+       if (create_path(udev, p) != 0)
+               return -1;
 
-       return name_new;
+       dbg(udev, "mkdir '%s'\n", p);
+       udev_selinux_setfscreatecon(udev, p, S_IFDIR|0755);
+       ret = mkdir(p, 0755);
+       udev_selinux_resetfscreatecon(udev);
+       if (ret == 0)
+               return 0;
+
+       if (errno == EEXIST)
+               if (stat(p, &stats) == 0 && (stats.st_mode & S_IFMT) == S_IFDIR)
+                       return 0;
+       return -1;
 }
 
-int name_list_key_remove(struct udev *udev, struct list_head *name_list, const char *key)
+int delete_path(struct udev *udev, const char *path)
 {
-       struct name_entry *name_loop;
-       struct name_entry *name_tmp;
-       size_t keylen = strlen(key);
-       int retval = 0;
-
-       list_for_each_entry_safe(name_loop, name_tmp, name_list, node) {
-               if (strncmp(name_loop->name, key, keylen) != 0)
-                       continue;
-               if (name_loop->name[keylen] != '=')
-                       continue;
-               list_del(&name_loop->node);
-               free(name_loop);
-               retval = 1;
-               break;
-       }
-       return retval;
-}
+       char p[UTIL_PATH_SIZE];
+       char *pos;
+       int retval;
 
-void name_list_cleanup(struct udev *udev, struct list_head *name_list)
-{
-       struct name_entry *name_loop;
-       struct name_entry *name_tmp;
+       strcpy (p, path);
+       pos = strrchr(p, '/');
+       if (pos == p || pos == NULL)
+               return 0;
+
+       while (1) {
+               *pos = '\0';
+               pos = strrchr(p, '/');
+
+               /* don't remove the last one */
+               if ((pos == p) || (pos == NULL))
+                       break;
 
-       list_for_each_entry_safe(name_loop, name_tmp, name_list, node) {
-               list_del(&name_loop->node);
-               free(name_loop);
+               /* remove if empty */
+               retval = rmdir(p);
+               if (errno == ENOENT)
+                       retval = 0;
+               if (retval) {
+                       if (errno == ENOTEMPTY)
+                               return 0;
+                       err(udev, "rmdir(%s) failed: %m\n", p);
+                       break;
+               }
+               dbg(udev, "removed '%s'\n", p);
        }
+       return 0;
 }
 
-/* calls function for every file found in specified directory */
-int add_matching_files(struct udev *udev, struct list_head *name_list, const char *dirname, const char *suffix)
+/* Reset permissions on the device node, before unlinking it to make sure,
+ * that permisions of possible hard links will be removed too.
+ */
+int unlink_secure(struct udev *udev, const char *filename)
 {
-       struct dirent *ent;
-       DIR *dir;
-       char filename[UTIL_PATH_SIZE];
-
-       dbg(udev, "open directory '%s'\n", dirname);
-       dir = opendir(dirname);
-       if (dir == NULL) {
-               err(udev, "unable to open '%s': %m\n", dirname);
-               return -1;
-       }
+       int retval;
 
-       while (1) {
-               ent = readdir(dir);
-               if (ent == NULL || ent->d_name[0] == '\0')
-                       break;
-
-               if ((ent->d_name[0] == '.') || (ent->d_name[0] == '#'))
-                       continue;
+       retval = chown(filename, 0, 0);
+       if (retval)
+               err(udev, "chown(%s, 0, 0) failed: %m\n", filename);
 
-               /* look for file matching with specified suffix */
-               if (suffix != NULL) {
-                       const char *ext;
+       retval = chmod(filename, 0000);
+       if (retval)
+               err(udev, "chmod(%s, 0000) failed: %m\n", filename);
 
-                       ext = strrchr(ent->d_name, '.');
-                       if (ext == NULL)
-                               continue;
-                       if (strcmp(ext, suffix) != 0)
-                               continue;
-               }
-               dbg(udev, "put file '%s/%s' into list\n", dirname, ent->d_name);
+       retval = unlink(filename);
+       if (errno == ENOENT)
+               retval = 0;
 
-               snprintf(filename, sizeof(filename), "%s/%s", dirname, ent->d_name);
-               filename[sizeof(filename)-1] = '\0';
-               name_list_add(udev, name_list, filename, 1);
-       }
+       if (retval)
+               err(udev, "unlink(%s) failed: %m\n", filename);
 
-       closedir(dir);
-       return 0;
+       return retval;
 }
 
 uid_t lookup_user(struct udev *udev, const char *user)
@@ -200,4 +158,3 @@ extern gid_t lookup_group(struct udev *udev, const char *group)
 
        return gid;
 }
-