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>
17
18 #include "debugfs.h"
19
20 /* Dump extended attributes */
dump_xattr_string(FILE * out,const char * str,int len)21 static void dump_xattr_string(FILE *out, const char *str, int len)
22 {
23 int printable = 0;
24 int i;
25
26 /* check: is string "printable enough?" */
27 for (i = 0; i < len; i++)
28 if (isprint(str[i]))
29 printable++;
30
31 if (printable <= len*7/8)
32 printable = 0;
33
34 for (i = 0; i < len; i++)
35 if (printable)
36 fprintf(out, isprint(str[i]) ? "%c" : "\\%03o",
37 (unsigned char)str[i]);
38 else
39 fprintf(out, "%02x ", (unsigned char)str[i]);
40 }
41
dump_attr(char * name,char * value,size_t value_len,void * data)42 static int dump_attr(char *name, char *value, size_t value_len, void *data)
43 {
44 FILE *out = data;
45
46 fprintf(out, " ");
47 dump_xattr_string(out, name, strlen(name));
48 if (strcmp(name, "system.data") != 0) {
49 fprintf(out, " = \"");
50 dump_xattr_string(out, value, value_len);
51 fprintf(out, "\"");
52 }
53 fprintf(out, " (%zu)\n", value_len);
54
55 return 0;
56 }
57
dump_inode_attributes(FILE * out,ext2_ino_t ino)58 void dump_inode_attributes(FILE *out, ext2_ino_t ino)
59 {
60 struct ext2_xattr_handle *h;
61 size_t sz;
62 errcode_t err;
63
64 err = ext2fs_xattrs_open(current_fs, ino, &h);
65 if (err)
66 return;
67
68 err = ext2fs_xattrs_read(h);
69 if (err)
70 goto out;
71
72 err = ext2fs_xattrs_count(h, &sz);
73 if (err || sz == 0)
74 goto out;
75
76 fprintf(out, "Extended attributes:\n");
77 err = ext2fs_xattrs_iterate(h, dump_attr, out);
78 if (err)
79 goto out;
80
81 out:
82 err = ext2fs_xattrs_close(&h);
83 }
84
do_list_xattr(int argc,char ** argv)85 void do_list_xattr(int argc, char **argv)
86 {
87 ext2_ino_t ino;
88
89 if (argc != 2) {
90 printf("%s: Usage: %s <file>\n", argv[0],
91 argv[0]);
92 return;
93 }
94
95 if (check_fs_open(argv[0]))
96 return;
97
98 ino = string_to_inode(argv[1]);
99 if (!ino)
100 return;
101
102 dump_inode_attributes(stdout, ino);
103 }
104
do_get_xattr(int argc,char ** argv)105 void do_get_xattr(int argc, char **argv)
106 {
107 ext2_ino_t ino;
108 struct ext2_xattr_handle *h;
109 FILE *fp = NULL;
110 char *buf = NULL;
111 size_t buflen;
112 int i;
113 errcode_t err;
114
115 reset_getopt();
116 while ((i = getopt(argc, argv, "f:")) != -1) {
117 switch (i) {
118 case 'f':
119 if (fp)
120 fclose(fp);
121 fp = fopen(optarg, "w");
122 if (fp == NULL) {
123 perror(optarg);
124 return;
125 }
126 break;
127 default:
128 printf("%s: Usage: %s <file> <attr> [-f outfile]\n",
129 argv[0], argv[0]);
130 goto out2;
131 }
132 }
133
134 if (optind != argc - 2) {
135 printf("%s: Usage: %s <file> <attr> [-f outfile]\n", argv[0],
136 argv[0]);
137 goto out2;
138 }
139
140 if (check_fs_open(argv[0]))
141 goto out2;
142
143 ino = string_to_inode(argv[optind]);
144 if (!ino)
145 goto out2;
146
147 err = ext2fs_xattrs_open(current_fs, ino, &h);
148 if (err)
149 goto out2;
150
151 err = ext2fs_xattrs_read(h);
152 if (err)
153 goto out;
154
155 err = ext2fs_xattr_get(h, argv[optind + 1], (void **)&buf, &buflen);
156 if (err)
157 goto out;
158
159 if (fp) {
160 fwrite(buf, buflen, 1, fp);
161 } else {
162 dump_xattr_string(stdout, buf, buflen);
163 printf("\n");
164 }
165
166 ext2fs_free_mem(&buf);
167 out:
168 ext2fs_xattrs_close(&h);
169 if (err)
170 com_err(argv[0], err, "while getting extended attribute");
171 out2:
172 if (fp)
173 fclose(fp);
174 }
175
do_set_xattr(int argc,char ** argv)176 void do_set_xattr(int argc, char **argv)
177 {
178 ext2_ino_t ino;
179 struct ext2_xattr_handle *h;
180 FILE *fp = NULL;
181 char *buf = NULL;
182 size_t buflen;
183 int i;
184 errcode_t err;
185
186 reset_getopt();
187 while ((i = getopt(argc, argv, "f:")) != -1) {
188 switch (i) {
189 case 'f':
190 if (fp)
191 fclose(fp);
192 fp = fopen(optarg, "r");
193 if (fp == NULL) {
194 perror(optarg);
195 return;
196 }
197 break;
198 default:
199 goto print_usage;
200 }
201 }
202
203 if (!(fp && optind == argc - 2) && !(!fp && optind == argc - 3)) {
204 print_usage:
205 printf("Usage:\t%s <file> <attr> <value>\n", argv[0]);
206 printf("\t%s -f <value_file> <file> <attr>\n", argv[0]);
207 goto out2;
208 }
209
210 if (check_fs_open(argv[0]))
211 goto out2;
212 if (check_fs_read_write(argv[0]))
213 goto out2;
214 if (check_fs_bitmaps(argv[0]))
215 goto out2;
216
217 ino = string_to_inode(argv[optind]);
218 if (!ino)
219 goto out2;
220
221 err = ext2fs_xattrs_open(current_fs, ino, &h);
222 if (err)
223 goto out2;
224
225 err = ext2fs_xattrs_read(h);
226 if (err)
227 goto out;
228
229 if (fp) {
230 err = ext2fs_get_mem(current_fs->blocksize, &buf);
231 if (err)
232 goto out;
233 buflen = fread(buf, 1, current_fs->blocksize, fp);
234 } else {
235 buf = argv[optind + 2];
236 buflen = strlen(argv[optind + 2]);
237 }
238
239 err = ext2fs_xattr_set(h, argv[optind + 1], buf, buflen);
240 if (err)
241 goto out;
242
243 err = ext2fs_xattrs_write(h);
244 if (err)
245 goto out;
246
247 out:
248 ext2fs_xattrs_close(&h);
249 if (err)
250 com_err(argv[0], err, "while setting extended attribute");
251 out2:
252 if (fp) {
253 fclose(fp);
254 ext2fs_free_mem(&buf);
255 }
256 }
257
do_rm_xattr(int argc,char ** argv)258 void do_rm_xattr(int argc, char **argv)
259 {
260 ext2_ino_t ino;
261 struct ext2_xattr_handle *h;
262 int i;
263 errcode_t err;
264
265 if (argc < 3) {
266 printf("%s: Usage: %s <file> <attrs>...\n", argv[0], argv[0]);
267 return;
268 }
269
270 if (check_fs_open(argv[0]))
271 return;
272 if (check_fs_read_write(argv[0]))
273 return;
274 if (check_fs_bitmaps(argv[0]))
275 return;
276
277 ino = string_to_inode(argv[1]);
278 if (!ino)
279 return;
280
281 err = ext2fs_xattrs_open(current_fs, ino, &h);
282 if (err)
283 return;
284
285 err = ext2fs_xattrs_read(h);
286 if (err)
287 goto out;
288
289 for (i = 2; i < argc; i++) {
290 err = ext2fs_xattr_remove(h, argv[i]);
291 if (err)
292 goto out;
293 }
294
295 err = ext2fs_xattrs_write(h);
296 if (err)
297 goto out;
298 out:
299 ext2fs_xattrs_close(&h);
300 if (err)
301 com_err(argv[0], err, "while removing extended attribute");
302 }
303