bool FileSystem::rmtree(const Path& path) { Directory* test_dir = opendir(path); if (test_dir != NULL) { auto_Object<Directory> dir(test_dir); Directory::Entry* test_dentry = dir->read(); if (test_dentry != NULL) { auto_Object<Directory::Entry> dentry(*test_dentry); do { if (dentry->is_special()) { continue; } Path dentry_path(path / dentry->get_name()); if (dentry->ISDIR()) { if (rmtree(dentry_path)) { continue; } else { return false; } } else if (unlink(dentry_path)) { continue; } else { return false; } } while (dir->read(*dentry)); return rmdir(path); } } return false; }
/** * d_namespace_path - lookup a name associated with a given path * @path: path to lookup (NOT NULL) * @buf: buffer to store path to (NOT NULL) * @buflen: length of @buf * @name: Returns - pointer for start of path name with in @buf (NOT NULL) * @flags: flags controlling path lookup * * Handle path name lookup. * * Returns: %0 else error code if path lookup fails * When no error the path name is returned in @name which points to * to a position in @buf */ static int d_namespace_path(struct path *path, char *buf, int buflen, char **name, int flags) { char *res; int error = 0; int connected = 1; if (path->mnt->mnt_flags & MNT_INTERNAL) { /* it's not mounted anywhere */ res = dentry_path(path->dentry, buf, buflen); *name = res; if (IS_ERR(res)) { *name = buf; return PTR_ERR(res); } if (path->dentry->d_sb->s_magic == PROC_SUPER_MAGIC && strncmp(*name, "/sys/", 5) == 0) { /* TODO: convert over to using a per namespace * control instead of hard coded /proc */ return prepend(name, *name - buf, "/proc", 5); } return 0; } /* resolve paths relative to chroot?*/ if (flags & PATH_CHROOT_REL) { struct path root; get_fs_root(current->fs, &root); res = __d_path(path, &root, buf, buflen); path_put(&root); } else { res = d_absolute_path(path, buf, buflen); if (!our_mnt(path->mnt)) connected = 0; } /* handle error conditions - and still allow a partial path to * be returned. */ if (!res || IS_ERR(res)) { connected = 0; res = dentry_path_raw(path->dentry, buf, buflen); if (IS_ERR(res)) { error = PTR_ERR(res); *name = buf; goto out; }; } else if (!our_mnt(path->mnt)) connected = 0; *name = res; /* Handle two cases: * 1. A deleted dentry && profile is not allowing mediation of deleted * 2. On some filesystems, newly allocated dentries appear to the * security_path hooks as a deleted dentry except without an inode * allocated. */ if (d_unlinked(path->dentry) && path->dentry->d_inode && !(flags & PATH_MEDIATE_DELETED)) { error = -ENOENT; goto out; } /* If the path is not connected to the expected root, * check if it is a sysctl and handle specially else remove any * leading / that __d_path may have returned. * Unless * specifically directed to connect the path, * OR * if in a chroot and doing chroot relative paths and the path * resolves to the namespace root (would be connected outside * of chroot) and specifically directed to connect paths to * namespace root. */ if (!connected) { if (!(flags & PATH_CONNECT_PATH) && !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) && our_mnt(path->mnt))) { /* disconnected path, don't return pathname starting * with '/' */ error = -ESTALE; if (*res == '/') *name = res + 1; } } out: return error; }