X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flibudev%2Flibudev-device.c;h=825a0e10f4fe31d8515d48f5005610f036320164;hp=b5b07fc5de0cd7c90e1356a35c11ccf022ee683a;hb=c4ef05484df942b6cc2037d33dd56cd209d1db9b;hpb=994e023433e020e2b3f683d5d1f2c974db580447 diff --git a/src/libudev/libudev-device.c b/src/libudev/libudev-device.c index b5b07fc5d..825a0e10f 100644 --- a/src/libudev/libudev-device.c +++ b/src/libudev/libudev-device.c @@ -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; } -static int udev_device_set_devnum(struct udev_device *udev_device, dev_t devnum) +int udev_device_set_devnum(struct udev_device *udev_device, dev_t devnum) { char num[32]; @@ -534,10 +534,10 @@ int udev_device_read_db(struct udev_device *udev_device, const char *dbfile) } f = fopen(dbfile, "re"); - if (f == NULL) { - udev_dbg(udev_device->udev, "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; while (fgets(line, sizeof(line), f)) { @@ -575,7 +575,7 @@ int udev_device_read_db(struct udev_device *udev_device, const char *dbfile) } fclose(f); - udev_dbg(udev_device->udev, "device %p filled with db file data\n", udev_device); + log_debug("device %p filled with db file data", udev_device); return 0; } @@ -640,14 +640,17 @@ void udev_device_set_info_loaded(struct udev_device *device) struct udev_device *udev_device_new(struct udev *udev) { struct udev_device *udev_device; - struct udev_list_entry *list_entry; - if (udev == NULL) + if (udev == NULL) { + errno = EINVAL; return NULL; + } - udev_device = calloc(1, sizeof(struct udev_device)); - if (udev_device == NULL) + udev_device = new0(struct udev_device, 1); + if (udev_device == NULL) { + errno = ENOMEM; return NULL; + } udev_device->refcount = 1; udev_device->udev = udev; udev_list_init(udev, &udev_device->devlinks_list, true); @@ -656,11 +659,7 @@ struct udev_device *udev_device_new(struct udev *udev) udev_list_init(udev, &udev_device->sysattr_list, false); udev_list_init(udev, &udev_device->tags_list, true); udev_device->watch_handle = -1; - /* copy global properties */ - udev_list_entry_foreach(list_entry, udev_get_properties_list_entry(udev)) - udev_device_add_property(udev_device, - udev_list_entry_get_name(list_entry), - udev_list_entry_get_value(list_entry)); + return udev_device; } @@ -686,22 +685,30 @@ _public_ struct udev_device *udev_device_new_from_syspath(struct udev *udev, con struct stat statbuf; struct udev_device *udev_device; - if (udev == NULL) + if (udev == NULL) { + errno = EINVAL; return NULL; - if (syspath == NULL) + } + + if (syspath == NULL) { + errno = EINVAL; return NULL; + } /* path starts in sys */ if (!startswith(syspath, "/sys")) { - udev_dbg(udev, "not in sys :%s\n", syspath); + log_debug("not in sys :%s", syspath); + errno = EINVAL; return NULL; } /* path is not a root directory */ subdir = syspath + strlen("/sys"); pos = strrchr(subdir, '/'); - if (pos == NULL || pos[1] == '\0' || pos < &subdir[2]) + if (pos == NULL || pos[1] == '\0' || pos < &subdir[2]) { + errno = EINVAL; return NULL; + } /* resolve possible symlink to real path */ strscpy(path, sizeof(path), syspath); @@ -716,8 +723,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); @@ -725,7 +737,7 @@ _public_ struct udev_device *udev_device_new_from_syspath(struct udev *udev, con return NULL; udev_device_set_syspath(udev_device, path); - udev_dbg(udev, "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; } @@ -755,8 +767,10 @@ _public_ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type_str = "block"; else if (type == 'c') type_str = "char"; - else + else { + errno = EINVAL; return NULL; + } /* use /sys/dev/{block,char}/: link */ snprintf(path, sizeof(path), "/sys/dev/%s/%u:%u", @@ -802,13 +816,15 @@ _public_ struct udev_device *udev_device_new_from_device_id(struct udev *udev, c int ifindex; ifindex = strtoul(&id[1], NULL, 10); - if (ifindex <= 0) + if (ifindex <= 0) { + errno = EINVAL; return NULL; + } sk = socket(PF_INET, SOCK_DGRAM, 0); if (sk < 0) return NULL; - memset(&ifr, 0x00, sizeof(struct ifreq)); + memzero(&ifr, sizeof(struct ifreq)); ifr.ifr_ifindex = ifindex; if (ioctl(sk, SIOCGIFNAME, &ifr) != 0) { close(sk); @@ -821,18 +837,24 @@ _public_ struct udev_device *udev_device_new_from_device_id(struct udev *udev, c return NULL; if (udev_device_get_ifindex(dev) == ifindex) return dev; + + /* this is racy, so we may end up with the wrong device */ udev_device_unref(dev); + errno = ENODEV; return NULL; } case '+': strscpy(subsys, sizeof(subsys), &id[1]); sysname = strchr(subsys, ':'); - if (sysname == NULL) + if (sysname == NULL) { + errno = EINVAL; return NULL; + } sysname[0] = '\0'; sysname = &sysname[1]; return udev_device_new_from_subsystem_sysname(udev, subsys, sysname); default: + errno = EINVAL; return NULL; } } @@ -896,7 +918,9 @@ _public_ struct udev_device *udev_device_new_from_subsystem_sysname(struct udev strscpyl(path, sizeof(path), "/sys/bus/", subsys, "/drivers/", driver, NULL); if (stat(path, &statbuf) == 0) goto found; - } + } else + errno = EINVAL; + goto out; } @@ -945,7 +969,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) { - udev_dbg(udev, "missing values, invalid device\n"); + log_debug("missing values, invalid device"); udev_device_unref(udev_device); udev_device = NULL; } @@ -972,6 +996,8 @@ static struct udev_device *device_new_from_parent(struct udev_device *udev_devic if (udev_device_parent != NULL) return udev_device_parent; } + + errno = ENOENT; return NULL; } @@ -982,9 +1008,8 @@ static struct udev_device *device_new_from_parent(struct udev_device *udev_devic * Find the next parent device, and fill in information from the sys * device and the udev database entry. * - * The returned the device is not referenced. It is attached to the - * child device, and will be cleaned up when the child device - * is cleaned up. + * Returned device is not referenced. It is attached to the child + * device, and will be cleaned up when the child device is cleaned up. * * It is not necessarily just the upper level directory, empty or not * recognized sys directories are ignored. @@ -996,8 +1021,10 @@ static struct udev_device *device_new_from_parent(struct udev_device *udev_devic **/ _public_ struct udev_device *udev_device_get_parent(struct udev_device *udev_device) { - if (udev_device == NULL) + if (udev_device == NULL) { + errno = EINVAL; return NULL; + } if (!udev_device->parent_set) { udev_device->parent_set = true; udev_device->parent_device = device_new_from_parent(udev_device); @@ -1018,9 +1045,8 @@ _public_ struct udev_device *udev_device_get_parent(struct udev_device *udev_dev * If devtype is #NULL, only subsystem is checked, and any devtype will * match. * - * The returned the device is not referenced. It is attached to the - * child device, and will be cleaned up when the child device - * is cleaned up. + * Returned device is not referenced. It is attached to the child + * device, and will be cleaned up when the child device is cleaned up. * * It can be called as many times as needed, without caring about * references. @@ -1031,8 +1057,10 @@ _public_ struct udev_device *udev_device_get_parent_with_subsystem_devtype(struc { struct udev_device *parent; - if (subsystem == NULL) + if (subsystem == NULL) { + errno = EINVAL; return NULL; + } parent = udev_device_get_parent(udev_device); while (parent != NULL) { @@ -1049,6 +1077,10 @@ _public_ struct udev_device *udev_device_get_parent_with_subsystem_devtype(struc } parent = udev_device_get_parent(parent); } + + if (!parent) + errno = ENOENT; + return parent; } @@ -1090,7 +1122,7 @@ _public_ struct udev_device *udev_device_ref(struct udev_device *udev_device) * Drop a reference of a udev device. If the refcount reaches zero, * the resources of the device will be released. * - * Returns: the passed udev device if it has still an active reference, or #NULL otherwise. + * Returns: #NULL **/ _public_ struct udev_device *udev_device_unref(struct udev_device *udev_device) { @@ -1098,7 +1130,7 @@ _public_ struct udev_device *udev_device_unref(struct udev_device *udev_device) return NULL; udev_device->refcount--; if (udev_device->refcount > 0) - return udev_device; + return NULL; if (udev_device->parent_device != NULL) udev_device_unref(udev_device->parent_device); free(udev_device->syspath); @@ -1341,7 +1373,7 @@ void udev_device_set_usec_initialized(struct udev_device *udev_device, usec_t us char num[32]; udev_device->usec_initialized = usec_initialized; - snprintf(num, sizeof(num), "%llu", (unsigned long long)usec_initialized); + snprintf(num, sizeof(num), USEC_FMT, usec_initialized); udev_device_add_property(udev_device, "USEC_INITIALIZED", num); } @@ -1698,9 +1730,14 @@ void udev_device_set_is_initialized(struct udev_device *udev_device) udev_device->is_initialized = true; } +static bool is_valid_tag(const char *tag) +{ + return !strchr(tag, ':') && !strchr(tag, ' '); +} + int udev_device_add_tag(struct udev_device *udev_device, const char *tag) { - if (strchr(tag, ':') != NULL || strchr(tag, ' ') != NULL) + if (!is_valid_tag(tag)) return -EINVAL; udev_device->tags_uptodate = false; if (udev_list_entry_add(&udev_device->tags_list, tag, NULL) != NULL) @@ -1708,6 +1745,20 @@ int udev_device_add_tag(struct udev_device *udev_device, const char *tag) return -ENOMEM; } +void udev_device_remove_tag(struct udev_device *udev_device, const char *tag) +{ + struct udev_list_entry *e; + + if (!is_valid_tag(tag)) + return; + e = udev_list_get_entry(&udev_device->tags_list); + e = udev_list_entry_get_by_name(e, tag); + if (e) { + udev_device->tags_uptodate = false; + udev_list_entry_delete(e); + } +} + void udev_device_cleanup_tags_list(struct udev_device *udev_device) { udev_device->tags_uptodate = false;