xref: /original-bsd/usr.bin/chflags/chflags.c (revision c3e32dec)
1 /*
2  * Copyright (c) 1992, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1992, 1993\n\
11 	The Regents of the University of California.  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)chflags.c	8.1 (Berkeley) 06/06/93";
16 #endif /* not lint */
17 
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 
21 #include <err.h>
22 #include <fts.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 
28 u_long	string_to_flags __P((char **, u_long *, u_long *));
29 void	usage __P((void));
30 
31 int
32 main(argc, argv)
33 	int argc;
34 	char *argv[];
35 {
36 	register FTS *ftsp;
37 	register FTSENT *p;
38 	register int oct;
39 	u_long clear, set;
40 	int ch, fts_options, retval, rflag, hflag, Hflag;
41 	char *flags, *ep;
42 
43 	rflag = hflag = Hflag = 0;
44 	fts_options = FTS_PHYSICAL;
45 	while ((ch = getopt(argc, argv, "HRh")) != EOF)
46 		switch((char)ch) {
47 		case 'H':
48 			Hflag = 1;
49 			fts_options |= FTS_COMFOLLOW;
50 			break;
51 		case 'R':
52 			rflag = 1;
53 			break;
54 		case 'h':
55 			hflag = 1;
56 			fts_options &= ~FTS_PHYSICAL;
57 			fts_options |= FTS_LOGICAL;
58 			break;
59       		case '?':
60 		default:
61 			usage();
62 		}
63 	argv += optind;
64 	argc -= optind;
65 
66 	if (argc < 2)
67 		usage();
68 
69 	flags = *argv;
70 	if (*flags >= '0' && *flags <= '7') {
71 		set = (int)strtol(flags, &ep, 8);
72                 if (set < 0 || *ep)
73                         errx(1, "invalid flags: %s", flags);
74 		fts_options |= FTS_NOSTAT;
75                 oct = 1;
76 	} else {
77 		if (string_to_flags(&flags, &set, &clear))
78                         errx(1, "invalid flag: %s", flags);
79 		clear = ~clear;
80 		oct = 0;
81 	}
82 
83 	if ((ftsp = fts_open(++argv, fts_options , 0)) == NULL)
84 		err(1, "");
85 
86 	for (retval = 0; p = fts_read(ftsp);)
87 		switch(p->fts_info) {
88 		case FTS_D:
89 			if (!rflag)
90 				fts_set(ftsp, p, FTS_SKIP);
91 			break;
92 		case FTS_DNR:
93 		case FTS_ERR:
94 		case FTS_NS:
95 			err(1, "%s", p->fts_path);
96 		default:
97                         if (p->fts_info == FTS_SL &&
98                             !(hflag ||
99                             (Hflag && p->fts_level == FTS_ROOTLEVEL)))
100 				continue;
101 			if (oct) {
102 				if (!chflags(p->fts_accpath, set))
103 					break;
104 			} else {
105 				p->fts_statp->st_flags |= set;
106 				p->fts_statp->st_flags &= clear;
107 				if (!chflags(p->fts_accpath,
108 				    p->fts_statp->st_flags))
109 					break;
110 			}
111 			warn("%s", p->fts_path);
112 			retval = 1;
113 			break;
114 		}
115 	exit(retval);
116 }
117 
118 void
119 usage()
120 {
121 	(void)fprintf(stderr, "usage: chflags [-HRh] flags file ...\n");
122 	exit(1);
123 }
124