]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - io/attr.c
progs: clean up all remaining xfs*h includes
[thirdparty/xfsprogs-dev.git] / io / attr.c
CommitLineData
2ac030ae 1/*
da23017d
NS
2 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
2ac030ae 4 *
da23017d
NS
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
2ac030ae
NS
7 * published by the Free Software Foundation.
8 *
da23017d
NS
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
2ac030ae 13 *
da23017d
NS
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2ac030ae
NS
17 */
18
897853d5
DC
19#include "xfs/xfs.h"
20#include "xfs/command.h"
21#include "xfs/input.h"
2ac030ae
NS
22#include "init.h"
23#include "io.h"
24
25static cmdinfo_t chattr_cmd;
26static cmdinfo_t lsattr_cmd;
45532840
NS
27static unsigned int orflags;
28static unsigned int andflags;
3d93ccb7
NS
29unsigned int recurse_all;
30unsigned int recurse_dir;
2ac030ae 31
2ac030ae
NS
32static struct xflags {
33 uint flag;
34 char *shortname;
35 char *longname;
36} xflags[] = {
ae541a2b
NS
37 { XFS_XFLAG_REALTIME, "r", "realtime" },
38 { XFS_XFLAG_PREALLOC, "p", "prealloc" },
39 { XFS_XFLAG_IMMUTABLE, "i", "immutable" },
40 { XFS_XFLAG_APPEND, "a", "append-only" },
41 { XFS_XFLAG_SYNC, "s", "sync" },
42 { XFS_XFLAG_NOATIME, "A", "no-atime" },
43 { XFS_XFLAG_NODUMP, "d", "no-dump" },
44 { XFS_XFLAG_RTINHERIT, "t", "rt-inherit" },
45 { XFS_XFLAG_PROJINHERIT, "P", "proj-inherit" },
46 { XFS_XFLAG_NOSYMLINKS, "n", "nosymlinks" },
47 { XFS_XFLAG_EXTSIZE, "e", "extsize" },
48 { XFS_XFLAG_EXTSZINHERIT, "E", "extsz-inherit" },
2d5121ac
BN
49 { XFS_XFLAG_NODEFRAG, "f", "no-defrag" },
50 { XFS_XFLAG_FILESTREAM, "S", "filestream" },
2ac030ae
NS
51 { 0, NULL, NULL }
52};
2d5121ac 53#define CHATTR_XFLAG_LIST "r"/*p*/"iasAdtPneEfS"
2ac030ae
NS
54
55static void
56lsattr_help(void)
57{
58 printf(_(
59"\n"
60" displays the set of extended inode flags associated with the current file\n"
61"\n"
62" Each individual flag is displayed as a single character, in this order:\n"
63" r -- file data is stored in the realtime section\n"
64" p -- file has preallocated extents (cannot be changed using chattr)\n"
65" i -- immutable, file cannot be modified\n"
66" a -- append-only, file can only be appended to\n"
67" s -- all updates are synchronous\n"
68" A -- the access time is not updated for this inode\n"
69" d -- do not include this file in a dump of the filesystem\n"
70" t -- child created in this directory has realtime bit set by default\n"
71" P -- child created in this directory has parents project ID by default\n"
72" n -- symbolic links cannot be created in this directory\n"
ae541a2b
NS
73" e -- for non-realtime files, observe the inode extent size value\n"
74" E -- children created in this directory inherit the extent size value\n"
ed832ad2 75" f -- do not include this file when defragmenting the filesystem\n"
2d5121ac 76" S -- enable filestreams allocator for this directory\n"
2ac030ae
NS
77"\n"
78" Options:\n"
45532840
NS
79" -R -- recursively descend (useful when current file is a directory)\n"
80" -D -- recursively descend, but only list attributes on directories\n"
2ac030ae
NS
81" -a -- show all flags which can be set alongside those which are set\n"
82" -v -- verbose mode; show long names of flags, not single characters\n"
83"\n"));
84}
85
86static void
87chattr_help(void)
88{
89 printf(_(
90"\n"
91" modifies the set of extended inode flags associated with the current file\n"
92"\n"
93" Examples:\n"
94" 'chattr +a' - sets the append-only flag\n"
95" 'chattr -a' - clears the append-only flag\n"
96"\n"
45532840
NS
97" -R -- recursively descend (useful when current file is a directory)\n"
98" -D -- recursively descend, only modifying attributes on directories\n"
2ac030ae
NS
99" +/-r -- set/clear the realtime flag\n"
100" +/-i -- set/clear the immutable flag\n"
101" +/-a -- set/clear the append-only flag\n"
102" +/-s -- set/clear the sync flag\n"
103" +/-A -- set/clear the no-atime flag\n"
104" +/-d -- set/clear the no-dump flag\n"
105" +/-t -- set/clear the realtime inheritance flag\n"
106" +/-P -- set/clear the project ID inheritance flag\n"
107" +/-n -- set/clear the no-symbolic-links flag\n"
ae541a2b
NS
108" +/-e -- set/clear the extent-size flag\n"
109" +/-E -- set/clear the extent-size inheritance flag\n"
ed832ad2 110" +/-f -- set/clear the no-defrag flag\n"
2d5121ac 111" +/-S -- set/clear the filestreams allocator flag\n"
2ac030ae
NS
112" Note1: user must have certain capabilities to modify immutable/append-only.\n"
113" Note2: immutable/append-only files cannot be deleted; removing these files\n"
114" requires the immutable/append-only flag to be cleared first.\n"
115" Note3: the realtime flag can only be set if the filesystem has a realtime\n"
116" section, and the (regular) file must be empty when the flag is set.\n"
117"\n"));
118}
119
120void
121printxattr(
122 uint flags,
123 int verbose,
124 int dofname,
125 const char *fname,
126 int dobraces,
127 int doeol)
128{
129 struct xflags *p;
130 int first = 1;
131
132 if (dobraces)
133 fputs("[", stdout);
134 for (p = xflags; p->flag; p++) {
135 if (flags & p->flag) {
136 if (verbose) {
137 if (first)
138 first = 0;
139 else
140 fputs(", ", stdout);
141 fputs(p->longname, stdout);
142 } else {
143 fputs(p->shortname, stdout);
144 }
145 } else if (!verbose) {
146 fputs("-", stdout);
147 }
148 }
149 if (dobraces)
150 fputs("]", stdout);
151 if (dofname)
152 printf(" %s ", fname);
153 if (doeol)
154 fputs("\n", stdout);
155}
156
45532840
NS
157static int
158lsattr_callback(
159 const char *path,
160 const struct stat *stat,
161 int status,
162 struct FTW *data)
163{
164 struct fsxattr fsx;
165 int fd;
166
167 if (recurse_dir && !S_ISDIR(stat->st_mode))
168 return 0;
169
170 if ((fd = open(path, O_RDONLY)) == -1)
171 fprintf(stderr, _("%s: cannot open %s: %s\n"),
172 progname, path, strerror(errno));
173 else if ((xfsctl(path, fd, XFS_IOC_FSGETXATTR, &fsx)) < 0)
174 fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
175 progname, path, strerror(errno));
176 else
177 printxattr(fsx.fsx_xflags, 0, 1, path, 0, 1);
178
179 if (fd != -1)
180 close(fd);
181 return 0;
182}
183
2ac030ae
NS
184static int
185lsattr_f(
186 int argc,
187 char **argv)
188{
189 struct fsxattr fsx;
190 char *name = file->name;
191 int c, aflag = 0, vflag = 0;
192
45532840
NS
193 recurse_all = recurse_dir = 0;
194 while ((c = getopt(argc, argv, "DRav")) != EOF) {
2ac030ae 195 switch (c) {
45532840
NS
196 case 'D':
197 recurse_all = 0;
198 recurse_dir = 1;
199 break;
200 case 'R':
201 recurse_all = 1;
202 recurse_dir = 0;
203 break;
2ac030ae
NS
204 case 'a':
205 aflag = 1;
206 vflag = 0;
207 break;
208 case 'v':
209 aflag = 0;
210 vflag = 1;
211 break;
212 default:
45532840 213 return command_usage(&lsattr_cmd);
2ac030ae
NS
214 }
215 }
216
45532840
NS
217 if (recurse_all || recurse_dir) {
218 nftw(name, lsattr_callback,
219 100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH);
220 } else if ((xfsctl(name, file->fd, XFS_IOC_FSGETXATTR, &fsx)) < 0) {
221 fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
222 progname, name, strerror(errno));
2ac030ae
NS
223 } else {
224 printxattr(fsx.fsx_xflags, vflag, !aflag, name, vflag, !aflag);
225 if (aflag) {
226 fputs("/", stdout);
227 printxattr(-1, 0, 1, name, 0, 1);
228 }
229 }
230 return 0;
231}
232
45532840
NS
233static int
234chattr_callback(
235 const char *path,
236 const struct stat *stat,
237 int status,
238 struct FTW *data)
239{
240 struct fsxattr attr;
241 int fd;
242
243 if (recurse_dir && !S_ISDIR(stat->st_mode))
244 return 0;
245
246 if ((fd = open(path, O_RDONLY)) == -1) {
247 fprintf(stderr, _("%s: cannot open %s: %s\n"),
248 progname, path, strerror(errno));
249 } else if (xfsctl(path, fd, XFS_IOC_FSGETXATTR, &attr) < 0) {
250 fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
251 progname, path, strerror(errno));
252 } else {
253 attr.fsx_xflags |= orflags;
254 attr.fsx_xflags &= ~andflags;
255 if (xfsctl(path, fd, XFS_IOC_FSSETXATTR, &attr) < 0)
256 fprintf(stderr, _("%s: cannot set flags on %s: %s\n"),
257 progname, path, strerror(errno));
258 }
259
260 if (fd != -1)
261 close(fd);
262 return 0;
263}
264
2ac030ae
NS
265static int
266chattr_f(
267 int argc,
268 char **argv)
269{
270 struct fsxattr attr;
271 struct xflags *p;
272 unsigned int i = 0;
273 char *c, *name = file->name;
274
45532840
NS
275 orflags = andflags = 0;
276 recurse_all = recurse_dir = 0;
2ac030ae 277 while (++i < argc) {
45532840
NS
278 if (argv[i][0] == '-' && argv[i][1] == 'R') {
279 recurse_all = 1;
280 } else if (argv[i][0] == '-' && argv[i][1] == 'D') {
281 recurse_dir = 1;
282 } else if (argv[i][0] == '+') {
2ac030ae
NS
283 for (c = &argv[i][1]; *c; c++) {
284 for (p = xflags; p->flag; p++) {
285 if (strncmp(p->shortname, c, 1) == 0) {
45532840 286 orflags |= p->flag;
2ac030ae
NS
287 break;
288 }
289 }
290 if (!p->flag) {
291 fprintf(stderr, _("%s: unknown flag\n"),
292 progname);
293 return 0;
294 }
295 }
296 } else if (argv[i][0] == '-') {
297 for (c = &argv[i][1]; *c; c++) {
298 for (p = xflags; p->flag; p++) {
299 if (strncmp(p->shortname, c, 1) == 0) {
45532840 300 andflags |= p->flag;
2ac030ae
NS
301 break;
302 }
303 }
304 if (!p->flag) {
305 fprintf(stderr, _("%s: unknown flag\n"),
306 progname);
307 return 0;
308 }
309 }
310 } else {
311 fprintf(stderr, _("%s: bad chattr command, not +/-X\n"),
312 progname);
313 return 0;
314 }
315 }
45532840
NS
316
317 if (recurse_all || recurse_dir) {
318 nftw(name, chattr_callback,
319 100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH);
320 } else if (xfsctl(name, file->fd, XFS_IOC_FSGETXATTR, &attr) < 0) {
321 fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
322 progname, name, strerror(errno));
323 } else {
324 attr.fsx_xflags |= orflags;
325 attr.fsx_xflags &= ~andflags;
326 if (xfsctl(name, file->fd, XFS_IOC_FSSETXATTR, &attr) < 0)
327 fprintf(stderr, _("%s: cannot set flags on %s: %s\n"),
328 progname, name, strerror(errno));
329 }
2ac030ae
NS
330 return 0;
331}
332
333void
334attr_init(void)
335{
ad765595 336 chattr_cmd.name = "chattr";
2ac030ae 337 chattr_cmd.cfunc = chattr_f;
45532840 338 chattr_cmd.args = _("[-R|-D] [+/-"CHATTR_XFLAG_LIST"]");
2ac030ae
NS
339 chattr_cmd.argmin = 1;
340 chattr_cmd.argmax = -1;
341 chattr_cmd.flags = CMD_NOMAP_OK;
342 chattr_cmd.oneline =
343 _("change extended inode flags on the currently open file");
344 chattr_cmd.help = chattr_help;
345
ad765595 346 lsattr_cmd.name = "lsattr";
2ac030ae 347 lsattr_cmd.cfunc = lsattr_f;
45532840 348 lsattr_cmd.args = _("[-R|-D|-a|-v]");
2ac030ae
NS
349 lsattr_cmd.argmin = 0;
350 lsattr_cmd.argmax = 1;
351 lsattr_cmd.flags = CMD_NOMAP_OK;
352 lsattr_cmd.oneline =
353 _("list extended inode flags set on the currently open file");
354 lsattr_cmd.help = lsattr_help;
355
356 add_command(&chattr_cmd);
357 add_command(&lsattr_cmd);
358}