1*da39777eSkre /* $NetBSD: chflags.c,v 1.18 2023/05/05 04:14:02 kre Exp $ */
26e0c4dedSjtc
39636069cSjtc /*
49636069cSjtc * Copyright (c) 1992, 1993, 1994
59636069cSjtc * The Regents of the University of California. All rights reserved.
69636069cSjtc *
79636069cSjtc * Redistribution and use in source and binary forms, with or without
89636069cSjtc * modification, are permitted provided that the following conditions
99636069cSjtc * are met:
109636069cSjtc * 1. Redistributions of source code must retain the above copyright
119636069cSjtc * notice, this list of conditions and the following disclaimer.
129636069cSjtc * 2. Redistributions in binary form must reproduce the above copyright
139636069cSjtc * notice, this list of conditions and the following disclaimer in the
149636069cSjtc * documentation and/or other materials provided with the distribution.
1589aaa1bbSagc * 3. Neither the name of the University nor the names of its contributors
169636069cSjtc * may be used to endorse or promote products derived from this software
179636069cSjtc * without specific prior written permission.
189636069cSjtc *
199636069cSjtc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
209636069cSjtc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
219636069cSjtc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
229636069cSjtc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
239636069cSjtc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
249636069cSjtc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
259636069cSjtc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
269636069cSjtc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
279636069cSjtc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
289636069cSjtc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
299636069cSjtc * SUCH DAMAGE.
309636069cSjtc */
319636069cSjtc
325f18af1fSlukem #include <sys/cdefs.h>
339636069cSjtc #ifndef lint
3498e5374cSlukem __COPYRIGHT("@(#) Copyright (c) 1992, 1993, 1994\
3598e5374cSlukem The Regents of the University of California. All rights reserved.");
369636069cSjtc #endif /* not lint */
379636069cSjtc
389636069cSjtc #ifndef lint
39e0703abaSglass #if 0
40e0703abaSglass static char sccsid[] = "from: @(#)chflags.c 8.5 (Berkeley) 4/1/94";
41e0703abaSglass #else
42*da39777eSkre __RCSID("$NetBSD: chflags.c,v 1.18 2023/05/05 04:14:02 kre Exp $");
43e0703abaSglass #endif
449636069cSjtc #endif /* not lint */
459636069cSjtc
469636069cSjtc #include <sys/types.h>
479636069cSjtc #include <sys/stat.h>
489636069cSjtc
499636069cSjtc #include <err.h>
509636069cSjtc #include <errno.h>
519636069cSjtc #include <fts.h>
529636069cSjtc #include <stdio.h>
539636069cSjtc #include <stdlib.h>
549636069cSjtc #include <string.h>
559636069cSjtc #include <unistd.h>
5649444675She #include <util.h>
5714a817a5Smrg
586e33bec8Sjoerg __dead static void usage(void);
599636069cSjtc
609636069cSjtc int
main(int argc,char * argv[])6180a3a079Sxtraeme main(int argc, char *argv[])
629636069cSjtc {
639636069cSjtc FTS *ftsp;
649636069cSjtc FTSENT *p;
6575015c55Senami u_long clear, set, newflags;
669636069cSjtc long val;
67*da39777eSkre int Hflag, Lflag, Rflag, ch, fts_options, dflag, hflag, oct, rval;
689636069cSjtc char *flags, *ep;
69971b39dfSxtraeme int (*change_flags)(const char *, u_long);
709636069cSjtc
71*da39777eSkre Hflag = Lflag = Rflag = dflag = hflag = 0;
72*da39777eSkre while ((ch = getopt(argc, argv, "HLPRdh")) != -1)
739636069cSjtc switch (ch) {
749636069cSjtc case 'H':
759636069cSjtc Hflag = 1;
7643bbf1aeSenami Lflag = 0;
779636069cSjtc break;
789636069cSjtc case 'L':
799636069cSjtc Lflag = 1;
8043bbf1aeSenami Hflag = 0;
819636069cSjtc break;
829636069cSjtc case 'P':
839636069cSjtc Hflag = Lflag = 0;
849636069cSjtc break;
859636069cSjtc case 'R':
869636069cSjtc Rflag = 1;
879636069cSjtc break;
88*da39777eSkre case 'd':
89*da39777eSkre dflag = 1;
90*da39777eSkre break;
9175015c55Senami case 'h':
9275015c55Senami hflag = 1;
9375015c55Senami break;
949636069cSjtc case '?':
959636069cSjtc default:
969636069cSjtc usage();
979636069cSjtc }
989636069cSjtc argv += optind;
999636069cSjtc argc -= optind;
1009636069cSjtc
1019636069cSjtc if (argc < 2)
1029636069cSjtc usage();
1039636069cSjtc
1049636069cSjtc fts_options = FTS_PHYSICAL;
1059636069cSjtc if (Rflag) {
1069636069cSjtc if (Hflag)
1079636069cSjtc fts_options |= FTS_COMFOLLOW;
1089636069cSjtc if (Lflag) {
1099636069cSjtc fts_options &= ~FTS_PHYSICAL;
1109636069cSjtc fts_options |= FTS_LOGICAL;
1119636069cSjtc }
112525b0502Sbjh21 } else if (!hflag)
113525b0502Sbjh21 fts_options |= FTS_COMFOLLOW;
1149636069cSjtc
1159636069cSjtc flags = *argv;
1169636069cSjtc if (*flags >= '0' && *flags <= '7') {
1179636069cSjtc errno = 0;
1189636069cSjtc val = strtol(flags, &ep, 8);
1199636069cSjtc if (val < 0)
1209636069cSjtc errno = ERANGE;
1219636069cSjtc if (errno)
1229636069cSjtc err(1, "invalid flags: %s", flags);
1239636069cSjtc if (*ep)
1249636069cSjtc errx(1, "invalid flags: %s", flags);
1259636069cSjtc set = val;
1269636069cSjtc oct = 1;
1279636069cSjtc } else {
1289636069cSjtc if (string_to_flags(&flags, &set, &clear))
1299636069cSjtc errx(1, "invalid flag: %s", flags);
1309636069cSjtc clear = ~clear;
1319636069cSjtc oct = 0;
1329636069cSjtc }
1339636069cSjtc
13443bbf1aeSenami if ((ftsp = fts_open(++argv, fts_options, NULL)) == NULL)
13575015c55Senami err(1, "fts_open");
1369636069cSjtc
1379636069cSjtc for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
13875015c55Senami change_flags = chflags;
1399636069cSjtc switch (p->fts_info) {
1409636069cSjtc case FTS_D:
1419636069cSjtc if (Rflag) /* Change it at FTS_DP. */
1429636069cSjtc continue;
1439636069cSjtc fts_set(ftsp, p, FTS_SKIP);
1449636069cSjtc break;
1459636069cSjtc case FTS_DNR: /* Warn, chflag, continue. */
1469636069cSjtc warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
1479636069cSjtc rval = 1;
1489636069cSjtc break;
1499636069cSjtc case FTS_ERR: /* Warn, continue. */
1509636069cSjtc case FTS_NS:
1519636069cSjtc warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
1529636069cSjtc rval = 1;
1539636069cSjtc continue;
15475015c55Senami case FTS_SL: /* Ignore unless -h. */
15575015c55Senami /*
15675015c55Senami * All symlinks we found while doing a physical
15775015c55Senami * walk end up here.
15875015c55Senami */
15975015c55Senami if (!hflag)
16075015c55Senami continue;
16175015c55Senami /*
16275015c55Senami * Note that if we follow a symlink, fts_info is
16375015c55Senami * not FTS_SL but FTS_F or whatever. And we should
16475015c55Senami * use lchflags only for FTS_SL and should use chflags
16575015c55Senami * for others.
16675015c55Senami */
16775015c55Senami change_flags = lchflags;
16875015c55Senami break;
16975015c55Senami case FTS_SLNONE: /* Ignore. */
1709636069cSjtc /*
1719636069cSjtc * The only symlinks that end up here are ones that
17275015c55Senami * don't point to anything. Note that if we are
1736ef0b3e4Sandvar * doing a physical walk, we never reach here unless
17475015c55Senami * we asked to follow explicitly.
1759636069cSjtc */
1769636069cSjtc continue;
1779636069cSjtc default:
1789636069cSjtc break;
1799636069cSjtc }
18075015c55Senami if (oct)
18175015c55Senami newflags = set;
18275015c55Senami else {
18375015c55Senami newflags = p->fts_statp->st_flags;
18475015c55Senami newflags |= set;
18575015c55Senami newflags &= clear;
1869636069cSjtc }
187*da39777eSkre if (dflag && newflags == p->fts_statp->st_flags)
188*da39777eSkre continue;
18975015c55Senami if ((*change_flags)(p->fts_accpath, newflags)) {
1909636069cSjtc warn("%s", p->fts_path);
1919636069cSjtc rval = 1;
1929636069cSjtc }
19375015c55Senami }
1949636069cSjtc if (errno)
1959636069cSjtc err(1, "fts_read");
1969636069cSjtc exit(rval);
1979636069cSjtc }
1989636069cSjtc
1996e33bec8Sjoerg static void
usage(void)20080a3a079Sxtraeme usage(void)
2019636069cSjtc {
20275015c55Senami
2039636069cSjtc (void)fprintf(stderr,
204*da39777eSkre "usage: chflags [-R [-H | -L | -P]] [-dh] flags file ...\n");
2059636069cSjtc exit(1);
2069636069cSjtc }
207