Author: bapt
Date: Sun Jul 12 21:43:57 2015
New Revision: 285433
URL: https://svnweb.freebsd.org/changeset/base/285433

Log:
  pw -R <rootdir> userdel can now cleanup installation
  
  Rewrite rm_r to use *at function, allowing to remove home directories along 
with
  users. only crontabs and at(1) installation are not removed
  
  Relnotes:     yes

Modified:
  head/usr.sbin/pw/pw_user.c
  head/usr.sbin/pw/pwupd.h
  head/usr.sbin/pw/rm_r.c
  head/usr.sbin/pw/tests/pw_userdel.sh

Modified: head/usr.sbin/pw/pw_user.c
==============================================================================
--- head/usr.sbin/pw/pw_user.c  Sun Jul 12 21:43:31 2015        (r285432)
+++ head/usr.sbin/pw/pw_user.c  Sun Jul 12 21:43:57 2015        (r285433)
@@ -746,12 +746,12 @@ pw_user(int mode, char *name, long id, s
         */
        if (mode == M_ADD) {
                if (PWALTDIR() != PWF_ALT) {
-                       arg = getarg(args, 'R');
-                       snprintf(path, sizeof(path), "%s%s/%s",
-                           arg ? arg->val : "", _PATH_MAILDIR, pwd->pw_name);
-                       close(open(path, O_RDWR | O_CREAT, 0600));      /* 
Preserve contents &
-                                                                        * 
mtime */
-                       chown(path, pwd->pw_uid, pwd->pw_gid);
+                       snprintf(path, sizeof(path), "%s/%s", _PATH_MAILDIR,
+                           pwd->pw_name);
+                       close(openat(conf.rootfd, path +1, O_RDWR | O_CREAT,
+                           0600));     /* Preserve contents & mtime */
+                       fchownat(conf.rootfd, path + 1, pwd->pw_uid,
+                           pwd->pw_gid, AT_SYMLINK_NOFOLLOW);
                }
        }
 
@@ -1087,16 +1087,13 @@ pw_userdel(char *name, long id)
        if (strcmp(pwd->pw_name, "root") == 0)
                errx(EX_DATAERR, "cannot remove user 'root'");
 
-       if (!PWALTDIR()) {
-               /*
-                * Remove opie record from /etc/opiekeys
-               */
+               /* Remove opie record from /etc/opiekeys */
 
+       if (PWALTDIR() != PWF_ALT)
                rmopie(pwd->pw_name);
 
-               /*
-                * Remove crontabs
-                */
+       if (!PWALTDIR()) {
+               /* Remove crontabs */
                snprintf(file, sizeof(file), "/var/cron/tabs/%s", pwd->pw_name);
                if (access(file, F_OK) == 0) {
                        snprintf(file, sizeof(file), "crontab -u %s -r", 
pwd->pw_name);
@@ -1158,28 +1155,23 @@ pw_userdel(char *name, long id)
        pw_log(conf.userconf, M_DELETE, W_USER, "%s(%u) account removed", name,
            uid);
 
-       if (!PWALTDIR()) {
-               /*
-                * Remove mail file
-                */
-               remove(file);
-
-               /*
-                * Remove at jobs
-                */
-               if (getpwuid(uid) == NULL)
-                       rmat(uid);
-
-               /*
-                * Remove home directory and contents
-                */
-               if (conf.deletehome && *home == '/' && getpwuid(uid) == NULL &&
-                   stat(home, &st) != -1) {
-                       rm_r(home, uid);
-                       pw_log(conf.userconf, M_DELETE, W_USER, "%s(%u) home 
'%s' %sremoved",
-                              name, uid, home,
-                              stat(home, &st) == -1 ? "" : "not completely ");
-               }
+       /* Remove mail file */
+       if (PWALTDIR() != PWF_ALT)
+               unlinkat(conf.rootfd, file + 1, 0);
+
+               /* Remove at jobs */
+       if (!PWALTDIR() && getpwuid(uid) == NULL)
+               rmat(uid);
+
+       /* Remove home directory and contents */
+       if (PWALTDIR() != PWF_ALT && conf.deletehome && *home == '/' &&
+           getpwuid(uid) == NULL &&
+           fstatat(conf.rootfd, home + 1, &st, 0) != -1) {
+               rm_r(conf.rootfd, home, uid);
+               pw_log(conf.userconf, M_DELETE, W_USER, "%s(%u) home '%s' %s"
+                   "removed", name, uid, home,
+                    fstatat(conf.rootfd, home + 1, &st, 0) == -1 ? "" : "not "
+                    "completely ");
        }
 
        return (EXIT_SUCCESS);
@@ -1353,27 +1345,29 @@ rmat(uid_t uid)
 static void
 rmopie(char const * name)
 {
-       static const char etcopie[] = "/etc/opiekeys";
-       FILE   *fp = fopen(etcopie, "r+");
-
-       if (fp != NULL) {
-               char    tmp[1024];
-               off_t   atofs = 0;
-               int     length = strlen(name);
-
-               while (fgets(tmp, sizeof tmp, fp) != NULL) {
-                       if (strncmp(name, tmp, length) == 0 && tmp[length]==' 
') {
-                               if (fseek(fp, atofs, SEEK_SET) == 0) {
-                                       fwrite("#", 1, 1, fp);  /* Comment 
username out */
-                               }
-                               break;
-                       }
-                       atofs = ftell(fp);
+       char tmp[1014];
+       FILE *fp;
+       int fd;
+       size_t len;
+       off_t   atofs = 0;
+       
+       if ((fd = openat(conf.rootfd, "etc/opiekeys", O_RDWR)) == -1)
+               return;
+
+       fp = fdopen(fd, "r+");
+       len = strlen(name);
+
+       while (fgets(tmp, sizeof(tmp), fp) != NULL) {
+               if (strncmp(name, tmp, len) == 0 && tmp[len]==' ') {
+                       /* Comment username out */
+                       if (fseek(fp, atofs, SEEK_SET) == 0)
+                               fwrite("#", 1, 1, fp);
+                       break;
                }
-               /*
-                * If we got an error of any sort, don't update!
-                */
-               fclose(fp);
+               atofs = ftell(fp);
        }
+       /*
+        * If we got an error of any sort, don't update!
+        */
+       fclose(fp);
 }
-

Modified: head/usr.sbin/pw/pwupd.h
==============================================================================
--- head/usr.sbin/pw/pwupd.h    Sun Jul 12 21:43:31 2015        (r285432)
+++ head/usr.sbin/pw/pwupd.h    Sun Jul 12 21:43:57 2015        (r285433)
@@ -159,7 +159,7 @@ void           vendgrent(void);
 
 void copymkdir(int rootfd, char const * dir, int skelfd, mode_t mode, uid_t 
uid,
     gid_t gid, int flags);
-void rm_r(char const * dir, uid_t uid);
+void rm_r(int rootfd, char const * dir, uid_t uid);
 __END_DECLS
 
 #endif                         /* !_PWUPD_H */

Modified: head/usr.sbin/pw/rm_r.c
==============================================================================
--- head/usr.sbin/pw/rm_r.c     Sun Jul 12 21:43:31 2015        (r285432)
+++ head/usr.sbin/pw/rm_r.c     Sun Jul 12 21:43:57 2015        (r285433)
@@ -37,39 +37,37 @@ static const char rcsid[] =
 #include <sys/param.h>
 #include <unistd.h>
 #include <dirent.h>
+#include <fcntl.h>
 
 #include "pwupd.h"
 
 void
-rm_r(char const * dir, uid_t uid)
+rm_r(int rootfd, const char *path, uid_t uid)
 {
-       DIR            *d = opendir(dir);
+       int dirfd;
+       DIR *d;
+       struct dirent  *e;
+       struct stat     st;
 
-       if (d != NULL) {
-               struct dirent  *e;
-               struct stat     st;
-               char            file[MAXPATHLEN];
-
-               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);
-               }
+       if (*path == '/')
+               path++;
+
+       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);
        }
+       closedir(d);
+       if (fstatat(rootfd, path, &st, AT_SYMLINK_NOFOLLOW) != 0)
+               return;
+       unlinkat(rootfd, path, S_ISDIR(st.st_mode) ? AT_REMOVEDIR : 0);
 }

Modified: head/usr.sbin/pw/tests/pw_userdel.sh
==============================================================================
--- head/usr.sbin/pw/tests/pw_userdel.sh        Sun Jul 12 21:43:31 2015        
(r285432)
+++ head/usr.sbin/pw/tests/pw_userdel.sh        Sun Jul 12 21:43:57 2015        
(r285433)
@@ -31,7 +31,27 @@ user_do_not_try_to_delete_root_if_user_u
                ${PW} userdel -u plop
 }
 
+atf_test_case delete_files
+delete_files_body() {
+       populate_root_etc_skel
+
+       mkdir -p ${HOME}/skel
+       touch ${HOME}/skel/a
+       mkdir -p ${HOME}/home
+       mkdir -p ${HOME}/var/mail
+       echo "foo wedontcare" > ${HOME}/etc/opiekeys
+       atf_check -s exit:0 ${RPW} useradd foo -k skel -m
+       test -d ${HOME}/home || atf_fail "Fail to create home directory"
+       test -f ${HOME}/var/mail/foo || atf_fail "Mail file not created"
+       atf_check -s exit:0 ${RPW} userdel foo -r
+       atf_check -s exit:0 -o inline:"#oo wedontcare\n" cat 
${HOME}/etc/opiekeys
+       if test -f ${HOME}/var/mail/foo; then
+               atf_fail "Mail file not removed"
+       fi
+}
+
 atf_init_test_cases() {
        atf_add_test_case rmuser_seperate_group
        atf_add_test_case user_do_not_try_to_delete_root_if_user_unknown
+       atf_add_test_case delete_files
 }
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to