diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2020-07-06 07:47:51 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-06 07:47:51 +0200 |
commit | c5fbdebec641c61efca769a0a9168f8fb06f7436 (patch) | |
tree | 91e29cd649cc42583cca6e6c8a6eef79d2764b85 /src/libsystemd | |
parent | catalog: update Polish translation (diff) | |
parent | sd-device: be more defensive in FOREACH_DEVICE_SYSATTR (diff) | |
download | systemd-c5fbdebec641c61efca769a0a9168f8fb06f7436.tar.xz systemd-c5fbdebec641c61efca769a0a9168f8fb06f7436.zip |
Merge pull request #16287 from yuwata/udevadm-info-attribute-walk
udevadm: make --attribute-walk show subdir attributes
Diffstat (limited to 'src/libsystemd')
-rw-r--r-- | src/libsystemd/sd-device/sd-device.c | 75 |
1 files changed, 62 insertions, 13 deletions
diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c index 24f34dc182..13596f2303 100644 --- a/src/libsystemd/sd-device/sd-device.c +++ b/src/libsystemd/sd-device/sd-device.c @@ -1564,34 +1564,68 @@ _public_ const char *sd_device_get_property_next(sd_device *device, const char * return key; } -static int device_sysattrs_read_all(sd_device *device) { +static int device_sysattrs_read_all_internal(sd_device *device, const char *subdir) { + _cleanup_free_ char *path_dir = NULL; _cleanup_closedir_ DIR *dir = NULL; - const char *syspath; struct dirent *dent; + const char *syspath; int r; - assert(device); - - if (device->sysattrs_read) - return 0; - r = sd_device_get_syspath(device, &syspath); if (r < 0) return r; - dir = opendir(syspath); + if (subdir) { + _cleanup_free_ char *p = NULL; + + p = path_join(syspath, subdir, "uevent"); + if (!p) + return -ENOMEM; + + if (access(p, F_OK) >= 0) + /* this is a child device, skipping */ + return 0; + if (errno != ENOENT) { + log_debug_errno(errno, "Failed to stat %s, ignoring subdir: %m", p); + return 0; + } + + path_dir = path_join(syspath, subdir); + if (!path_dir) + return -ENOMEM; + } + + dir = opendir(path_dir ?: syspath); if (!dir) return -errno; FOREACH_DIRENT_ALL(dent, dir, return -errno) { - _cleanup_free_ char *path = NULL; + _cleanup_free_ char *path = NULL, *p = NULL; struct stat statbuf; - /* only handle symlinks and regular files */ - if (!IN_SET(dent->d_type, DT_LNK, DT_REG)) + if (dot_or_dot_dot(dent->d_name)) + continue; + + /* only handle symlinks, regular files, and directories */ + if (!IN_SET(dent->d_type, DT_LNK, DT_REG, DT_DIR)) + continue; + + if (subdir) { + p = path_join(subdir, dent->d_name); + if (!p) + return -ENOMEM; + } + + if (dent->d_type == DT_DIR) { + /* read subdirectory */ + r = device_sysattrs_read_all_internal(device, p ?: dent->d_name); + if (r < 0) + return r; + continue; + } - path = path_join(syspath, dent->d_name); + path = path_join(syspath, p ?: dent->d_name); if (!path) return -ENOMEM; @@ -1601,11 +1635,26 @@ static int device_sysattrs_read_all(sd_device *device) { if (!(statbuf.st_mode & S_IRUSR)) continue; - r = set_put_strdup(&device->sysattrs, dent->d_name); + r = set_put_strdup(&device->sysattrs, p ?: dent->d_name); if (r < 0) return r; } + return 0; +} + +static int device_sysattrs_read_all(sd_device *device) { + int r; + + assert(device); + + if (device->sysattrs_read) + return 0; + + r = device_sysattrs_read_all_internal(device, NULL); + if (r < 0) + return r; + device->sysattrs_read = true; return 0; |