+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);
+ }
+}
+