chiark / gitweb /
udev/libudev: event - move {OLD_,}INTERFACE handling from udevd to libudev
[elogind.git] / src / libudev / libudev-device.c
index 37e75d280fa6ed440610036916e0c14b6b1a101d..978b03dd0da02dd97052c7d781da8ccc978b290d 100644 (file)
@@ -139,7 +139,7 @@ static int udev_device_set_ifindex(struct udev_device *udev_device, int ifindex)
         char num[32];
 
         udev_device->ifindex = ifindex;
-        snprintf(num, sizeof(num), "%u", ifindex);
+        snprintf(num, sizeof(num), "%d", ifindex);
         udev_device_add_property(udev_device, "IFINDEX", num);
         return 0;
 }
@@ -161,7 +161,7 @@ _public_ dev_t udev_device_get_devnum(struct udev_device *udev_device)
         return udev_device->devnum;
 }
 
-int udev_device_set_devnum(struct udev_device *udev_device, dev_t devnum)
+static int udev_device_set_devnum(struct udev_device *udev_device, dev_t devnum)
 {
         char num[32];
 
@@ -258,7 +258,7 @@ static int udev_device_set_devtype(struct udev_device *udev_device, const char *
         return 0;
 }
 
-int udev_device_set_subsystem(struct udev_device *udev_device, const char *subsystem)
+static int udev_device_set_subsystem(struct udev_device *udev_device, const char *subsystem)
 {
         free(udev_device->subsystem);
         udev_device->subsystem = strdup(subsystem);
@@ -392,6 +392,44 @@ static struct udev_list_entry *udev_device_add_property_from_string(struct udev_
         return udev_device_add_property(udev_device, name, val);
 }
 
+static int udev_device_set_syspath(struct udev_device *udev_device, const char *syspath)
+{
+        const char *pos;
+        size_t len;
+
+        free(udev_device->syspath);
+        udev_device->syspath = strdup(syspath);
+        if (udev_device->syspath ==  NULL)
+                return -ENOMEM;
+        udev_device->devpath = udev_device->syspath + strlen("/sys");
+        udev_device_add_property(udev_device, "DEVPATH", udev_device->devpath);
+
+        pos = strrchr(udev_device->syspath, '/');
+        if (pos == NULL)
+                return -EINVAL;
+        udev_device->sysname = strdup(&pos[1]);
+        if (udev_device->sysname == NULL)
+                return -ENOMEM;
+
+        /* some devices have '!' in their name, change that to '/' */
+        len = 0;
+        while (udev_device->sysname[len] != '\0') {
+                if (udev_device->sysname[len] == '!')
+                        udev_device->sysname[len] = '/';
+                len++;
+        }
+
+        /* trailing number */
+        while (len > 0 && isdigit(udev_device->sysname[--len]))
+                udev_device->sysnum = &udev_device->sysname[len];
+
+        /* sysname is completely numeric */
+        if (len == 0)
+                udev_device->sysnum = NULL;
+
+        return 0;
+}
+
 /*
  * parse property string, and if needed, update internal values accordingly
  *
@@ -401,7 +439,7 @@ static struct udev_list_entry *udev_device_add_property_from_string(struct udev_
  * udev_device_set_info_loaded() needs to be set, to avoid trying
  * to use a device without a DEVPATH set
  */
-void udev_device_add_property_from_string_parse(struct udev_device *udev_device, const char *property)
+static void udev_device_add_property_from_string_parse(struct udev_device *udev_device, const char *property)
 {
         if (startswith(property, "DEVPATH=")) {
                 char path[UTIL_PATH_SIZE];
@@ -477,7 +515,7 @@ void udev_device_add_property_from_string_parse(struct udev_device *udev_device,
         }
 }
 
-int udev_device_add_property_from_string_parse_finish(struct udev_device *udev_device)
+static int udev_device_add_property_from_string_parse_finish(struct udev_device *udev_device)
 {
         if (udev_device->maj > 0)
                 udev_device_set_devnum(udev_device, makedev(udev_device->maj, udev_device->min));
@@ -534,10 +572,8 @@ int udev_device_read_db(struct udev_device *udev_device, const char *dbfile)
         }
 
         f = fopen(dbfile, "re");
-        if (f == NULL) {
-                log_debug("no db file to read %s: %m\n", dbfile);
-                return -errno;
-        }
+        if (f == NULL)
+                return log_debug_errno(errno, "no db file to read %s: %m", dbfile);
 
         /* devices with a database entry are initialized */
         udev_device->is_initialized = true;
@@ -577,7 +613,7 @@ int udev_device_read_db(struct udev_device *udev_device, const char *dbfile)
         }
         fclose(f);
 
-        log_debug("device %p filled with db file data\n", udev_device);
+        log_debug("device %p filled with db file data", udev_device);
         return 0;
 }
 
@@ -639,7 +675,7 @@ void udev_device_set_info_loaded(struct udev_device *device)
         device->info_loaded = true;
 }
 
-struct udev_device *udev_device_new(struct udev *udev)
+static struct udev_device *udev_device_new(struct udev *udev)
 {
         struct udev_device *udev_device;
 
@@ -699,7 +735,7 @@ _public_ struct udev_device *udev_device_new_from_syspath(struct udev *udev, con
 
         /* path starts in sys */
         if (!startswith(syspath, "/sys")) {
-                log_debug("not in sys :%s\n", syspath);
+                log_debug("not in sys :%s", syspath);
                 errno = EINVAL;
                 return NULL;
         }
@@ -725,8 +761,13 @@ _public_ struct udev_device *udev_device_new_from_syspath(struct udev *udev, con
                         return NULL;
         } else {
                 /* everything else just needs to be a directory */
-                if (stat(path, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
+                if (stat(path, &statbuf) != 0)
+                        return NULL;
+
+                if (!S_ISDIR(statbuf.st_mode)) {
+                        errno = EISDIR;
                         return NULL;
+                }
         }
 
         udev_device = udev_device_new(udev);
@@ -734,7 +775,7 @@ _public_ struct udev_device *udev_device_new_from_syspath(struct udev *udev, con
                 return NULL;
 
         udev_device_set_syspath(udev_device, path);
-        log_debug("device %p has devpath '%s'\n", udev_device, udev_device_get_devpath(udev_device));
+        log_debug("device %p has devpath '%s'", udev_device, udev_device_get_devpath(udev_device));
 
         return udev_device;
 }
@@ -966,7 +1007,7 @@ _public_ struct udev_device *udev_device_new_from_environment(struct udev *udev)
                 udev_device_add_property_from_string_parse(udev_device, environ[i]);
 
         if (udev_device_add_property_from_string_parse_finish(udev_device) < 0) {
-                log_debug("missing values, invalid device\n");
+                log_debug("missing values, invalid device");
                 udev_device_unref(udev_device);
                 udev_device = NULL;
         }
@@ -1604,44 +1645,6 @@ _public_ struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_
         return udev_list_get_entry(&udev_device->sysattr_list);
 }
 
-int udev_device_set_syspath(struct udev_device *udev_device, const char *syspath)
-{
-        const char *pos;
-        size_t len;
-
-        free(udev_device->syspath);
-        udev_device->syspath = strdup(syspath);
-        if (udev_device->syspath ==  NULL)
-                return -ENOMEM;
-        udev_device->devpath = udev_device->syspath + strlen("/sys");
-        udev_device_add_property(udev_device, "DEVPATH", udev_device->devpath);
-
-        pos = strrchr(udev_device->syspath, '/');
-        if (pos == NULL)
-                return -EINVAL;
-        udev_device->sysname = strdup(&pos[1]);
-        if (udev_device->sysname == NULL)
-                return -ENOMEM;
-
-        /* some devices have '!' in their name, change that to '/' */
-        len = 0;
-        while (udev_device->sysname[len] != '\0') {
-                if (udev_device->sysname[len] == '!')
-                        udev_device->sysname[len] = '/';
-                len++;
-        }
-
-        /* trailing number */
-        while (len > 0 && isdigit(udev_device->sysname[--len]))
-                udev_device->sysnum = &udev_device->sysname[len];
-
-        /* sysname is completely numeric */
-        if (len == 0)
-                udev_device->sysnum = NULL;
-
-        return 0;
-}
-
 static int udev_device_set_devnode(struct udev_device *udev_device, const char *devnode)
 {
         free(udev_device->devnode);
@@ -1683,7 +1686,7 @@ const char *udev_device_get_id_filename(struct udev_device *udev_device)
                                 udev_device->id_filename = NULL;
                 } else if (udev_device_get_ifindex(udev_device) > 0) {
                         /* use netdev ifindex -- n3 */
-                        if (asprintf(&udev_device->id_filename, "n%u", udev_device_get_ifindex(udev_device)) < 0)
+                        if (asprintf(&udev_device->id_filename, "n%i", udev_device_get_ifindex(udev_device)) < 0)
                                 udev_device->id_filename = NULL;
                 } else {
                         /*
@@ -1919,3 +1922,99 @@ void udev_device_set_db_persist(struct udev_device *udev_device)
 {
         udev_device->db_persist = true;
 }
+
+int udev_device_rename(struct udev_device *udev_device, const char *name)
+{
+        _cleanup_free_ char *dirname = NULL;
+        const char *interface;
+        char *new_syspath;
+        int r;
+
+        if (udev_device == NULL || name == NULL)
+                return -EINVAL;
+
+        dirname = dirname_malloc(udev_device->syspath);
+        if (!dirname)
+                return -ENOMEM;
+
+        new_syspath = strjoina(dirname, "/", name);
+
+        r = udev_device_set_syspath(udev_device, new_syspath);
+        if (r < 0)
+                return r;
+
+        interface = udev_device_get_property_value(udev_device, "INTERFACE");
+        if (interface) {
+                /* like DEVPATH_OLD, INTERFACE_OLD is not saved to the db, but only stays around for the current event */
+                udev_device_add_property(udev_device, "INTERFACE_OLD", interface);
+                udev_device_add_property(udev_device, "INTERFACE", name);
+        }
+
+        return 0;
+}
+
+struct udev_device *udev_device_shallow_clone(struct udev_device *old_device)
+{
+        struct udev_device *device;
+
+        if (old_device == NULL)
+                return NULL;
+
+        device = udev_device_new(old_device->udev);
+        if (!device) {
+                errno = ENOMEM;
+
+                return NULL;
+        }
+
+        udev_device_set_syspath(device, udev_device_get_syspath(old_device));
+        udev_device_set_subsystem(device, udev_device_get_subsystem(old_device));
+        udev_device_set_devnum(device, udev_device_get_devnum(old_device));
+
+        return device;
+}
+
+struct udev_device *udev_device_new_from_nulstr(struct udev *udev, char *nulstr, ssize_t buflen) {
+        struct udev_device *device;
+        ssize_t bufpos = 0;
+
+        if (nulstr == NULL || buflen <= 0) {
+                errno = EINVAL;
+
+                return NULL;
+        }
+
+        device = udev_device_new(udev);
+        if (!device) {
+                errno = ENOMEM;
+
+                return NULL;
+        }
+
+        udev_device_set_info_loaded(device);
+
+        while (bufpos < buflen) {
+                char *key;
+                size_t keylen;
+
+                key = nulstr + bufpos;
+                keylen = strlen(key);
+                if (keylen == 0)
+                        break;
+
+                bufpos += keylen + 1;
+                udev_device_add_property_from_string_parse(device, key);
+        }
+
+        if (udev_device_add_property_from_string_parse_finish(device) < 0) {
+                log_debug("missing values, invalid device");
+
+                udev_device_unref(device);
+
+                errno = EINVAL;
+
+                return NULL;
+        }
+
+        return device;
+}