mirror of
https://github.com/systemd/systemd.git
synced 2024-10-30 06:25:37 +03:00
Merge pull request #22205 from yuwata/udevadm-info-cleanups
udevadm: keep watch directory and several cleanups
This commit is contained in:
commit
57cbf080b3
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user