X-Git-Url: https://git.saurik.com/apple/file_cmds.git/blobdiff_plain/6c780a1f93b6cb2162f563ddae2d48867866f44c..refs/heads/master:/chown/chown.c diff --git a/chown/chown.c b/chown/chown.c index 464bf23..708a6c5 100644 --- a/chown/chown.c +++ b/chown/chown.c @@ -31,8 +31,9 @@ * SUCH DAMAGE. */ +#include #ifndef lint -static const char copyright[] = +__used static const char copyright[] = "@(#) Copyright (c) 1988, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ @@ -58,16 +59,26 @@ __RCSID("$FreeBSD: src/usr.sbin/chown/chown.c,v 1.24 2002/07/17 16:22:24 dwmalon #include #include #include +#include + +#ifdef __APPLE__ +#include +#else +#define COMPAT_MODE(a,b) (1) +#endif /* __APPLE__ */ void a_gid(const char *); void a_uid(const char *); void chownerr(const char *); -u_long id(const char *, const char *); +static uid_t id(const char *, const char *); void usage(void); uid_t uid; gid_t gid; int ischown; +#ifdef __APPLE__ +int isnumeric = 0; +#endif const char *gname; int @@ -75,26 +86,35 @@ main(int argc, char **argv) { FTS *ftsp; FTSENT *p; - int Hflag, Lflag, Rflag, fflag, hflag, vflag; + int Hflag, Lflag, Pflag, Rflag, fflag, hflag, vflag; int ch, fts_options, rval; char *cp; + int unix2003_compat = 0; + int symlink_found = 0; + if (argc < 1) + usage(); cp = strrchr(argv[0], '/'); cp = (cp != NULL) ? cp + 1 : argv[0]; ischown = (strcmp(cp, "chown") == 0); - Hflag = Lflag = Rflag = fflag = hflag = vflag = 0; + Hflag = Lflag = Pflag = Rflag = fflag = hflag = vflag = 0; +#ifdef __APPLE__ + while ((ch = getopt(argc, argv, "HLPRfhnv")) != -1) +#else while ((ch = getopt(argc, argv, "HLPRfhv")) != -1) +#endif switch (ch) { case 'H': Hflag = 1; - Lflag = 0; + Lflag = Pflag = 0; break; case 'L': Lflag = 1; - Hflag = 0; + Hflag = Pflag = 0; break; case 'P': + Pflag = 1; Hflag = Lflag = 0; break; case 'R': @@ -105,7 +125,12 @@ main(int argc, char **argv) break; case 'h': hflag = 1; + break; +#ifdef __APPLE__ + case 'n': + isnumeric = 1; break; +#endif case 'v': vflag = 1; break; @@ -118,6 +143,8 @@ main(int argc, char **argv) if (argc < 2) usage(); + if (!Rflag && (Hflag || Lflag || Pflag)) + warnx("options -H, -L, -P only useful with -R"); if (Rflag) { fts_options = FTS_PHYSICAL; @@ -136,6 +163,7 @@ main(int argc, char **argv) uid = (uid_t)-1; gid = (gid_t)-1; if (ischown) { + unix2003_compat = COMPAT_MODE("bin/chown", "Unix2003"); if ((cp = strchr(*argv, ':')) != NULL) { *cp++ = '\0'; a_gid(cp); @@ -148,13 +176,16 @@ main(int argc, char **argv) } #endif a_uid(*argv); - } else + } else { + unix2003_compat = COMPAT_MODE("bin/chgrp", "Unix2003"); a_gid(*argv); + } if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL) err(1, NULL); for (rval = 0; (p = fts_read(ftsp)) != NULL;) { + symlink_found = 0; switch (p->fts_info) { case FTS_D: /* Change it at FTS_DP. */ if (!Rflag) @@ -178,19 +209,33 @@ main(int argc, char **argv) */ if (hflag) break; - else + else { + symlink_found = 1; + if (unix2003_compat) { + if (Hflag || Lflag) { /* -H or -L was specified */ + if (p->fts_errno) { + warnx("%s: %s", p->fts_name, strerror(p->fts_errno)); + rval = 1; + continue; + } + } + break; /* Otherwise symlinks keep going */ + } continue; + } default: break; } - if ((uid == (uid_t)-1 || uid == p->fts_statp->st_uid) && - (gid == (gid_t)-1 || gid == p->fts_statp->st_gid)) - continue; -#ifndef __APPLE__ - if ((hflag ? lchown : chown)(p->fts_accpath, uid, gid) == -1) { -#else - if (chown(p->fts_accpath, uid, gid) == -1) { -#endif /* __APPLE__ */ + if (unix2003_compat) { + /* Can only avoid updating times if both uid and gid are -1 */ + if ((uid == (uid_t)-1) && (gid == (gid_t)-1)) + continue; + } else { + if ((uid == (uid_t)-1 || uid == p->fts_statp->st_uid) && + (gid == (gid_t)-1 || gid == p->fts_statp->st_gid)) + continue; + } + if (((hflag || symlink_found) ? lchown : chown)(p->fts_accpath, uid, gid) == -1) { if (!fflag) { chownerr(p->fts_path); rval = 1; @@ -213,7 +258,11 @@ a_gid(const char *s) if (*s == '\0') /* Argument was "uid[:.]". */ return; gname = s; +#ifdef __APPLE__ + gid = (!isnumeric && ((gr = getgrnam(s)) != NULL)) ? gr->gr_gid : id(s, "group"); +#else gid = ((gr = getgrnam(s)) != NULL) ? gr->gr_gid : id(s, "group"); +#endif } void @@ -223,26 +272,24 @@ a_uid(const char *s) if (*s == '\0') /* Argument was "[:.]gid". */ return; +#ifdef __APPLE__ + uid = (!isnumeric && ((pw = getpwnam(s)) != NULL)) ? pw->pw_uid : id(s, "user"); +#else uid = ((pw = getpwnam(s)) != NULL) ? pw->pw_uid : id(s, "user"); +#endif } -u_long +static uid_t id(const char *name, const char *type) { - u_long val; + unsigned long val; char *ep; - /* - * XXX - * We know that uid_t's and gid_t's are unsigned longs. - */ errno = 0; val = strtoul(name, &ep, 10); - if (errno) - err(1, "%s", name); - if (*ep != '\0') + if (errno || *ep != '\0' || val > UID_MAX) errx(1, "%s: illegal %s name", name, type); - return (val); + return (uid_t)val; } void @@ -278,11 +325,21 @@ usage(void) if (ischown) (void)fprintf(stderr, "%s\n%s\n", +#ifdef __APPLE__ + "usage: chown [-fhnv] [-R [-H | -L | -P]] owner[:group]" + " file ...", + " chown [-fhnv] [-R [-H | -L | -P]] :group file ..."); +#else "usage: chown [-fhv] [-R [-H | -L | -P]] owner[:group]" " file ...", " chown [-fhv] [-R [-H | -L | -P]] :group file ..."); +#endif else (void)fprintf(stderr, "%s\n", +#ifdef __APPLE__ + "usage: chgrp [-fhnv] [-R [-H | -L | -P]] group file ..."); +#else "usage: chgrp [-fhv] [-R [-H | -L | -P]] group file ..."); +#endif exit(1); }