Whamcloud - gitweb
tests,debugfs: ea_set's "-f <value_file" needs to be before the other args
[tools/e2fsprogs.git] / debugfs / xattrs.c
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 */
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
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
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
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
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
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
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 }