xref: /original-bsd/usr.bin/chflags/chflags.c (revision 68549010)
1 /*
2  * Copyright (c) 1992 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 char copyright[] =
10 "@(#) Copyright (c) 1992 The Regents of the University of California.\n\
11  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)chflags.c	5.2 (Berkeley) 03/10/92";
16 #endif /* not lint */
17 
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <errno.h>
21 #include <fts.h>
22 #include <unistd.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 typedef struct cmdset {
28 	long clrbits;
29 	long setbits;
30 } CMDS;
31 CMDS cmds;
32 int retval;
33 
34 void	 err __P((const char *, ...));
35 void	 error __P((char *));
36 int	 getflags __P((CMDS *, int));
37 void	*setflags __P((char *));
38 void	 usage __P((void));
39 
40 int
41 main(argc, argv)
42 	int argc;
43 	char *argv[];
44 {
45 	register FTS *fts;
46 	register FTSENT *p;
47 	register long oflags;
48 	register int oct;
49 	register char *flags;
50 	struct stat sb;
51 	void *set;
52 	int ch, rflag;
53 	char *ep;
54 
55 	rflag = 0;
56 	while ((ch = getopt(argc, argv, "R")) != EOF)
57 		switch((char)ch) {
58 		case 'R':
59 			rflag = 1;
60 			break;
61 		case '?':
62 		default:
63 			usage();
64 		}
65 	argv += optind;
66 	argc -= optind;
67 
68 	if (argc < 2)
69 		usage();
70 
71 	flags = *argv;
72 	if (*flags >= '0' && *flags <= '7') {
73 		oflags = (int)strtol(flags, &ep, 8);
74                 if (oflags < 0 || *ep)
75                         err("invalid flags: %s", flags);
76                 oct = 1;
77 	} else {
78 		if ((set = setflags(flags)) == NULL)
79                         err("invalid flags: %s", flags);
80 		oct = 0;
81 	}
82 
83 	retval = 0;
84 	if (rflag) {
85 		if (!(fts = fts_open(++argv,
86 		    oct ? FTS_NOSTAT|FTS_PHYSICAL : FTS_PHYSICAL, 0)))
87 			err("%s", strerror(errno));
88 		while (p = fts_read(fts))
89 			switch(p->fts_info) {
90 			case FTS_D:
91 				break;
92 			case FTS_DNR:
93 			case FTS_ERR:
94 			case FTS_NS:
95 				err("%s: %s", p->fts_path, strerror(errno));
96 			default:
97 				if (chflags(p->fts_accpath, oct ? oflags :
98 				    getflags(set, p->fts_statp->st_flags)))
99 					error(p->fts_path);
100 				break;
101 			}
102 		exit(retval);
103 	}
104 	if (oct) {
105 		while (*++argv)
106 			if (chflags(*argv, oflags))
107 				error(*argv);
108 	} else
109 		while (*++argv)
110 			if (lstat(*argv, &sb) ||
111 			    chflags(*argv, getflags(set, sb.st_flags)))
112 				error(*argv);
113 	exit(retval);
114 }
115 
116 /*
117  * These are analogous to the setmode/getmode routines in the C library.
118  */
119 void *
120 setflags(cp)
121 	char *cp;
122 {
123 	register CMDS *fset;
124 	register char *arg;
125 
126 	fset = &cmds;
127 	fset->clrbits = 0;
128 	fset->setbits = 0;
129 	while (cp) {
130 		while ((arg = strsep(&cp, ",")) != NULL && *arg == '\0')
131 			/* void */;
132 		if (!strcasecmp(arg, "dump"))
133 			fset->clrbits |= NODUMP;
134 		else if (!strcasecmp(arg, "nodump"))
135 			fset->setbits |= NODUMP;
136 		else
137 			return (NULL);
138 	}
139 	return (fset);
140 }
141 
142 int
143 getflags(fset, oflags)
144 	register CMDS *fset;
145 	register int oflags;
146 {
147 
148 	oflags &= ~fset->clrbits;
149 	oflags |= fset->setbits;
150 	return (oflags);
151 }
152 
153 #if __STDC__
154 #include <stdarg.h>
155 #else
156 #include <varargs.h>
157 #endif
158 
159 void
160 #if __STDC__
161 err(const char *fmt, ...)
162 #else
163 err(fmt, va_alist)
164 	char *fmt;
165         va_dcl
166 #endif
167 {
168 	va_list ap;
169 #if __STDC__
170 	va_start(ap, fmt);
171 #else
172 	va_start(ap);
173 #endif
174 	(void)fprintf(stderr, "chflags: ");
175 	(void)vfprintf(stderr, fmt, ap);
176 	va_end(ap);
177 	(void)fprintf(stderr, "\n");
178 	exit(1);
179 	/* NOTREACHED */
180 }
181 
182 void
183 error(name)
184 	char *name;
185 {
186 	(void)fprintf(stderr, "chflags: %s: %s.\n", name, strerror(errno));
187 	retval = 1;
188 }
189 
190 void
191 usage()
192 {
193 	(void)fprintf(stderr, "usage: chflags [-R] flags file ...\n");
194 	exit(1);
195 }
196