Home | History | Annotate | Download | only in debugfs
      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 }
    303