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