Whamcloud - gitweb
debugfs: fix printing of inline data during symlink inode dump
[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                         printf("%s: Usage: %s <file> <attr> [-f infile | "
200                                "value]\n", argv[0], argv[0]);
201                         goto out2;
202                 }
203         }
204
205         if (optind != argc - 2 && optind != argc - 3) {
206                 printf("%s: Usage: %s <file> <attr> [-f infile | value>]\n",
207                        argv[0], argv[0]);
208                 goto out2;
209         }
210
211         if (check_fs_open(argv[0]))
212                 goto out2;
213         if (check_fs_read_write(argv[0]))
214                 goto out2;
215         if (check_fs_bitmaps(argv[0]))
216                 goto out2;
217
218         ino = string_to_inode(argv[optind]);
219         if (!ino)
220                 goto out2;
221
222         err = ext2fs_xattrs_open(current_fs, ino, &h);
223         if (err)
224                 goto out2;
225
226         err = ext2fs_xattrs_read(h);
227         if (err)
228                 goto out;
229
230         if (fp) {
231                 err = ext2fs_get_mem(current_fs->blocksize, &buf);
232                 if (err)
233                         goto out;
234                 buflen = fread(buf, 1, current_fs->blocksize, fp);
235         } else {
236                 buf = argv[optind + 2];
237                 buflen = strlen(argv[optind + 2]);
238         }
239
240         err = ext2fs_xattr_set(h, argv[optind + 1], buf, buflen);
241         if (err)
242                 goto out;
243
244         err = ext2fs_xattrs_write(h);
245         if (err)
246                 goto out;
247
248 out:
249         ext2fs_xattrs_close(&h);
250         if (err)
251                 com_err(argv[0], err, "while setting extended attribute");
252 out2:
253         if (fp) {
254                 fclose(fp);
255                 ext2fs_free_mem(&buf);
256         }
257 }
258
259 void do_rm_xattr(int argc, char **argv)
260 {
261         ext2_ino_t ino;
262         struct ext2_xattr_handle *h;
263         int i;
264         errcode_t err;
265
266         if (argc < 3) {
267                 printf("%s: Usage: %s <file> <attrs>...\n", argv[0], argv[0]);
268                 return;
269         }
270
271         if (check_fs_open(argv[0]))
272                 return;
273         if (check_fs_read_write(argv[0]))
274                 return;
275         if (check_fs_bitmaps(argv[0]))
276                 return;
277
278         ino = string_to_inode(argv[1]);
279         if (!ino)
280                 return;
281
282         err = ext2fs_xattrs_open(current_fs, ino, &h);
283         if (err)
284                 return;
285
286         err = ext2fs_xattrs_read(h);
287         if (err)
288                 goto out;
289
290         for (i = 2; i < argc; i++) {
291                 size_t buflen;
292                 char *buf;
293
294                 err = ext2fs_xattr_remove(h, argv[i]);
295                 if (err)
296                         goto out;
297         }
298
299         err = ext2fs_xattrs_write(h);
300         if (err)
301                 goto out;
302 out:
303         ext2fs_xattrs_close(&h);
304         if (err)
305                 com_err(argv[0], err, "while removing extended attribute");
306 }