chiark / gitweb /
[PATCH] PATCH udev close on exec
[elogind.git] / udev_lib.c
index 4a9eea506cacaf8171313719a33a4b27ae2d185b..4991ec3acb4447699b34e2a643c76429a5d04833 100644 (file)
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <stddef.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
 
 #include "libsysfs/sysfs/libsysfs.h"
 #include "udev.h"
+#include "logging.h"
 #include "udev_lib.h"
+#include "list.h"
 
 
 char *get_action(void)
@@ -53,15 +58,15 @@ char *get_devpath(void)
        return devpath;
 }
 
-char *get_devnode(void)
+char *get_devname(void)
 {
-       char *devnode;
+       char *devname;
 
-       devnode = getenv("DEVNODE");
-       if (devnode != NULL && strlen(devnode) > NAME_SIZE)
-               devnode[NAME_SIZE-1] = '\0';
+       devname = getenv("DEVNAME");
+       if (devname != NULL && strlen(devname) > NAME_SIZE)
+               devname[NAME_SIZE-1] = '\0';
 
-       return devnode;
+       return devname;
 }
 
 char *get_seqnum(void)
@@ -81,17 +86,28 @@ char *get_subsystem(char *subsystem)
        return subsystem;
 }
 
+#define BLOCK_PATH             "/block/"
+#define CLASS_PATH             "/class/"
+#define NET_PATH               "/class/net/"
+
 char get_device_type(const char *path, const char *subsystem)
 {
-       if (strcmp(subsystem, "block") == 0 ||
-           strstr(path, "/block/") != NULL)
+       if (strcmp(subsystem, "block") == 0)
+               return 'b';
+
+       if (strcmp(subsystem, "net") == 0)
+               return 'n';
+
+       if (strncmp(path, BLOCK_PATH, strlen(BLOCK_PATH)) == 0 &&
+           strlen(path) > strlen(BLOCK_PATH))
                return 'b';
 
-       if (strcmp(subsystem, "net") == 0 ||
-           strstr(path, "/class/net/") != NULL)
+       if (strncmp(path, NET_PATH, strlen(NET_PATH)) == 0 &&
+           strlen(path) > strlen(NET_PATH))
                return 'n';
 
-       if (strstr(path, "/class/") != NULL)
+       if (strncmp(path, CLASS_PATH, strlen(CLASS_PATH)) == 0 &&
+           strlen(path) > strlen(CLASS_PATH))
                return 'c';
 
        return '\0';
@@ -108,11 +124,13 @@ int file_map(const char *filename, char **buf, size_t *bufsize)
        }
 
        if (fstat(fd, &stats) < 0) {
+               close(fd);
                return -1;
        }
 
        *buf = mmap(NULL, stats.st_size, PROT_READ, MAP_SHARED, fd, 0);
        if (*buf == MAP_FAILED) {
+               close(fd);
                return -1;
        }
        *bufsize = stats.st_size;
@@ -136,3 +154,123 @@ size_t buf_get_line(char *buf, size_t buflen, size_t cur)
        return count - cur;
 }
 
+void leading_slash(char *path)
+{
+       int len;
+
+       len = strlen(path);
+       if (len > 0 && path[len-1] != '/') {
+               path[len] = '/';
+               path[len+1] = '\0';
+       }
+}
+
+void no_leading_slash(char *path)
+{
+       int len;
+
+       len = strlen(path);
+       if (len > 0 && path[len-1] == '/')
+               path[len-1] = '\0';
+}
+
+struct files {
+       struct list_head list;
+       char name[NAME_SIZE];
+};
+
+/* sort files in lexical order */
+static int file_list_insert(char *filename, struct list_head *file_list)
+{
+       struct files *loop_file;
+       struct files *new_file;
+
+       list_for_each_entry(loop_file, file_list, list) {
+               if (strcmp(loop_file->name, filename) > 0) {
+                       break;
+               }
+       }
+
+       new_file = malloc(sizeof(struct files));
+       if (new_file == NULL) {
+               dbg("error malloc");
+               return -ENOMEM;
+       }
+
+       strfieldcpy(new_file->name, filename);
+       list_add_tail(&new_file->list, &loop_file->list);
+       return 0;
+}
+
+/* calls function for every file found in specified directory */
+int call_foreach_file(int fnct(char *f) , char *dirname, char *suffix)
+{
+       struct dirent *ent;
+       DIR *dir;
+       char *ext;
+       char file[NAME_SIZE];
+       struct files *loop_file;
+       struct files *tmp_file;
+       LIST_HEAD(file_list);
+
+       dbg("open directory '%s'", dirname);
+       dir = opendir(dirname);
+       if (dir == NULL) {
+               dbg("unable to open '%s'", dirname);
+               return -1;
+       }
+
+       while (1) {
+               ent = readdir(dir);
+               if (ent == NULL || ent->d_name[0] == '\0')
+                       break;
+
+               if ((ent->d_name[0] == '.') || (ent->d_name[0] == COMMENT_CHARACTER))
+                       continue;
+
+               /* look for file with specified suffix */
+               ext = strrchr(ent->d_name, '.');
+               if (ext == NULL)
+                       continue;
+
+               if (strcmp(ext, suffix) != 0)
+                       continue;
+
+               dbg("put file '%s/%s' in list", dirname, ent->d_name);
+               file_list_insert(ent->d_name, &file_list);
+       }
+
+       /* call function for every file in the list */
+       list_for_each_entry_safe(loop_file, tmp_file, &file_list, list) {
+               strfieldcpy(file, dirname);
+               strfieldcat(file, "/");
+               strfieldcat(file, loop_file->name);
+
+               fnct(file);
+
+               list_del(&loop_file->list);
+               free(loop_file);
+       }
+
+       closedir(dir);
+       return 0;
+}
+
+/* Set the FD_CLOEXEC  flag of desc if value is nonzero,
+   or clear the flag if value is 0.
+   Return 0 on success, or -1 on error with errno  set. */ 
+       
+int set_cloexec_flag (int desc, int value)
+{
+       int oldflags = fcntl (desc, F_GETFD, 0);
+       /* If reading the flags failed, return error indication now. */
+       if (oldflags < 0)
+               return oldflags;
+       /* Set just the flag we want to set. */
+       if (value != 0)
+               oldflags |= FD_CLOEXEC;
+       else
+               oldflags &= ~FD_CLOEXEC;
+       /* Store modified flag word in the descriptor. */
+       return fcntl (desc, F_SETFD, oldflags);
+}