1 |
/*- |
2 |
* Copyright (c) 1992, 1993, 1994 |
3 |
* The Regents of the University of California. All rights reserved. |
4 |
* |
5 |
* Redistribution and use in source and binary forms, with or without |
6 |
* modification, are permitted provided that the following conditions |
7 |
* are met: |
8 |
* 1. Redistributions of source code must retain the above copyright |
9 |
* notice, this list of conditions and the following disclaimer. |
10 |
* 2. Redistributions in binary form must reproduce the above copyright |
11 |
* notice, this list of conditions and the following disclaimer in the |
12 |
* documentation and/or other materials provided with the distribution. |
13 |
* 4. Neither the name of the University nor the names of its contributors |
14 |
* may be used to endorse or promote products derived from this software |
15 |
* without specific prior written permission. |
16 |
* |
17 |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
18 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
19 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
20 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
21 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
22 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
23 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
24 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
25 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
26 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
27 |
* SUCH DAMAGE. |
28 |
*/ |
29 |
|
30 |
#if 0 |
31 |
#ifndef lint |
32 |
static const char copyright[] = |
33 |
"@(#) Copyright (c) 1992, 1993, 1994\n\ |
34 |
The Regents of the University of California. All rights reserved.\n"; |
35 |
#endif |
36 |
|
37 |
#ifndef lint |
38 |
static char sccsid[] = "@(#)chflags.c 8.5 (Berkeley) 4/1/94"; |
39 |
#endif |
40 |
#endif |
41 |
|
42 |
#include <sys/cdefs.h> |
43 |
__FBSDID("$FreeBSD: release/10.0.0/bin/chflags/chflags.c 248597 2013-03-21 22:44:33Z pjd $"); |
44 |
|
45 |
#include <sys/types.h> |
46 |
#include <sys/stat.h> |
47 |
|
48 |
#include <err.h> |
49 |
#include <errno.h> |
50 |
#include <fts.h> |
51 |
#include <stdio.h> |
52 |
#include <stdlib.h> |
53 |
#include <string.h> |
54 |
#include <unistd.h> |
55 |
|
56 |
static void usage(void); |
57 |
|
58 |
int |
59 |
main(int argc, char *argv[]) |
60 |
{ |
61 |
FTS *ftsp; |
62 |
FTSENT *p; |
63 |
u_long clear, newflags, set; |
64 |
long val; |
65 |
int Hflag, Lflag, Rflag, fflag, hflag, vflag; |
66 |
int ch, fts_options, oct, rval; |
67 |
char *flags, *ep; |
68 |
int (*change_flags)(const char *, unsigned long); |
69 |
|
70 |
Hflag = Lflag = Rflag = fflag = hflag = vflag = 0; |
71 |
while ((ch = getopt(argc, argv, "HLPRfhv")) != -1) |
72 |
switch (ch) { |
73 |
case 'H': |
74 |
Hflag = 1; |
75 |
Lflag = 0; |
76 |
break; |
77 |
case 'L': |
78 |
Lflag = 1; |
79 |
Hflag = 0; |
80 |
break; |
81 |
case 'P': |
82 |
Hflag = Lflag = 0; |
83 |
break; |
84 |
case 'R': |
85 |
Rflag = 1; |
86 |
break; |
87 |
case 'f': |
88 |
fflag = 1; |
89 |
break; |
90 |
case 'h': |
91 |
hflag = 1; |
92 |
break; |
93 |
case 'v': |
94 |
vflag++; |
95 |
break; |
96 |
case '?': |
97 |
default: |
98 |
usage(); |
99 |
} |
100 |
argv += optind; |
101 |
argc -= optind; |
102 |
|
103 |
if (argc < 2) |
104 |
usage(); |
105 |
|
106 |
if (Rflag) { |
107 |
fts_options = FTS_PHYSICAL; |
108 |
if (hflag) |
109 |
errx(1, "the -R and -h options " |
110 |
"may not be specified together"); |
111 |
if (Hflag) |
112 |
fts_options |= FTS_COMFOLLOW; |
113 |
if (Lflag) { |
114 |
fts_options &= ~FTS_PHYSICAL; |
115 |
fts_options |= FTS_LOGICAL; |
116 |
} |
117 |
} else |
118 |
fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL; |
119 |
|
120 |
change_flags = hflag ? lchflags : chflags; |
121 |
|
122 |
flags = *argv; |
123 |
if (*flags >= '0' && *flags <= '7') { |
124 |
errno = 0; |
125 |
val = strtol(flags, &ep, 8); |
126 |
if (val < 0) |
127 |
errno = ERANGE; |
128 |
if (errno) |
129 |
err(1, "invalid flags: %s", flags); |
130 |
if (*ep) |
131 |
errx(1, "invalid flags: %s", flags); |
132 |
set = val; |
133 |
oct = 1; |
134 |
} else { |
135 |
if (strtofflags(&flags, &set, &clear)) |
136 |
errx(1, "invalid flag: %s", flags); |
137 |
clear = ~clear; |
138 |
oct = 0; |
139 |
} |
140 |
|
141 |
if ((ftsp = fts_open(++argv, fts_options , 0)) == NULL) |
142 |
err(1, NULL); |
143 |
|
144 |
for (rval = 0; (p = fts_read(ftsp)) != NULL;) { |
145 |
switch (p->fts_info) { |
146 |
case FTS_D: /* Change it at FTS_DP if we're recursive. */ |
147 |
if (!Rflag) |
148 |
fts_set(ftsp, p, FTS_SKIP); |
149 |
continue; |
150 |
case FTS_DNR: /* Warn, chflag, continue. */ |
151 |
warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); |
152 |
rval = 1; |
153 |
break; |
154 |
case FTS_ERR: /* Warn, continue. */ |
155 |
case FTS_NS: |
156 |
warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); |
157 |
rval = 1; |
158 |
continue; |
159 |
case FTS_SL: /* Ignore. */ |
160 |
case FTS_SLNONE: |
161 |
/* |
162 |
* The only symlinks that end up here are ones that |
163 |
* don't point to anything and ones that we found |
164 |
* doing a physical walk. |
165 |
*/ |
166 |
if (!hflag) |
167 |
continue; |
168 |
/* FALLTHROUGH */ |
169 |
default: |
170 |
break; |
171 |
} |
172 |
if (oct) |
173 |
newflags = set; |
174 |
else |
175 |
newflags = (p->fts_statp->st_flags | set) & clear; |
176 |
if (newflags == p->fts_statp->st_flags) |
177 |
continue; |
178 |
if ((*change_flags)(p->fts_accpath, newflags) && !fflag) { |
179 |
warn("%s", p->fts_path); |
180 |
rval = 1; |
181 |
} else if (vflag) { |
182 |
(void)printf("%s", p->fts_path); |
183 |
if (vflag > 1) |
184 |
(void)printf(": 0%lo -> 0%lo", |
185 |
(u_long)p->fts_statp->st_flags, |
186 |
newflags); |
187 |
(void)printf("\n"); |
188 |
} |
189 |
} |
190 |
if (errno) |
191 |
err(1, "fts_read"); |
192 |
exit(rval); |
193 |
} |
194 |
|
195 |
static void |
196 |
usage(void) |
197 |
{ |
198 |
(void)fprintf(stderr, |
199 |
"usage: chflags [-fhv] [-R [-H | -L | -P]] flags file ...\n"); |
200 |
exit(1); |
201 |
} |