]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - io/attr.c
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
12 static cmdinfo_t chattr_cmd
;
13 static cmdinfo_t lsattr_cmd
;
14 static unsigned int orflags
;
15 static unsigned int andflags
;
16 unsigned int recurse_all
;
17 unsigned int recurse_dir
;
19 static struct xflags
{
24 { FS_XFLAG_REALTIME
, "r", "realtime" },
25 { FS_XFLAG_PREALLOC
, "p", "prealloc" },
26 { FS_XFLAG_IMMUTABLE
, "i", "immutable" },
27 { FS_XFLAG_APPEND
, "a", "append-only" },
28 { FS_XFLAG_SYNC
, "s", "sync" },
29 { FS_XFLAG_NOATIME
, "A", "no-atime" },
30 { FS_XFLAG_NODUMP
, "d", "no-dump" },
31 { FS_XFLAG_RTINHERIT
, "t", "rt-inherit" },
32 { FS_XFLAG_PROJINHERIT
, "P", "proj-inherit" },
33 { FS_XFLAG_NOSYMLINKS
, "n", "nosymlinks" },
34 { FS_XFLAG_EXTSIZE
, "e", "extsize" },
35 { FS_XFLAG_EXTSZINHERIT
, "E", "extsz-inherit" },
36 { FS_XFLAG_NODEFRAG
, "f", "no-defrag" },
37 { FS_XFLAG_FILESTREAM
, "S", "filestream" },
38 { FS_XFLAG_DAX
, "x", "dax" },
39 { FS_XFLAG_COWEXTSIZE
, "C", "cowextsize" },
42 #define CHATTR_XFLAG_LIST "r"/*p*/"iasAdtPneEfSxC"
49 " displays the set of extended inode flags associated with the current file\n"
51 " Each individual flag is displayed as a single character, in this order:\n"
52 " r -- file data is stored in the realtime section\n"
53 " p -- file has preallocated extents (cannot be changed using chattr)\n"
54 " i -- immutable, file cannot be modified\n"
55 " a -- append-only, file can only be appended to\n"
56 " s -- all updates are synchronous\n"
57 " A -- the access time is not updated for this inode\n"
58 " d -- do not include this file in a dump of the filesystem\n"
59 " t -- child created in this directory has realtime bit set by default\n"
60 " P -- child created in this directory has parents project ID by default\n"
61 " n -- symbolic links cannot be created in this directory\n"
62 " e -- for non-realtime files, observe the inode extent size value\n"
63 " E -- children created in this directory inherit the extent size value\n"
64 " f -- do not include this file when defragmenting the filesystem\n"
65 " S -- enable filestreams allocator for this directory\n"
66 " x -- Use direct access (DAX) for data in this file\n"
67 " C -- for files with shared blocks, observe the inode CoW extent size value\n"
70 " -R -- recursively descend (useful when current file is a directory)\n"
71 " -D -- recursively descend, but only list attributes on directories\n"
72 " -a -- show all flags which can be set alongside those which are set\n"
73 " -v -- verbose mode; show long names of flags, not single characters\n"
82 " modifies the set of extended inode flags associated with the current file\n"
85 " 'chattr +a' - sets the append-only flag\n"
86 " 'chattr -a' - clears the append-only flag\n"
88 " -R -- recursively descend (useful when current file is a directory)\n"
89 " -D -- recursively descend, only modifying attributes on directories\n"
90 " +/-r -- set/clear the realtime flag\n"
91 " +/-i -- set/clear the immutable flag\n"
92 " +/-a -- set/clear the append-only flag\n"
93 " +/-s -- set/clear the sync flag\n"
94 " +/-A -- set/clear the no-atime flag\n"
95 " +/-d -- set/clear the no-dump flag\n"
96 " +/-t -- set/clear the realtime inheritance flag\n"
97 " +/-P -- set/clear the project ID inheritance flag\n"
98 " +/-n -- set/clear the no-symbolic-links flag\n"
99 " +/-e -- set/clear the extent-size flag\n"
100 " +/-E -- set/clear the extent-size inheritance flag\n"
101 " +/-f -- set/clear the no-defrag flag\n"
102 " +/-S -- set/clear the filestreams allocator flag\n"
103 " +/-x -- set/clear the direct access (DAX) flag\n"
104 " +/-C -- set/clear the CoW extent-size flag\n"
105 " Note1: user must have certain capabilities to modify immutable/append-only.\n"
106 " Note2: immutable/append-only files cannot be deleted; removing these files\n"
107 " requires the immutable/append-only flag to be cleared first.\n"
108 " Note3: the realtime flag can only be set if the filesystem has a realtime\n"
109 " section, and the (regular) file must be empty when the flag is set.\n"
127 for (p
= xflags
; p
->flag
; p
++) {
128 if (flags
& p
->flag
) {
134 fputs(p
->longname
, stdout
);
136 fputs(p
->shortname
, stdout
);
138 } else if (!verbose
) {
145 printf(" %s ", fname
);
153 const struct stat
*stat
,
160 if (recurse_dir
&& !S_ISDIR(stat
->st_mode
))
163 if ((fd
= open(path
, O_RDONLY
)) == -1)
164 fprintf(stderr
, _("%s: cannot open %s: %s\n"),
165 progname
, path
, strerror(errno
));
166 else if ((xfsctl(path
, fd
, FS_IOC_FSGETXATTR
, &fsx
)) < 0)
167 fprintf(stderr
, _("%s: cannot get flags on %s: %s\n"),
168 progname
, path
, strerror(errno
));
170 printxattr(fsx
.fsx_xflags
, 0, 1, path
, 0, 1);
183 char *name
= file
->name
;
184 int c
, aflag
= 0, vflag
= 0;
186 recurse_all
= recurse_dir
= 0;
187 while ((c
= getopt(argc
, argv
, "DRav")) != EOF
) {
206 return command_usage(&lsattr_cmd
);
210 if (recurse_all
|| recurse_dir
) {
211 nftw(name
, lsattr_callback
,
212 100, FTW_PHYS
| FTW_MOUNT
| FTW_DEPTH
);
213 } else if ((xfsctl(name
, file
->fd
, FS_IOC_FSGETXATTR
, &fsx
)) < 0) {
214 fprintf(stderr
, _("%s: cannot get flags on %s: %s\n"),
215 progname
, name
, strerror(errno
));
217 printxattr(fsx
.fsx_xflags
, vflag
, !aflag
, name
, vflag
, !aflag
);
220 printxattr(-1, 0, 1, name
, 0, 1);
229 const struct stat
*stat
,
236 if (recurse_dir
&& !S_ISDIR(stat
->st_mode
))
239 if ((fd
= open(path
, O_RDONLY
)) == -1) {
240 fprintf(stderr
, _("%s: cannot open %s: %s\n"),
241 progname
, path
, strerror(errno
));
242 } else if (xfsctl(path
, fd
, FS_IOC_FSGETXATTR
, &attr
) < 0) {
243 fprintf(stderr
, _("%s: cannot get flags on %s: %s\n"),
244 progname
, path
, strerror(errno
));
246 attr
.fsx_xflags
|= orflags
;
247 attr
.fsx_xflags
&= ~andflags
;
248 if (xfsctl(path
, fd
, FS_IOC_FSSETXATTR
, &attr
) < 0)
249 fprintf(stderr
, _("%s: cannot set flags on %s: %s\n"),
250 progname
, path
, strerror(errno
));
266 char *c
, *name
= file
->name
;
268 orflags
= andflags
= 0;
269 recurse_all
= recurse_dir
= 0;
271 if (argv
[i
][0] == '-' && argv
[i
][1] == 'R') {
273 } else if (argv
[i
][0] == '-' && argv
[i
][1] == 'D') {
275 } else if (argv
[i
][0] == '+') {
276 for (c
= &argv
[i
][1]; *c
; c
++) {
277 for (p
= xflags
; p
->flag
; p
++) {
278 if (strncmp(p
->shortname
, c
, 1) == 0) {
284 fprintf(stderr
, _("%s: unknown flag\n"),
289 } else if (argv
[i
][0] == '-') {
290 for (c
= &argv
[i
][1]; *c
; c
++) {
291 for (p
= xflags
; p
->flag
; p
++) {
292 if (strncmp(p
->shortname
, c
, 1) == 0) {
298 fprintf(stderr
, _("%s: unknown flag\n"),
304 fprintf(stderr
, _("%s: bad chattr command, not +/-X\n"),
310 if (recurse_all
|| recurse_dir
) {
311 nftw(name
, chattr_callback
,
312 100, FTW_PHYS
| FTW_MOUNT
| FTW_DEPTH
);
313 } else if (xfsctl(name
, file
->fd
, FS_IOC_FSGETXATTR
, &attr
) < 0) {
314 fprintf(stderr
, _("%s: cannot get flags on %s: %s\n"),
315 progname
, name
, strerror(errno
));
317 attr
.fsx_xflags
|= orflags
;
318 attr
.fsx_xflags
&= ~andflags
;
319 if (xfsctl(name
, file
->fd
, FS_IOC_FSSETXATTR
, &attr
) < 0)
320 fprintf(stderr
, _("%s: cannot set flags on %s: %s\n"),
321 progname
, name
, strerror(errno
));
329 chattr_cmd
.name
= "chattr";
330 chattr_cmd
.cfunc
= chattr_f
;
331 chattr_cmd
.args
= _("[-R|-D] [+/-"CHATTR_XFLAG_LIST
"]");
332 chattr_cmd
.argmin
= 1;
333 chattr_cmd
.argmax
= -1;
334 chattr_cmd
.flags
= CMD_NOMAP_OK
| CMD_FOREIGN_OK
;
336 _("change extended inode flags on the currently open file");
337 chattr_cmd
.help
= chattr_help
;
339 lsattr_cmd
.name
= "lsattr";
340 lsattr_cmd
.cfunc
= lsattr_f
;
341 lsattr_cmd
.args
= _("[-R|-D|-a|-v]");
342 lsattr_cmd
.argmin
= 0;
343 lsattr_cmd
.argmax
= 1;
344 lsattr_cmd
.flags
= CMD_NOMAP_OK
| CMD_FOREIGN_OK
;
346 _("list extended inode flags set on the currently open file");
347 lsattr_cmd
.help
= lsattr_help
;
349 add_command(&chattr_cmd
);
350 add_command(&lsattr_cmd
);