summaryrefslogtreecommitdiffstats
path: root/src/libsystemd
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2020-07-06 07:47:51 +0200
committerGitHub <noreply@github.com>2020-07-06 07:47:51 +0200
commitc5fbdebec641c61efca769a0a9168f8fb06f7436 (patch)
tree91e29cd649cc42583cca6e6c8a6eef79d2764b85 /src/libsystemd
parentcatalog: update Polish translation (diff)
parentsd-device: be more defensive in FOREACH_DEVICE_SYSATTR (diff)
downloadsystemd-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.c75
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;