change group character, dot, to colon (dot still permitted)
authorKeith Bostic <bostic@ucbvax.Berkeley.EDU>
Sat, 27 Oct 1990 06:52:07 +0000 (22:52 -0800)
committerKeith Bostic <bostic@ucbvax.Berkeley.EDU>
Sat, 27 Oct 1990 06:52:07 +0000 (22:52 -0800)
change the -f flag to ONLY mask errors in changing owner/group
new manual page, started from the POSIX.2 manual page
use FTS to walk the tree

SCCS-vsn: usr.sbin/chown/Makefile 5.4
SCCS-vsn: usr.sbin/chown/chown.8 6.4
SCCS-vsn: usr.sbin/chown/chown.c 5.16

usr/src/usr.sbin/chown/Makefile
usr/src/usr.sbin/chown/chown.8
usr/src/usr.sbin/chown/chown.c

index 9cec81e..fc2928a 100644 (file)
@@ -1,6 +1,7 @@
-#      @(#)Makefile    5.3 (Berkeley) %G%
+#      @(#)Makefile    5.4 (Berkeley) %G%
 
 PROG=  chown
 
 PROG=  chown
+CFLAGS+=-DSUPPORT_DOT
 MAN1=  chgrp.0
 MAN8=  chown.0
 LINKS= ${BINDIR}/chown /usr/bin/chgrp
 MAN1=  chgrp.0
 MAN8=  chown.0
 LINKS= ${BINDIR}/chown /usr/bin/chgrp
index 5ae1a53..f959974 100644 (file)
@@ -1,44 +1,66 @@
-.\" Copyright (c) 1980 Regents of the University of California.
-.\" All rights reserved.  The Berkeley software License Agreement
-.\" specifies the terms and conditions for redistribution.
+.\" Copyright (c) 1990 The Regents of the University of California.
+.\" All rights reserved.
 .\"
 .\"
-.\"    @(#)chown.8     6.3 (Berkeley) %G%
+.\" %sccs.include.redist.man%
+.\"
+.\"    @(#)chown.8     6.4 (Berkeley) %G%
 .\"
 .TH CHOWN 8 ""
 .UC 4
 .SH NAME
 .\"
 .TH CHOWN 8 ""
 .UC 4
 .SH NAME
-chown \- change owner
+chown \- change file owner and group
 .SH SYNOPSIS
 .SH SYNOPSIS
-.B chown
-[
-.B \-Rf
-]
-owner[.group] file ...
+.nf
+.ft B
+chown [-Rf] [owner][:group] file ...
 .SH DESCRIPTION
 .I Chown
 .SH DESCRIPTION
 .I Chown
-changes the owner of the
-.I files
-to
-.IR owner .
-The owner may be either a decimal UID or
-a login name found in the password file.
-An optional group may also be specified.
-The group may be either a decimal GID or
-a group name found in the group-ID file.
+sets the user ID and/or the group ID of the specified files.
+.PP
+The options are as follows:
+.TP
+-R
+Change the user ID and/or the group ID for the file hierarchies rooted
+in the files instead of just the files themselves.
+.TP
+-f
+Don't report any failure to change file owner or group, nor modify
+the exit status to reflect such failures.
+.PP
+The
+.I owner
+and
+.I group
+operands are both optional, but at least one must be specified; if
+the group operand is specified, it must be preceded by a colon (``:'')
+character.
 .PP
 .PP
-Only the super-user can change owner,
-in order to simplify accounting procedures.
-No errors, except for usage errors, are reported when the
-.B \-f
-(force) option is given.
+The
+.I owner
+should be either a numeric user ID or a user name.
+If a user name is also a numeric user ID, the operand is used as a
+user name.
+The
+.I group
+should be either a numeric group ID or a group name.
+If a group name is also a numeric group ID, the operand is used as a
+group name.
 .PP
 .PP
-When the
-.B \-R
-option is given, 
+Only the super-user may change the owner of a file in order to
+simplify accounting procedures and to prevent the circumvention
+of system security.
+.PP
+The owner and group of symbolic links are themselves changed instead
+of the file to which the link points.
+.PP
+The
+.I chown
+utility exits 0 on success, and >0 if an error occurs.
+.SH COMPATIBILITY
+Previous versions of the
 .I chown
 .I chown
-recursively descends its directory arguments
-setting the specified owner.
-When symbolic links are encountered, their ownership is changed,
-but they are not traversed.
+utility used the dot (``.'') character to distinguish the group name.
+This has been changed to be a colon (``:'') character so that user and
+group names may contain the dot character.
 .SH "SEE ALSO"
 .SH "SEE ALSO"
-chgrp(1), chown(2)
+chgrp(1), find(1), chown(2)
index 0d0c43f..e785ec9 100644 (file)
@@ -12,17 +12,19 @@ char copyright[] =
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)chown.c    5.15 (Berkeley) %G%";
+static char sccsid[] = "@(#)chown.c    5.16 (Berkeley) %G%";
 #endif /* not lint */
 
 #include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/errno.h>
 #include <dirent.h>
 #endif /* not lint */
 
 #include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/errno.h>
 #include <dirent.h>
+#include <fts.h>
 #include <pwd.h>
 #include <grp.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <pwd.h>
 #include <grp.h>
 #include <stdio.h>
 #include <ctype.h>
+#include <string.h>
 
 int ischown, uid, gid, fflag, rflag, retval;
 char *gname, *myname;
 
 int ischown, uid, gid, fflag, rflag, retval;
 char *gname, *myname;
@@ -31,11 +33,11 @@ main(argc, argv)
        int argc;
        char **argv;
 {
        int argc;
        char **argv;
 {
-       extern char *optarg;
        extern int optind;
        extern int optind;
+       register FTS *fts;
+       register FTSENT *p;
        register char *cp;
        int ch;
        register char *cp;
        int ch;
-       char curpath[MAXPATHLEN], *reset, *index(), *rindex();
 
        myname = (cp = rindex(*argv, '/')) ? cp + 1 : *argv;
        ischown = myname[2] == 'o';
 
        myname = (cp = rindex(*argv, '/')) ? cp + 1 : *argv;
        ischown = myname[2] == 'o';
@@ -43,10 +45,10 @@ main(argc, argv)
        while ((ch = getopt(argc, argv, "Rf")) != EOF)
                switch((char)ch) {
                case 'R':
        while ((ch = getopt(argc, argv, "Rf")) != EOF)
                switch((char)ch) {
                case 'R':
-                       rflag++;
+                       rflag = 1;
                        break;
                case 'f':
                        break;
                case 'f':
-                       fflag++;
+                       fflag = 1;
                        break;
                case '?':
                default:
                        break;
                case '?':
                default:
@@ -58,31 +60,44 @@ main(argc, argv)
        if (argc < 2)
                usage();
 
        if (argc < 2)
                usage();
 
+       uid = gid = -1;
        if (ischown) {
        if (ischown) {
+#ifdef SUPPORT_DOT
                if (cp = index(*argv, '.')) {
                        *cp++ = '\0';
                        setgid(cp);
                if (cp = index(*argv, '.')) {
                        *cp++ = '\0';
                        setgid(cp);
-               }
-               else
-                       gid = -1;
+               } else
+#endif
+               if (cp = index(*argv, ':')) {
+                       *cp++ = '\0';
+                       setgid(cp);
+               } 
                setuid(*argv);
        }
                setuid(*argv);
        }
-       else {
-               uid = -1;
+       else 
                setgid(*argv);
                setgid(*argv);
-       }
 
 
-       while (*++argv) {
-               if (reset = index(*argv, '/'))
-                       (void)getwd(curpath);
-               change(*argv);
-               if (reset && chdir(curpath)) {
-                       if (fflag)
-                               exit(0);
-                       err(curpath);
-                       exit(-1);
+       if (rflag) {
+               if (!(fts = ftsopen(++argv, FTS_NOSTAT|FTS_PHYSICAL, 0))) {
+                       (void)fprintf(stderr,
+                           "%s: %s.\n", myname, strerror(errno));
+                       exit(1);
                }
                }
+               while (p = ftsread(fts)) {
+                       if (p->fts_info == FTS_D)
+                               continue;
+                       if (p->fts_info == FTS_ERR) {
+                               error(p->fts_path);
+                               continue;
+                       }
+                       if (chown(p->fts_accpath, uid, gid) && !fflag)
+                               chownerr(p->fts_path);
+               }
+               exit(retval);
        }
        }
+       while (*++argv)
+               if (chown(*argv, uid, gid) && !fflag)
+                       chownerr(*argv);
        exit(retval);
 }
 
        exit(retval);
 }
 
@@ -100,11 +115,9 @@ setgid(s)
                gid = atoi(gname);
        else {
                if (!(gr = getgrnam(gname))) {
                gid = atoi(gname);
        else {
                if (!(gr = getgrnam(gname))) {
-                       if (fflag)
-                               exit(0);
                        (void)fprintf(stderr, "%s: unknown group id: %s\n",
                            myname, gname);
                        (void)fprintf(stderr, "%s: unknown group id: %s\n",
                            myname, gname);
-                       exit(-1);
+                       exit(1);
                }
                gid = gr->gr_gid;
        }
                }
                gid = gr->gr_gid;
        }
@@ -125,64 +138,25 @@ setuid(s)
                uid = atoi(beg);
        else {
                if (!(pwd = getpwnam(beg))) {
                uid = atoi(beg);
        else {
                if (!(pwd = getpwnam(beg))) {
-                       if (fflag)
-                               exit(0);
                        (void)fprintf(stderr,
                            "chown: unknown user id: %s\n", beg);
                        (void)fprintf(stderr,
                            "chown: unknown user id: %s\n", beg);
-                       exit(-1);
+                       exit(1);
                }
                uid = pwd->pw_uid;
        }
 }
 
                }
                uid = pwd->pw_uid;
        }
 }
 
-change(file)
-       char *file;
-{
-       register DIR *dirp;
-       register struct dirent *dp;
-       struct stat buf;
-
-       if (chown(file, uid, gid)) {
-               chownerr(file);
-               return;
-       }
-       if (!rflag)
-               return;
-       if (lstat(file, &buf)) {
-               err(file);
-               return;
-       }
-       if ((buf.st_mode & S_IFMT) == S_IFDIR) {
-               if (chdir(file) < 0 || !(dirp = opendir("."))) {
-                       err(file);
-                       return;
-               }
-               for (dp = readdir(dirp); dp; dp = readdir(dirp)) {
-                       if (dp->d_name[0] == '.' && (!dp->d_name[1] ||
-                           dp->d_name[1] == '.' && !dp->d_name[2]))
-                               continue;
-                       change(dp->d_name);
-               }
-               closedir(dirp);
-               if (chdir("..")) {
-                       err("..");
-                       exit(fflag ? 0 : -1);
-               }
-       }
-}
-
 chownerr(file)
        char *file;
 {
 chownerr(file)
        char *file;
 {
-       extern int errno;
        static int euid = -1, ngroups = -1;
 
        /* check for chown without being root */
        if (errno != EPERM || uid != -1 && euid == -1 && (euid = geteuid())) {
                if (fflag)
                        exit(0);
        static int euid = -1, ngroups = -1;
 
        /* check for chown without being root */
        if (errno != EPERM || uid != -1 && euid == -1 && (euid = geteuid())) {
                if (fflag)
                        exit(0);
-               err(file);
-               exit(-1);
+               error(file);
+               exit(1);
        }
        /* check group membership; kernel just returns EPERM */
        if (gid != -1 && ngroups == -1) {
        }
        /* check group membership; kernel just returns EPERM */
        if (gid != -1 && ngroups == -1) {
@@ -196,27 +170,23 @@ chownerr(file)
                        (void)fprintf(stderr,
                            "%s: you are not a member of group %s.\n",
                            myname, gname);
                        (void)fprintf(stderr,
                            "%s: you are not a member of group %s.\n",
                            myname, gname);
-                       exit(-1);
+                       exit(1);
                }
        }
                }
        }
-       err(file);
+       if (!fflag)
+               error(file);
 }
 
 }
 
-err(s)
-       char *s;
+error(name)
+       char *name;
 {
 {
-       extern int errno;
-       char *strerror();
-
-       if (fflag)
-               return;
-       (void)fprintf(stderr, "%s: %s: %s\n", myname, s, strerror(errno));
-       retval = -1;
+       (void)fprintf(stderr, "%s: %s: %s\n", myname, name, strerror(errno));
+       retval = 1;
 }
 
 usage()
 {
        (void)fprintf(stderr, "usage: %s [-Rf] %s file ...\n", myname,
 }
 
 usage()
 {
        (void)fprintf(stderr, "usage: %s [-Rf] %s file ...\n", myname,
-           ischown ? "owner[.group]" : "group");
-       exit(-1);
+           ischown ? "[owner][:group]" : "group");
+       exit(1);
 }
 }