From f49acbb15c88c49847785684e639e67b8cfe3f6d Mon Sep 17 00:00:00 2001 From: Keith Bostic Date: Thu, 31 Mar 1994 23:58:08 -0800 Subject: [PATCH] POSIX 1003.2B/D9 symbolic links SCCS-vsn: usr.bin/chflags/chflags.1 8.2 SCCS-vsn: usr.bin/chflags/chflags.c 8.2 --- usr/src/usr.bin/chflags/chflags.1 | 50 ++++++++---- usr/src/usr.bin/chflags/chflags.c | 129 +++++++++++++++++++----------- 2 files changed, 115 insertions(+), 64 deletions(-) diff --git a/usr/src/usr.bin/chflags/chflags.1 b/usr/src/usr.bin/chflags/chflags.1 index 6eba4f3296..737513368e 100644 --- a/usr/src/usr.bin/chflags/chflags.1 +++ b/usr/src/usr.bin/chflags/chflags.1 @@ -1,4 +1,4 @@ -.\" Copyright (c) 1989, 1990, 1993 +.\" Copyright (c) 1989, 1990, 1993, 1994 .\" The Regents of the University of California. All rights reserved. .\" .\" This code is derived from software contributed to Berkeley by @@ -6,7 +6,7 @@ .\" .\" %sccs.include.redist.roff% .\" -.\" @(#)chflags.1 8.1 (Berkeley) %G% +.\" @(#)chflags.1 8.2 (Berkeley) %G% .\" .Dd .Dt CHFLAGS 1 @@ -16,7 +16,10 @@ .Nd change file flags .Sh SYNOPSIS .Nm chflags -.Op Fl HRh +.Oo +.Fl R +.Op Fl H | Fl L | Fl P +.Oc .Ar flags .Ar file ... .Sh DESCRIPTION @@ -30,16 +33,21 @@ 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 chflags -changes the flags of all files in the file hierarchy below it followed -by the flags of the directory itself. -.It Fl h -When encountering a symbolic link anywhere in the traversal, follow it. +Change the file flags for the file hierarchies rooted +in the files instead of just the files themselves. .El .Pp Flags are a comma separated list of keywords. @@ -61,13 +69,23 @@ For example: nodump the file should never be dumped .Ed .Pp -The flags of a symbolic link are immutable, so unless the -.Fl h -or +Symbolic links do not have flags, so unless the .Fl H -flag is set, +or +.Fl L +option is set, .Nm chflags on a symbolic link always succeeds and has no effect. +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 The .Nm chflags diff --git a/usr/src/usr.bin/chflags/chflags.c b/usr/src/usr.bin/chflags/chflags.c index e36183ce7a..a860e433ec 100644 --- a/usr/src/usr.bin/chflags/chflags.c +++ b/usr/src/usr.bin/chflags/chflags.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1992, 1993 + * Copyright (c) 1992, 1993, 1994 * The Regents of the University of California. All rights reserved. * * %sccs.include.redist.c% @@ -7,18 +7,19 @@ #ifndef lint static char copyright[] = -"@(#) Copyright (c) 1992, 1993\n\ +"@(#) Copyright (c) 1992, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)chflags.c 8.1 (Berkeley) %G%"; +static char sccsid[] = "@(#)chflags.c 8.2 (Berkeley) %G%"; #endif /* not lint */ #include #include #include +#include #include #include #include @@ -33,30 +34,32 @@ main(argc, argv) int argc; char *argv[]; { - register FTS *ftsp; - register FTSENT *p; - register int oct; + FTS *ftsp; + FTSENT *p; u_long clear, set; - int ch, fts_options, retval, rflag, hflag, Hflag; + long val; + int Hflag, Lflag, Pflag, Rflag, ch, fts_options, oct, rval; char *flags, *ep; - rflag = hflag = Hflag = 0; - fts_options = FTS_PHYSICAL; - while ((ch = getopt(argc, argv, "HRh")) != EOF) - switch((char)ch) { + Hflag = Lflag = Pflag = Rflag = 0; + while ((ch = getopt(argc, argv, "HLPR")) != EOF) + switch (ch) { case 'H': Hflag = 1; - fts_options |= FTS_COMFOLLOW; + Lflag = Pflag = 0; break; - case 'R': - rflag = 1; + case 'L': + Lflag = 1; + Hflag = Pflag = 0; break; - case 'h': - hflag = 1; - fts_options &= ~FTS_PHYSICAL; - fts_options |= FTS_LOGICAL; + case 'P': + Pflag = 1; + Hflag = Lflag = 0; + break; + case 'R': + Rflag = 1; break; - case '?': + case '?': default: usage(); } @@ -66,12 +69,27 @@ main(argc, argv) if (argc < 2) usage(); + fts_options = FTS_PHYSICAL; + if (Rflag) { + if (Hflag) + fts_options |= FTS_COMFOLLOW; + if (Lflag) { + fts_options &= ~FTS_PHYSICAL; + fts_options |= FTS_LOGICAL; + } + } + flags = *argv; if (*flags >= '0' && *flags <= '7') { - set = (int)strtol(flags, &ep, 8); - if (set < 0 || *ep) + errno = 0; + val = strtol(flags, &ep, 8); + if (val < 0) + errno = ERANGE; + if (errno) + err(1, "invalid flags: %s", flags); + if (*ep) errx(1, "invalid flags: %s", flags); - fts_options |= FTS_NOSTAT; + set = val; oct = 1; } else { if (string_to_flags(&flags, &set, &clear)) @@ -81,43 +99,58 @@ main(argc, argv) } if ((ftsp = fts_open(++argv, fts_options , 0)) == NULL) - err(1, ""); + err(1, NULL); - for (retval = 0; p = fts_read(ftsp);) - switch(p->fts_info) { + for (rval = 0; (p = fts_read(ftsp)) != NULL;) { + switch (p->fts_info) { case FTS_D: - if (!rflag) - fts_set(ftsp, p, FTS_SKIP); + if (Rflag) /* Change it at FTS_DP. */ + continue; + fts_set(ftsp, p, FTS_SKIP); break; - case FTS_DNR: - case FTS_ERR: + case FTS_DC: /* Ignore. */ + continue; + case FTS_DNR: /* Warn, chflag, continue. */ + errno = p->fts_errno; + warn("%s", p->fts_path); + rval = 1; + break; + 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 (oct) { - if (!chflags(p->fts_accpath, set)) - break; - } else { - p->fts_statp->st_flags |= set; - p->fts_statp->st_flags &= clear; - if (!chflags(p->fts_accpath, - p->fts_statp->st_flags)) - break; - } + errno = p->fts_errno; warn("%s", p->fts_path); - retval = 1; + 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 (oct) { + if (!chflags(p->fts_accpath, set)) + continue; + } else { + p->fts_statp->st_flags |= set; + p->fts_statp->st_flags &= clear; + if (!chflags(p->fts_accpath, p->fts_statp->st_flags)) + continue; + } + warn("%s", p->fts_path); + rval = 1; + } + exit(rval); } void usage() { - (void)fprintf(stderr, "usage: chflags [-HRh] flags file ...\n"); + (void)fprintf(stderr, + "usage: chflags [-R [-H | -L | -P]] flags file ...\n"); exit(1); } -- 2.20.1