Deleted Added
full compact
29c29
< "$FreeBSD: head/usr.sbin/pw/rm_r.c 243897 2012-12-05 13:56:52Z eadler $";
---
> "$FreeBSD: head/usr.sbin/pw/rm_r.c 285433 2015-07-12 21:43:57Z bapt $";
39a40
> #include <fcntl.h>
44c45
< rm_r(char const * dir, uid_t uid)
---
> rm_r(int rootfd, const char *path, uid_t uid)
46c47,50
< DIR *d = opendir(dir);
---
> int dirfd;
> DIR *d;
> struct dirent *e;
> struct stat st;
48,51c52,53
< if (d != NULL) {
< struct dirent *e;
< struct stat st;
< char file[MAXPATHLEN];
---
> if (*path == '/')
> path++;
53,73c55,67
< while ((e = readdir(d)) != NULL) {
< if (strcmp(e->d_name, ".") != 0 && strcmp(e->d_name, "..") != 0) {
< snprintf(file, sizeof(file), "%s/%s", dir, e->d_name);
< if (lstat(file, &st) == 0) { /* Need symlinks, not
< * linked file */
< if (S_ISDIR(st.st_mode)) /* Directory - recurse */
< rm_r(file, uid);
< else {
< if (S_ISLNK(st.st_mode) || st.st_uid == uid)
< remove(file);
< }
< }
< }
< }
< closedir(d);
< if (lstat(dir, &st) == 0) {
< if (S_ISLNK(st.st_mode))
< remove(dir);
< else if (st.st_uid == uid)
< rmdir(dir);
< }
---
> dirfd = openat(rootfd, path, O_DIRECTORY);
>
> d = fdopendir(dirfd);
> while ((e = readdir(d)) != NULL) {
> if (strcmp(e->d_name, ".") == 0 || strcmp(e->d_name, "..") == 0)
> continue;
>
> if (fstatat(dirfd, e->d_name, &st, AT_SYMLINK_NOFOLLOW) != 0)
> continue;
> if (S_ISDIR(st.st_mode))
> rm_r(dirfd, e->d_name, uid);
> else if (S_ISLNK(st.st_mode) || st.st_uid == uid)
> unlinkat(dirfd, e->d_name, 0);
74a69,72
> closedir(d);
> if (fstatat(rootfd, path, &st, AT_SYMLINK_NOFOLLOW) != 0)
> return;
> unlinkat(rootfd, path, S_ISDIR(st.st_mode) ? AT_REMOVEDIR : 0);