chiark / gitweb /
udev_db.c: include <sys/stat.h>
[elogind.git] / udev_db.c
index 6e9a1187d03f4c94d0d19e1c609da5c6a65a97c1..99d73bd5afba9d11f4cb7feb1f650e8236ddba75 100644 (file)
--- a/udev_db.c
+++ b/udev_db.c
 #include <string.h>
 #include <errno.h>
 #include <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 
-#include "libsysfs/sysfs/libsysfs.h"
-#include "udev_libc_wrapper.h"
 #include "udev.h"
-#include "udev_utils.h"
-#include "logging.h"
 
 
 static int devpath_to_db_path(const char *devpath, char *filename, size_t len)
@@ -74,49 +72,54 @@ static int db_file_to_devpath(const char *filename, char *devpath, size_t len)
 int udev_db_add_device(struct udevice *udev)
 {
        char filename[PATH_SIZE];
-       struct name_entry *name_loop;
-       FILE *f;
 
        if (udev->test_run)
                return 0;
 
-       /* don't write anything if udev created only the node with the
-        * kernel name without any interesting data to remember
+       devpath_to_db_path(udev->dev->devpath, filename, sizeof(filename));
+       create_path(filename);
+
+       /*
+        * create only a symlink with the name as the target
+        * if we don't have any interesting data to remember
         */
-       if (strcmp(udev->name, udev->kernel_name) == 0 &&
-           list_empty(&udev->symlink_list) && list_empty(&udev->env_list) &&
+       if (list_empty(&udev->symlink_list) && list_empty(&udev->env_list) &&
            !udev->partitions && !udev->ignore_remove) {
-               dbg("nothing interesting to store in udevdb, skip");
-               goto exit;
-       }
-
-       devpath_to_db_path(udev->devpath, filename, sizeof(filename));
-       create_path(filename);
-       f = fopen(filename, "w");
-       if (f == NULL) {
-               err("unable to create db file '%s': %s", filename, strerror(errno));
-               return -1;
+               dbg("nothing interesting to store, create symlink");
+               unlink(filename);
+               if (symlink(udev->name, filename) != 0) {
+                       err("unable to create db link '%s': %s", filename, strerror(errno));
+                       return -1;
+               }
+       } else {
+               struct name_entry *name_loop;
+               FILE *f;
+
+               f = fopen(filename, "w");
+               if (f == NULL) {
+                       err("unable to create db file '%s': %s", filename, strerror(errno));
+                       return -1;
+               }
+               dbg("storing data for device '%s' in '%s'", udev->dev->devpath, filename);
+
+               fprintf(f, "N:%s\n", udev->name);
+               list_for_each_entry(name_loop, &udev->symlink_list, node)
+                       fprintf(f, "S:%s\n", name_loop->name);
+               fprintf(f, "M:%u:%u\n", major(udev->devt), minor(udev->devt));
+               if (udev->partitions)
+                       fprintf(f, "A:%u\n", udev->partitions);
+               if (udev->ignore_remove)
+                       fprintf(f, "R:%u\n", udev->ignore_remove);
+               list_for_each_entry(name_loop, &udev->env_list, node)
+                       fprintf(f, "E:%s\n", name_loop->name);
+               fclose(f);
        }
-       dbg("storing data for device '%s' in '%s'", udev->devpath, filename);
-
-       fprintf(f, "N:%s\n", udev->name);
-       list_for_each_entry(name_loop, &udev->symlink_list, node)
-               fprintf(f, "S:%s\n", name_loop->name);
-       fprintf(f, "M:%u:%u\n", major(udev->devt), minor(udev->devt));
-       if (udev->partitions)
-               fprintf(f, "A:%u\n", udev->partitions);
-       if (udev->ignore_remove)
-               fprintf(f, "R:%u\n", udev->ignore_remove);
-       list_for_each_entry(name_loop, &udev->env_list, node)
-               fprintf(f, "E:%s\n", name_loop->name);
-       fclose(f);
-
-exit:
        return 0;
 }
 
 int udev_db_get_device(struct udevice *udev, const char *devpath)
 {
+       struct stat stats;
        char filename[PATH_SIZE];
        char line[PATH_SIZE];
        unsigned int major, minor;
@@ -126,13 +129,35 @@ int udev_db_get_device(struct udevice *udev, const char *devpath)
        size_t cur;
        size_t count;
 
+       strlcpy(udev->dev->devpath, devpath, sizeof(udev->dev->devpath));
        devpath_to_db_path(devpath, filename, sizeof(filename));
-       if (file_map(filename, &buf, &bufsize) != 0) {
+
+       if (lstat(filename, &stats) != 0) {
                info("no db file to read %s: %s", filename, strerror(errno));
                return -1;
        }
+       if ((stats.st_mode & S_IFMT) == S_IFLNK) {
+               char target[NAME_SIZE];
+               int target_len;
+
+               info("found a symlink as db file");
+               target_len = readlink(filename, target, sizeof(target));
+               if (target_len > 0)
+                       target[target_len] = '\0';
+               else {
+                       info("error reading db link %s: %s", filename, strerror(errno));
+                       return -1;
+               }
+               dbg("db link points to '%s'", target);
+               strlcpy(udev->name, target, sizeof(udev->name));
+               return 0;
+       }
+
+       if (file_map(filename, &buf, &bufsize) != 0) {
+               info("error reading db file %s: %s", filename, strerror(errno));
+               return -1;
+       }
 
-       strlcpy(udev->devpath, devpath, sizeof(udev->devpath));
        cur = 0;
        while (cur < bufsize) {
                count = buf_get_line(buf, bufsize, cur);
@@ -196,7 +221,7 @@ int udev_db_delete_device(struct udevice *udev)
 {
        char filename[PATH_SIZE];
 
-       devpath_to_db_path(udev->devpath, filename, sizeof(filename));
+       devpath_to_db_path(udev->dev->devpath, filename, sizeof(filename));
        unlink(filename);
 
        return 0;
@@ -212,7 +237,7 @@ int udev_db_lookup_name(const char *name, char *devpath, size_t len)
        strlcat(dbpath, "/"DB_DIR, sizeof(dbpath));
        dir = opendir(dbpath);
        if (dir == NULL) {
-               err("unable to open udev_db '%s': %s", dbpath, strerror(errno));
+               info("no udev_db available '%s': %s", dbpath, strerror(errno));
                return -1;
        }
 
@@ -220,6 +245,7 @@ int udev_db_lookup_name(const char *name, char *devpath, size_t len)
                struct dirent *ent;
                char filename[PATH_SIZE];
                char nodename[PATH_SIZE];
+               struct stat stats;
                char *bufline;
                char *buf;
                size_t bufsize;
@@ -236,8 +262,32 @@ int udev_db_lookup_name(const char *name, char *devpath, size_t len)
                filename[sizeof(filename)-1] = '\0';
                dbg("looking at '%s'", filename);
 
+               if (lstat(filename, &stats) != 0) {
+                       info("unable to read %s: %s", filename, strerror(errno));
+                       continue;
+               }
+               if ((stats.st_mode & S_IFMT) == S_IFLNK) {
+                       char target[NAME_SIZE];
+                       int target_len;
+
+                       info("found a symlink as db file");
+                       target_len = readlink(filename, target, sizeof(target));
+                       if (target_len > 0)
+                               target[target_len] = '\0';
+                       else {
+                               info("error reading db link %s: %s", filename, strerror(errno));
+                               return -1;
+                       }
+                       dbg("db link points to '%s'", target);
+                       if (strcmp(name, target) == 0) {
+                               db_file_to_devpath(ent->d_name, devpath, len);
+                               found =1;
+                       }
+                       continue;
+               }
+
                if (file_map(filename, &buf, &bufsize) != 0) {
-                       err("unable to read db file '%s': %s", filename, strerror(errno));
+                       info("unable to read db file '%s': %s", filename, strerror(errno));
                        continue;
                }
 
@@ -283,7 +333,7 @@ int udev_db_get_all_entries(struct list_head *name_list)
        strlcat(dbpath, "/"DB_DIR, sizeof(dbpath));
        dir = opendir(dbpath);
        if (dir == NULL) {
-               err("unable to open udev_db '%s': %s", dbpath, strerror(errno));
+               info("no udev_db available '%s': %s", dbpath, strerror(errno));
                return -1;
        }