diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c index 018a52ada8..5ae33e101a 100644 --- a/src/udev/udevadm-info.c +++ b/src/udev/udevadm-info.c @@ -47,6 +47,8 @@ static const char *arg_export_prefix = NULL; static usec_t arg_wait_for_initialization_timeout = 0; static bool skip_attribute(const char *name) { + assert(name); + /* Those are either displayed separately or should not be shown at all. */ return STR_IN_SET(name, "uevent", @@ -66,6 +68,9 @@ typedef struct SysAttr { STATIC_DESTRUCTOR_REGISTER(arg_properties, strv_freep); static int sysattr_compare(const SysAttr *a, const SysAttr *b) { + assert(a); + assert(b); + return strcmp(a->name, b->name); } @@ -75,6 +80,8 @@ static int print_all_attributes(sd_device *device, bool is_parent) { size_t n_items = 0; int r; + assert(device); + value = NULL; (void) sd_device_get_devpath(device, &value); printf(" looking at %sdevice '%s':\n", is_parent ? "parent " : "", strempty(value)); @@ -139,6 +146,8 @@ static int print_device_chain(sd_device *device) { sd_device *child, *parent; int r; + assert(device); + printf("\n" "Udevadm info starts with the device specified by the devpath and then\n" "walks up the chain of parent devices. It prints for every device\n" @@ -164,6 +173,8 @@ static int print_record(sd_device *device) { const char *str, *val; int i; + assert(device); + (void) sd_device_get_devpath(device, &str); printf("P: %s\n", str); @@ -190,6 +201,8 @@ static int print_record(sd_device *device) { static int stat_device(const char *name, bool export, const char *prefix) { struct stat statbuf; + assert(name); + if (stat(name, &statbuf) != 0) return -errno; @@ -229,11 +242,11 @@ static int export_devices(void) { } static void cleanup_dir(DIR *dir, mode_t mask, int depth) { + assert(dir); + if (depth <= 0) return; - assert(dir); - FOREACH_DIRENT_ALL(dent, dir, break) { struct stat stats; @@ -261,38 +274,27 @@ static void cleanup_dir(DIR *dir, mode_t mask, int depth) { * entries for devices in /run/udev/data (such as "b8:16"), and removes * all files except those that haven't been deleted in /run/udev/data * (i.e. they were skipped during db cleanup because of the db_persist flag). - * Returns true if the directory is empty after cleanup. */ -static bool cleanup_dir_after_db_cleanup(DIR *dir, DIR *datadir) { - unsigned int kept = 0; - - assert(dir && datadir); +static void cleanup_dir_after_db_cleanup(DIR *dir, DIR *datadir) { + assert(dir); + assert(datadir); FOREACH_DIRENT_ALL(dent, dir, break) { - struct stat data_stats, link_stats; - if (dot_or_dot_dot(dent->d_name)) continue; - if (fstatat(dirfd(dir), dent->d_name, &link_stats, AT_SYMLINK_NOFOLLOW) < 0) { - if (errno != ENOENT) - kept++; + + if (faccessat(dirfd(datadir), dent->d_name, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) + /* The corresponding udev database file still exists. + * Assuming the parsistent flag is set for the database. */ continue; - } - if (fstatat(dirfd(datadir), dent->d_name, &data_stats, 0) < 0) - (void) unlinkat(dirfd(dir), dent->d_name, - S_ISDIR(link_stats.st_mode) ? AT_REMOVEDIR : 0); - else - /* The entry still exists under /run/udev/data */ - kept++; + (void) unlinkat(dirfd(dir), dent->d_name, 0); } - - return kept == 0; } static void cleanup_dirs_after_db_cleanup(DIR *dir, DIR *datadir) { - - assert(dir && datadir); + assert(dir); + assert(datadir); FOREACH_DIRENT_ALL(dent, dir, break) { struct stat stats; @@ -305,15 +307,17 @@ static void cleanup_dirs_after_db_cleanup(DIR *dir, DIR *datadir) { _cleanup_closedir_ DIR *dir2 = NULL; dir2 = fdopendir(openat(dirfd(dir), dent->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC)); - if (dir2 && cleanup_dir_after_db_cleanup(dir2, datadir)) - (void) unlinkat(dirfd(dir), dent->d_name, AT_REMOVEDIR); + if (dir2) + cleanup_dir_after_db_cleanup(dir2, datadir); + + (void) unlinkat(dirfd(dir), dent->d_name, AT_REMOVEDIR); } else (void) unlinkat(dirfd(dir), dent->d_name, 0); } } static void cleanup_db(void) { - _cleanup_closedir_ DIR *dir1 = NULL, *dir2 = NULL, *dir3 = NULL, *dir4 = NULL, *dir5 = NULL; + _cleanup_closedir_ DIR *dir1 = NULL, *dir2 = NULL, *dir3 = NULL, *dir4 = NULL; dir1 = opendir("/run/udev/data"); if (dir1) @@ -331,9 +335,8 @@ static void cleanup_db(void) { if (dir4) cleanup_dir(dir4, 0, 2); - dir5 = opendir("/run/udev/watch"); - if (dir5) - cleanup_dir_after_db_cleanup(dir5, dir1); + /* Do not remove /run/udev/watch. It will be handled by udevd well on restart. + * And should not be removed by external program when udevd is running. */ } static int query_device(QueryType query, sd_device* device) { @@ -399,10 +402,10 @@ static int query_device(QueryType query, sd_device* device) { case QUERY_ALL: return print_record(device); - } - assert_not_reached(); - return 0; + default: + assert_not_reached(); + } } static int help(void) {