]>
Commit | Line | Data |
---|---|---|
227239b1 DW |
1 | /* |
2 | * xattrs.c --- Modify extended attributes via debugfs. | |
3 | * | |
4 | * Copyright (C) 2014 Oracle. This file may be redistributed | |
5 | * under the terms of the GNU Public License. | |
6 | */ | |
7 | ||
8 | #include "config.h" | |
9 | #include <stdio.h> | |
10 | #ifdef HAVE_GETOPT_H | |
11 | #include <getopt.h> | |
12 | #else | |
13 | extern int optind; | |
14 | extern char *optarg; | |
15 | #endif | |
16 | #include <ctype.h> | |
997e213b | 17 | #include "support/cstring.h" |
227239b1 DW |
18 | |
19 | #include "debugfs.h" | |
20 | ||
997e213b TT |
21 | #define PRINT_XATTR_HEX 0x01 |
22 | #define PRINT_XATTR_RAW 0x02 | |
23 | #define PRINT_XATTR_C 0x04 | |
24 | #define PRINT_XATTR_STATFMT 0x08 | |
25 | #define PRINT_XATTR_NOQUOTES 0x10 | |
26 | ||
227239b1 | 27 | /* Dump extended attributes */ |
997e213b | 28 | static void print_xattr_hex(FILE *f, const char *str, int len) |
227239b1 | 29 | { |
227239b1 DW |
30 | int i; |
31 | ||
227239b1 | 32 | for (i = 0; i < len; i++) |
997e213b TT |
33 | fprintf(f, "%02x ", (unsigned char)str[i]); |
34 | } | |
227239b1 | 35 | |
997e213b TT |
36 | /* Dump extended attributes */ |
37 | static void print_xattr_string(FILE *f, const char *str, int len, int flags) | |
38 | { | |
39 | int printable = 0; | |
40 | int i; | |
227239b1 | 41 | |
997e213b TT |
42 | if (flags & PRINT_XATTR_RAW) { |
43 | fwrite(str, len, 1, f); | |
44 | return; | |
45 | } | |
46 | ||
47 | if ((flags & PRINT_XATTR_C) == 0) { | |
48 | /* check: is string "printable enough?" */ | |
49 | for (i = 0; i < len; i++) | |
50 | if (isprint(str[i])) | |
51 | printable++; | |
52 | ||
53 | if (printable <= len*7/8) | |
54 | flags |= PRINT_XATTR_HEX; | |
55 | } | |
56 | ||
57 | if (flags & PRINT_XATTR_HEX) { | |
58 | print_xattr_hex(f, str, len); | |
59 | } else { | |
60 | if ((flags & PRINT_XATTR_NOQUOTES) == 0) | |
61 | fputc('\"', f); | |
62 | print_c_string(f, str, len); | |
63 | if ((flags & PRINT_XATTR_NOQUOTES) == 0) | |
64 | fputc('\"', f); | |
65 | } | |
66 | } | |
67 | ||
68 | static void print_xattr(FILE *f, char *name, char *value, size_t value_len, | |
69 | int print_flags) | |
70 | { | |
71 | print_xattr_string(f, name, strlen(name), PRINT_XATTR_NOQUOTES); | |
72 | fprintf(f, " (%zu)", value_len); | |
73 | if ((print_flags & PRINT_XATTR_STATFMT) && | |
74 | (strcmp(name, "system.data") == 0)) | |
75 | value_len = 0; | |
76 | if (value_len != 0 && | |
77 | (!(print_flags & PRINT_XATTR_STATFMT) || (value_len < 40))) { | |
78 | fprintf(f, " = "); | |
79 | print_xattr_string(f, value, value_len, print_flags); | |
80 | } | |
81 | fputc('\n', f); | |
227239b1 DW |
82 | } |
83 | ||
84 | static int dump_attr(char *name, char *value, size_t value_len, void *data) | |
85 | { | |
86 | FILE *out = data; | |
87 | ||
88 | fprintf(out, " "); | |
997e213b | 89 | print_xattr(out, name, value, value_len, PRINT_XATTR_STATFMT); |
227239b1 DW |
90 | return 0; |
91 | } | |
92 | ||
93 | void dump_inode_attributes(FILE *out, ext2_ino_t ino) | |
94 | { | |
95 | struct ext2_xattr_handle *h; | |
96 | size_t sz; | |
97 | errcode_t err; | |
98 | ||
99 | err = ext2fs_xattrs_open(current_fs, ino, &h); | |
100 | if (err) | |
101 | return; | |
102 | ||
103 | err = ext2fs_xattrs_read(h); | |
104 | if (err) | |
105 | goto out; | |
106 | ||
107 | err = ext2fs_xattrs_count(h, &sz); | |
108 | if (err || sz == 0) | |
109 | goto out; | |
110 | ||
111 | fprintf(out, "Extended attributes:\n"); | |
112 | err = ext2fs_xattrs_iterate(h, dump_attr, out); | |
113 | if (err) | |
114 | goto out; | |
115 | ||
116 | out: | |
117 | err = ext2fs_xattrs_close(&h); | |
118 | } | |
119 | ||
120 | void do_list_xattr(int argc, char **argv) | |
121 | { | |
122 | ext2_ino_t ino; | |
123 | ||
124 | if (argc != 2) { | |
125 | printf("%s: Usage: %s <file>\n", argv[0], | |
126 | argv[0]); | |
127 | return; | |
128 | } | |
129 | ||
130 | if (check_fs_open(argv[0])) | |
131 | return; | |
132 | ||
133 | ino = string_to_inode(argv[1]); | |
134 | if (!ino) | |
135 | return; | |
136 | ||
137 | dump_inode_attributes(stdout, ino); | |
138 | } | |
139 | ||
140 | void do_get_xattr(int argc, char **argv) | |
141 | { | |
142 | ext2_ino_t ino; | |
143 | struct ext2_xattr_handle *h; | |
144 | FILE *fp = NULL; | |
145 | char *buf = NULL; | |
146 | size_t buflen; | |
147 | int i; | |
997e213b | 148 | int print_flags = 0; |
0ee1eaf7 | 149 | int handle_flags = 0; |
227239b1 DW |
150 | errcode_t err; |
151 | ||
152 | reset_getopt(); | |
0ee1eaf7 | 153 | while ((i = getopt(argc, argv, "Cf:rxV")) != -1) { |
227239b1 DW |
154 | switch (i) { |
155 | case 'f': | |
ec3a42b1 DW |
156 | if (fp) |
157 | fclose(fp); | |
227239b1 DW |
158 | fp = fopen(optarg, "w"); |
159 | if (fp == NULL) { | |
160 | perror(optarg); | |
161 | return; | |
162 | } | |
163 | break; | |
0ee1eaf7 TT |
164 | case 'r': |
165 | handle_flags |= XATTR_HANDLE_FLAG_RAW; | |
166 | break; | |
997e213b TT |
167 | case 'x': |
168 | print_flags |= PRINT_XATTR_HEX; | |
169 | break; | |
170 | case 'V': | |
171 | print_flags |= PRINT_XATTR_RAW; | |
172 | break; | |
173 | case 'C': | |
174 | print_flags |= PRINT_XATTR_C; | |
175 | break; | |
227239b1 | 176 | default: |
997e213b | 177 | goto usage; |
227239b1 DW |
178 | } |
179 | } | |
180 | ||
181 | if (optind != argc - 2) { | |
997e213b | 182 | usage: |
0ee1eaf7 | 183 | printf("%s: Usage: %s [-f outfile]|[-xVC] [-r] <file> <attr>\n", |
997e213b | 184 | argv[0], argv[0]); |
0ee1eaf7 | 185 | |
1bad6f46 | 186 | goto out2; |
227239b1 DW |
187 | } |
188 | ||
189 | if (check_fs_open(argv[0])) | |
1bad6f46 | 190 | goto out2; |
227239b1 DW |
191 | |
192 | ino = string_to_inode(argv[optind]); | |
193 | if (!ino) | |
1bad6f46 | 194 | goto out2; |
227239b1 DW |
195 | |
196 | err = ext2fs_xattrs_open(current_fs, ino, &h); | |
197 | if (err) | |
1bad6f46 | 198 | goto out2; |
227239b1 | 199 | |
0ee1eaf7 TT |
200 | err = ext2fs_xattrs_flags(h, &handle_flags, NULL); |
201 | if (err) | |
202 | goto out; | |
203 | ||
227239b1 DW |
204 | err = ext2fs_xattrs_read(h); |
205 | if (err) | |
206 | goto out; | |
207 | ||
208 | err = ext2fs_xattr_get(h, argv[optind + 1], (void **)&buf, &buflen); | |
209 | if (err) | |
210 | goto out; | |
211 | ||
212 | if (fp) { | |
213 | fwrite(buf, buflen, 1, fp); | |
227239b1 | 214 | } else { |
997e213b TT |
215 | if (print_flags & PRINT_XATTR_RAW) { |
216 | if (print_flags & PRINT_XATTR_HEX|PRINT_XATTR_C) | |
217 | print_flags &= ~PRINT_XATTR_RAW; | |
218 | print_xattr_string(stdout, buf, buflen, print_flags); | |
219 | } else { | |
220 | print_xattr(stdout, argv[optind + 1], | |
221 | buf, buflen, print_flags); | |
222 | } | |
227239b1 DW |
223 | printf("\n"); |
224 | } | |
225 | ||
1bad6f46 | 226 | ext2fs_free_mem(&buf); |
227239b1 DW |
227 | out: |
228 | ext2fs_xattrs_close(&h); | |
229 | if (err) | |
230 | com_err(argv[0], err, "while getting extended attribute"); | |
1bad6f46 DW |
231 | out2: |
232 | if (fp) | |
233 | fclose(fp); | |
227239b1 DW |
234 | } |
235 | ||
236 | void do_set_xattr(int argc, char **argv) | |
237 | { | |
238 | ext2_ino_t ino; | |
239 | struct ext2_xattr_handle *h; | |
240 | FILE *fp = NULL; | |
241 | char *buf = NULL; | |
242 | size_t buflen; | |
0ee1eaf7 TT |
243 | int print_flags = 0; |
244 | int handle_flags = 0; | |
227239b1 DW |
245 | int i; |
246 | errcode_t err; | |
247 | ||
248 | reset_getopt(); | |
0ee1eaf7 | 249 | while ((i = getopt(argc, argv, "f:r")) != -1) { |
227239b1 DW |
250 | switch (i) { |
251 | case 'f': | |
ec3a42b1 DW |
252 | if (fp) |
253 | fclose(fp); | |
227239b1 DW |
254 | fp = fopen(optarg, "r"); |
255 | if (fp == NULL) { | |
256 | perror(optarg); | |
257 | return; | |
258 | } | |
259 | break; | |
0ee1eaf7 TT |
260 | case 'r': |
261 | handle_flags |= XATTR_HANDLE_FLAG_RAW; | |
262 | break; | |
227239b1 | 263 | default: |
be05f60e | 264 | goto print_usage; |
227239b1 DW |
265 | } |
266 | } | |
267 | ||
d0bc2c88 | 268 | if (!(fp && optind == argc - 2) && !(!fp && optind == argc - 3)) { |
be05f60e TT |
269 | print_usage: |
270 | printf("Usage:\t%s <file> <attr> <value>\n", argv[0]); | |
0ee1eaf7 | 271 | printf("\t%s -f <value_file> [-r] <file> <attr>\n", argv[0]); |
1bad6f46 | 272 | goto out2; |
227239b1 DW |
273 | } |
274 | ||
275 | if (check_fs_open(argv[0])) | |
1bad6f46 | 276 | goto out2; |
227239b1 | 277 | if (check_fs_read_write(argv[0])) |
1bad6f46 | 278 | goto out2; |
227239b1 | 279 | if (check_fs_bitmaps(argv[0])) |
1bad6f46 | 280 | goto out2; |
227239b1 DW |
281 | |
282 | ino = string_to_inode(argv[optind]); | |
283 | if (!ino) | |
1bad6f46 | 284 | goto out2; |
227239b1 DW |
285 | |
286 | err = ext2fs_xattrs_open(current_fs, ino, &h); | |
287 | if (err) | |
1bad6f46 | 288 | goto out2; |
227239b1 | 289 | |
0ee1eaf7 TT |
290 | err = ext2fs_xattrs_flags(h, &handle_flags, NULL); |
291 | if (err) | |
292 | goto out; | |
293 | ||
227239b1 DW |
294 | err = ext2fs_xattrs_read(h); |
295 | if (err) | |
296 | goto out; | |
297 | ||
298 | if (fp) { | |
299 | err = ext2fs_get_mem(current_fs->blocksize, &buf); | |
300 | if (err) | |
301 | goto out; | |
302 | buflen = fread(buf, 1, current_fs->blocksize, fp); | |
303 | } else { | |
304 | buf = argv[optind + 2]; | |
997e213b | 305 | buflen = parse_c_string(buf); |
227239b1 DW |
306 | } |
307 | ||
308 | err = ext2fs_xattr_set(h, argv[optind + 1], buf, buflen); | |
309 | if (err) | |
310 | goto out; | |
311 | ||
312 | err = ext2fs_xattrs_write(h); | |
313 | if (err) | |
314 | goto out; | |
315 | ||
316 | out: | |
1bad6f46 DW |
317 | ext2fs_xattrs_close(&h); |
318 | if (err) | |
319 | com_err(argv[0], err, "while setting extended attribute"); | |
320 | out2: | |
227239b1 DW |
321 | if (fp) { |
322 | fclose(fp); | |
323 | ext2fs_free_mem(&buf); | |
324 | } | |
227239b1 DW |
325 | } |
326 | ||
327 | void do_rm_xattr(int argc, char **argv) | |
328 | { | |
329 | ext2_ino_t ino; | |
330 | struct ext2_xattr_handle *h; | |
331 | int i; | |
332 | errcode_t err; | |
333 | ||
334 | if (argc < 3) { | |
335 | printf("%s: Usage: %s <file> <attrs>...\n", argv[0], argv[0]); | |
336 | return; | |
337 | } | |
338 | ||
339 | if (check_fs_open(argv[0])) | |
340 | return; | |
341 | if (check_fs_read_write(argv[0])) | |
342 | return; | |
343 | if (check_fs_bitmaps(argv[0])) | |
344 | return; | |
345 | ||
346 | ino = string_to_inode(argv[1]); | |
347 | if (!ino) | |
348 | return; | |
349 | ||
350 | err = ext2fs_xattrs_open(current_fs, ino, &h); | |
351 | if (err) | |
352 | return; | |
353 | ||
354 | err = ext2fs_xattrs_read(h); | |
355 | if (err) | |
356 | goto out; | |
357 | ||
358 | for (i = 2; i < argc; i++) { | |
227239b1 DW |
359 | err = ext2fs_xattr_remove(h, argv[i]); |
360 | if (err) | |
361 | goto out; | |
362 | } | |
363 | ||
364 | err = ext2fs_xattrs_write(h); | |
365 | if (err) | |
366 | goto out; | |
367 | out: | |
368 | ext2fs_xattrs_close(&h); | |
369 | if (err) | |
370 | com_err(argv[0], err, "while removing extended attribute"); | |
371 | } |