chiark / gitweb /
rules: fix typo
[elogind.git] / udev / udevadm-info.c
index 9357f672083e86a36fc22b160d487c3b72a9f706..f7e7e86b6a4a8f43cf9207b85f4176ab4874191c 100644 (file)
@@ -52,10 +52,10 @@ static bool skip_attribute(const char *name)
 
 static void print_all_attributes(struct udev_device *device, const char *key)
 {
+       struct udev *udev = udev_device_get_udev(device);
        struct udev_list_entry *sysattr;
 
        udev_list_entry_foreach(sysattr, udev_device_get_sysattr_list_entry(device)) {
-               struct udev *udev = udev_device_get_udev(device);
                const char *name;
                const char *value;
                size_t len;
@@ -69,6 +69,10 @@ static void print_all_attributes(struct udev_device *device, const char *key)
                        continue;
                dbg(udev, "attr '%s'='%s'\n", name, value);
 
+               /* skip any values that look like a path */
+               if (value[0] == '/')
+                       continue;
+
                /* skip nonprintable attributes */
                len = strlen(value);
                while (len > 0 && isprint(value[len-1]))
@@ -200,7 +204,82 @@ static int export_devices(struct udev *udev)
        return 0;
 }
 
-int udevadm_info(struct udev *udev, int argc, char *argv[])
+static void cleanup_dir(DIR *dir, mode_t mask, int depth)
+{
+       struct dirent *dent;
+
+       if (depth <= 0)
+               return;
+
+       for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
+               struct stat stats;
+
+               if (dent->d_name[0] == '.')
+                       continue;
+               if (fstatat(dirfd(dir), dent->d_name, &stats, AT_SYMLINK_NOFOLLOW) != 0)
+                       continue;
+               if ((stats.st_mode & mask) != 0)
+                       continue;
+               if (S_ISDIR(stats.st_mode)) {
+                       DIR *dir2;
+
+                       dir2 = fdopendir(openat(dirfd(dir), dent->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC));
+                       if (dir2 != NULL) {
+                               cleanup_dir(dir2, mask, depth-1);
+                               closedir(dir2);
+                       }
+                       unlinkat(dirfd(dir), dent->d_name, AT_REMOVEDIR);
+               } else {
+                       unlinkat(dirfd(dir), dent->d_name, 0);
+               }
+       }
+}
+
+static void cleanup_db(struct udev *udev)
+{
+       char filename[UTIL_PATH_SIZE];
+       DIR *dir;
+
+       util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/queue.bin", NULL);
+       unlink(filename);
+
+       util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/data", NULL);
+       dir = opendir(filename);
+       if (dir != NULL) {
+               cleanup_dir(dir, S_ISVTX, 1);
+               closedir(dir);
+       }
+
+       util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/links", NULL);
+       dir = opendir(filename);
+       if (dir != NULL) {
+               cleanup_dir(dir, 0, 2);
+               closedir(dir);
+       }
+
+       util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/tags", NULL);
+       dir = opendir(filename);
+       if (dir != NULL) {
+               cleanup_dir(dir, 0, 2);
+               closedir(dir);
+       }
+
+       util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/watch", NULL);
+       dir = opendir(filename);
+       if (dir != NULL) {
+               cleanup_dir(dir, 0, 1);
+               closedir(dir);
+       }
+
+       util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/firmware-missing", NULL);
+       dir = opendir(filename);
+       if (dir != NULL) {
+               cleanup_dir(dir, 0, 1);
+               closedir(dir);
+       }
+}
+
+static int uinfo(struct udev *udev, int argc, char *argv[])
 {
        struct udev_device *device = NULL;
        bool root = 0;
@@ -216,6 +295,7 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
                { "path", required_argument, NULL, 'p' },
                { "query", required_argument, NULL, 'q' },
                { "attribute-walk", no_argument, NULL, 'a' },
+               { "cleanup-db", no_argument, NULL, 'c' },
                { "export-db", no_argument, NULL, 'e' },
                { "root", no_argument, NULL, 'r' },
                { "run", no_argument, NULL, 'R' },
@@ -248,7 +328,7 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
                int option;
                struct stat statbuf;
 
-               option = getopt_long(argc, argv, "aed:n:p:q:rxP:RVh", options, NULL);
+               option = getopt_long(argc, argv, "aced:n:p:q:rxP:RVh", options, NULL);
                if (option == -1)
                        break;
 
@@ -345,6 +425,9 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
                case 'e':
                        export_devices(udev);
                        goto exit;
+               case 'c':
+                       cleanup_db(udev);
+                       goto exit;
                case 'x':
                        export = true;
                        break;
@@ -371,9 +454,11 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
                               "  --export                   export key/value pairs\n"
                               "  --export-prefix            export the key name with a prefix\n"
                               "  --export-db                export the content of the udev database\n"
+                              "  --cleanup-db               cleanup the udev database\n"
                               "  --help\n\n");
                        goto exit;
                default:
+                       rc = 1;
                        goto exit;
                }
        }
@@ -475,3 +560,9 @@ exit:
        udev_device_unref(device);
        return rc;
 }
+
+const struct udevadm_cmd udevadm_info = {
+       .name = "info",
+       .cmd = uinfo,
+       .help = "query sysfs or the udev database",
+};