From: Keith Bostic Date: Fri, 1 Apr 1994 07:32:04 +0000 (-0800) Subject: POSIX 1003.2B/D9 symbolic links X-Git-Tag: BSD-4_4_Lite1-Snapshot-Development~44 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/17beb503f704f03048713d3802423fd44c790489 POSIX 1003.2B/D9 symbolic links SCCS-vsn: bin/chmod/chmod.1 8.3 SCCS-vsn: bin/chmod/chmod.c 8.4 --- diff --git a/usr/src/bin/chmod/chmod.1 b/usr/src/bin/chmod/chmod.1 index 0d6cccb640..f129eb279f 100644 --- a/usr/src/bin/chmod/chmod.1 +++ b/usr/src/bin/chmod/chmod.1 @@ -6,7 +6,7 @@ .\" .\" %sccs.include.redist.roff% .\" -.\" @(#)chmod.1 8.2 (Berkeley) %G% +.\" @(#)chmod.1 8.3 (Berkeley) %G% .\" .Dd .Dt CHMOD 1 @@ -16,7 +16,10 @@ .Nd change file modes .Sh SYNOPSIS .Nm chmod -.Op Fl HRh +.Oo +.Fl R +.Op Fl H | Fl L | Fl P +.Oc .Ar mode .Ar file ... .Sh DESCRIPTION @@ -30,25 +33,40 @@ operand. The options are as follows: .Bl -tag -width Ds .It Fl H -When encountering a symbolic link on the command line, follow it. All other -symbolic links encountered in the traversal are not followed. +If the +.Fl R +option is specified, symbolic links on the command line are followed. +(Symbolic links encountered in the tree traversal are not followed.) +.It Fl L +If the +.Fl R +option is specified, all symbolic links are followed. +.It Fl P +If the +.Fl R +option is specified, no symbolic links are followed. .It Fl R -Traverse a file hierarchy. -For each file that is of type directory, -.Nm chmod -changes the mode of all files in the file hierarchy below it followed -by the mode of the directory itself. -.It Fl h -When encountering a symbolic link anywhere in the traversal, follow it. +Change the modes of the file hierarchies rooted in the files +instead of just the files themselves. .El .Pp -The mode of a symbolic link is immutable, so unless the -.Fl h -or +Symbolic links do not have modes, so unless the .Fl H -flag is set, +or +.Fl L +option is set, .Nm chmod on a symbolic link is a no-op. +The +.Fl H , +.Fl L +and +.Fl P +options are ignored unless the +.Fl R +option is specified. +In addition, these options override each other and the +command's actions are determined by the last one specified. .Pp Only the owner of a file or the super-user is permitted to change the mode of a file. @@ -216,7 +234,7 @@ already searchable/executable by anyone. .It Li 755 .It Li u=rwx,go=rx .It Li u=rwx,go=u-w -make a file readable/executable by everyone and writeable by the owner only. +make a file readable/executable by everyone and writable by the owner only. .Pp .It Li go= clear all mode bits for group and others. diff --git a/usr/src/bin/chmod/chmod.c b/usr/src/bin/chmod/chmod.c index e0f2c9fdbb..17e0b4fd84 100644 --- a/usr/src/bin/chmod/chmod.c +++ b/usr/src/bin/chmod/chmod.c @@ -12,7 +12,7 @@ static char copyright[] = #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)chmod.c 8.3 (Berkeley) %G%"; +static char sccsid[] = "@(#)chmod.c 8.4 (Berkeley) %G%"; #endif /* not lint */ #include @@ -37,28 +37,39 @@ main(argc, argv) register FTSENT *p; register int oct, omode; mode_t *set; - int ch, fflag, rflag, hflag, Hflag; - int fts_options, retval; + int Hflag, Lflag, Pflag, Rflag, ch, fflag, fts_options, hflag, rval; char *ep, *mode; - fts_options = FTS_PHYSICAL; - fflag = rflag = hflag = Hflag = 0; - while ((ch = getopt(argc, argv, "HRXfghorstuwx")) != EOF) + Hflag = Lflag = Pflag = Rflag = fflag = hflag = 0; + while ((ch = getopt(argc, argv, "HLPRXfgorstuwx")) != EOF) switch (ch) { case 'H': Hflag = 1; - fts_options |= FTS_COMFOLLOW; + Lflag = Pflag = 0; + break; + case 'L': + Lflag = 1; + Hflag = Pflag = 0; + break; + case 'P': + Pflag = 1; + Hflag = Lflag = 0; break; case 'R': - rflag = 1; + Rflag = 1; break; - case 'f': /* XXX: no longer documented. */ + case 'f': /* XXX: undocumented. */ fflag = 1; break; case 'h': + /* + * In System V (and probably POSIX.2) the -h option + * causes chmod to change the mode of the symbolic + * link. 4.4BSD's symbolic links don't have modes, + * so it's an undocumented noop. Do syntax checking, + * though. + */ hflag = 1; - fts_options &= ~FTS_PHYSICAL; - fts_options |= FTS_LOGICAL; break; /* * XXX @@ -83,6 +94,19 @@ done: argv += optind; if (argc < 2) usage(); + fts_options = FTS_PHYSICAL; + if (Rflag) { + if (hflag) + errx(1, + "the -R and -h options may not be specified together."); + if (Hflag) + fts_options |= FTS_COMFOLLOW; + if (Lflag) { + fts_options &= ~FTS_PHYSICAL; + fts_options |= FTS_LOGICAL; + } + } + mode = *argv; if (*mode >= '0' && *mode <= '7') { omode = (int)strtol(mode, &ep, 8); @@ -95,38 +119,52 @@ done: argv += optind; oct = 0; } - retval = 0; if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL) - err(1, ""); - while ((p = fts_read(ftsp)) != NULL) + err(1, NULL); + for (rval = 0; (p = fts_read(ftsp)) != NULL;) { switch (p->fts_info) { case FTS_D: - if (!rflag) - fts_set(ftsp, p, FTS_SKIP); - case FTS_SL: - case FTS_SLNONE: + if (Rflag) /* Change it at FTS_DP. */ + continue; + fts_set(ftsp, p, FTS_SKIP); + break; + case FTS_DC: /* Ignore. */ + continue; + case FTS_DNR: /* Warn, chmod, continue. */ + errno = p->fts_errno; + warn("%s", p->fts_path); + rval = 1; break; - case FTS_DNR: - case FTS_ERR: + case FTS_ERR: /* Warn, continue. */ case FTS_NS: - err(1, "%s", p->fts_path); - default: - if (p->fts_info == FTS_SL && !(hflag || - (Hflag && p->fts_level == FTS_ROOTLEVEL))) - continue; - if (chmod(p->fts_accpath, oct ? omode : - getmode(set, p->fts_statp->st_mode)) && !fflag) { - warn(p->fts_path); - retval = 1; - } + errno = p->fts_errno; + warn("%s", p->fts_path); + rval = 1; + continue; + case FTS_SL: /* Ignore. */ + case FTS_SLNONE: + /* + * The only symlinks that end up here are ones that + * don't point to anything and ones that we found + * doing a physical walk. + */ + continue; + default: break; } - exit(retval); + if (chmod(p->fts_accpath, oct ? omode : + getmode(set, p->fts_statp->st_mode)) && !fflag) { + warn(p->fts_path); + rval = 1; + } + } + exit(rval); } void usage() { - (void)fprintf(stderr, "usage: chmod [-HRh] mode file ...\n"); + (void)fprintf(stderr, + "usage: chmod [-R [-H | -L | -P]] mode file ...\n"); exit(1); }