]>
git.saurik.com Git - apple/file_cmds.git/blob - chown/chown.c
   2  * Copyright (c) 1988, 1993, 1994 
   3  *      The Regents of the University of California.  All rights reserved. 
   5  * Redistribution and use in source and binary forms, with or without 
   6  * modification, are permitted provided that the following conditions 
   8  * 1. Redistributions of source code must retain the above copyright 
   9  *    notice, this list of conditions and the following disclaimer. 
  10  * 2. Redistributions in binary form must reproduce the above copyright 
  11  *    notice, this list of conditions and the following disclaimer in the 
  12  *    documentation and/or other materials provided with the distribution. 
  13  * 3. All advertising materials mentioning features or use of this software 
  14  *    must display the following acknowledgement: 
  15  *      This product includes software developed by the University of 
  16  *      California, Berkeley and its contributors. 
  17  * 4. Neither the name of the University nor the names of its contributors 
  18  *    may be used to endorse or promote products derived from this software 
  19  *    without specific prior written permission. 
  21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 
  22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 
  25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
  26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
  27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
  30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
  34 #include <sys/cdefs.h> 
  36 __used 
static const char copyright
[] = 
  37 "@(#) Copyright (c) 1988, 1993, 1994\n\ 
  38         The Regents of the University of California.  All rights reserved.\n"; 
  43 static char sccsid
[] = "@(#)chown.c     8.8 (Berkeley) 4/4/94"; 
  47 #include <sys/cdefs.h> 
  48 __RCSID("$FreeBSD: src/usr.sbin/chown/chown.c,v 1.24 2002/07/17 16:22:24 dwmalone Exp $"); 
  50 #include <sys/param.h> 
  65 #include <get_compat.h> 
  67 #define COMPAT_MODE(a,b) (1) 
  68 #endif /* __APPLE__ */ 
  70 void    a_gid(const char *); 
  71 void    a_uid(const char *); 
  72 void    chownerr(const char *); 
  73 static uid_t    
id(const char *, const char *); 
  85 main(int argc
, char **argv
) 
  89         int Hflag
, Lflag
, Pflag
, Rflag
, fflag
, hflag
, vflag
; 
  90         int ch
, fts_options
, rval
; 
  92         int unix2003_compat 
= 0; 
  93         int symlink_found 
= 0; 
  97         cp 
= strrchr(argv
[0], '/'); 
  98         cp 
= (cp 
!= NULL
) ? cp 
+ 1 : argv
[0]; 
  99         ischown 
= (strcmp(cp
, "chown") == 0); 
 101         Hflag 
= Lflag 
= Pflag 
= Rflag 
= fflag 
= hflag 
= vflag 
= 0; 
 103         while ((ch 
= getopt(argc
, argv
, "HLPRfhnv")) != -1) 
 105         while ((ch 
= getopt(argc
, argv
, "HLPRfhv")) != -1) 
 146         if (!Rflag 
&& (Hflag 
|| Lflag 
|| Pflag
)) 
 147                 warnx("options -H, -L, -P only useful with -R"); 
 150                 fts_options 
= FTS_PHYSICAL
; 
 151                 if (hflag 
&& (Hflag 
|| Lflag
)) 
 152                         errx(1, "the -R%c and -h options may not be " 
 153                             "specified together", Hflag 
? 'H' : 'L'); 
 155                         fts_options 
|= FTS_COMFOLLOW
; 
 157                         fts_options 
&= ~FTS_PHYSICAL
; 
 158                         fts_options 
|= FTS_LOGICAL
; 
 161                 fts_options 
= hflag 
? FTS_PHYSICAL 
: FTS_LOGICAL
; 
 166                 unix2003_compat 
= COMPAT_MODE("bin/chown", "Unix2003"); 
 167                 if ((cp 
= strchr(*argv
, ':')) != NULL
) { 
 172                 else if ((cp 
= strchr(*argv
, '.')) != NULL
) { 
 173                         warnx("separation of user and group with a period is deprecated"); 
 180                 unix2003_compat 
= COMPAT_MODE("bin/chgrp", "Unix2003"); 
 184         if ((ftsp 
= fts_open(++argv
, fts_options
, 0)) == NULL
) 
 187         for (rval 
= 0; (p 
= fts_read(ftsp
)) != NULL
;) { 
 189                 switch (p
->fts_info
) { 
 190                 case FTS_D
:                     /* Change it at FTS_DP. */ 
 192                                 fts_set(ftsp
, p
, FTS_SKIP
); 
 194                 case FTS_DNR
:                   /* Warn, chown. */ 
 195                         warnx("%s: %s", p
->fts_path
, strerror(p
->fts_errno
)); 
 198                 case FTS_ERR
:                   /* Warn, continue. */ 
 200                         warnx("%s: %s", p
->fts_path
, strerror(p
->fts_errno
)); 
 206                          * The only symlinks that end up here are ones that 
 207                          * don't point to anything and ones that we found 
 208                          * doing a physical walk. 
 214                                 if (unix2003_compat
) { 
 215                                         if (Hflag 
|| Lflag
) {       /* -H or -L was specified */ 
 217                                                         warnx("%s: %s", p
->fts_name
, strerror(p
->fts_errno
)); 
 222                                         break; /* Otherwise symlinks keep going */ 
 229                 if (unix2003_compat
) { 
 230                         /* Can only avoid updating times if both uid and gid are -1 */ 
 231                         if ((uid 
== (uid_t
)-1) && (gid 
== (gid_t
)-1)) 
 234                         if ((uid 
== (uid_t
)-1 || uid 
== p
->fts_statp
->st_uid
) && 
 235                             (gid 
== (gid_t
)-1 || gid 
== p
->fts_statp
->st_gid
)) 
 238                 if (((hflag 
|| symlink_found
) ? lchown 
: chown
)(p
->fts_accpath
, uid
, gid
) == -1) { 
 240                                 chownerr(p
->fts_path
); 
 245                                 printf("%s\n", p
->fts_path
); 
 258         if (*s 
== '\0')                 /* Argument was "uid[:.]". */ 
 262         gid 
= (!isnumeric 
&& ((gr 
= getgrnam(s
)) != NULL
)) ? gr
->gr_gid 
: id(s
, "group"); 
 264         gid 
= ((gr 
= getgrnam(s
)) != NULL
) ? gr
->gr_gid 
: id(s
, "group"); 
 273         if (*s 
== '\0')                 /* Argument was "[:.]gid". */ 
 276         uid 
= (!isnumeric 
&& ((pw 
= getpwnam(s
)) != NULL
)) ? pw
->pw_uid 
: id(s
, "user"); 
 278         uid 
= ((pw 
= getpwnam(s
)) != NULL
) ? pw
->pw_uid 
: id(s
, "user"); 
 283 id(const char *name
, const char *type
) 
 289         val 
= strtoul(name
, &ep
, 10); 
 290         if (errno 
|| *ep 
!= '\0' || val 
> UID_MAX
) 
 291                 errx(1, "%s: illegal %s name", name
, type
); 
 296 chownerr(const char *file
) 
 298         static uid_t euid 
= -1; 
 299         static int ngroups 
= -1; 
 300         gid_t groups
[NGROUPS_MAX
]; 
 302         /* Check for chown without being root. */ 
 303         if (errno 
!= EPERM 
|| (uid 
!= (uid_t
)-1 && 
 304             euid 
== (uid_t
)-1 && (euid 
= geteuid()) != 0)) { 
 309         /* Check group membership; kernel just returns EPERM. */ 
 310         if (gid 
!= (gid_t
)-1 && ngroups 
== -1 && 
 311             euid 
== (uid_t
)-1 && (euid 
= geteuid()) != 0) { 
 312                 ngroups 
= getgroups(NGROUPS_MAX
, groups
); 
 313                 while (--ngroups 
>= 0 && gid 
!= groups
[ngroups
]); 
 315                         warnx("you are not a member of group %s", gname
); 
 327                 (void)fprintf(stderr
, "%s\n%s\n", 
 329                     "usage: chown [-fhnv] [-R [-H | -L | -P]] owner[:group]" 
 331                     "       chown [-fhnv] [-R [-H | -L | -P]] :group file ..."); 
 333                     "usage: chown [-fhv] [-R [-H | -L | -P]] owner[:group]" 
 335                     "       chown [-fhv] [-R [-H | -L | -P]] :group file ..."); 
 338                 (void)fprintf(stderr
, "%s\n", 
 340                     "usage: chgrp [-fhnv] [-R [-H | -L | -P]] group file ..."); 
 342                     "usage: chgrp [-fhv] [-R [-H | -L | -P]] group file ...");