diff options
| author | Darrick J. Wong <darrick.wong@oracle.com> | 2014-03-11 23:49:58 -0400 |
|---|---|---|
| committer | Theodore Ts'o <tytso@mit.edu> | 2014-03-11 23:50:08 -0400 |
| commit | 227239b10b93bb51b6d8fc4023af77a94cdd7775 (patch) | |
| tree | d40b7beef4a4f0ff6ff407c3448524e1e9821ee8 /debugfs/xattrs.c | |
| parent | 2ddcee17711b37fe9fca7d2350f275789a014f86 (diff) | |
| download | platform_external_e2fsprogs-227239b10b93bb51b6d8fc4023af77a94cdd7775.tar.gz platform_external_e2fsprogs-227239b10b93bb51b6d8fc4023af77a94cdd7775.tar.bz2 platform_external_e2fsprogs-227239b10b93bb51b6d8fc4023af77a94cdd7775.zip | |
debugfs: create commands to edit extended attributes
Enhance debugfs to be able to display and modify extended attributes, and
create some simple tests for the extended attribute editing functions.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'debugfs/xattrs.c')
| -rw-r--r-- | debugfs/xattrs.c | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/debugfs/xattrs.c b/debugfs/xattrs.c new file mode 100644 index 000000000..0a2952143 --- /dev/null +++ b/debugfs/xattrs.c @@ -0,0 +1,297 @@ +/* + * xattrs.c --- Modify extended attributes via debugfs. + * + * Copyright (C) 2014 Oracle. This file may be redistributed + * under the terms of the GNU Public License. + */ + +#include "config.h" +#include <stdio.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#else +extern int optind; +extern char *optarg; +#endif +#include <ctype.h> + +#include "debugfs.h" + +/* Dump extended attributes */ +static void dump_xattr_string(FILE *out, const char *str, int len) +{ + int printable = 0; + int i; + + /* check: is string "printable enough?" */ + for (i = 0; i < len; i++) + if (isprint(str[i])) + printable++; + + if (printable <= len*7/8) + printable = 0; + + for (i = 0; i < len; i++) + if (printable) + fprintf(out, isprint(str[i]) ? "%c" : "\\%03o", + (unsigned char)str[i]); + else + fprintf(out, "%02x ", (unsigned char)str[i]); +} + +static int dump_attr(char *name, char *value, size_t value_len, void *data) +{ + FILE *out = data; + + fprintf(out, " "); + dump_xattr_string(out, name, strlen(name)); + fprintf(out, " = \""); + dump_xattr_string(out, value, value_len); + fprintf(out, "\" (%zu)\n", value_len); + + return 0; +} + +void dump_inode_attributes(FILE *out, ext2_ino_t ino) +{ + struct ext2_xattr_handle *h; + size_t sz; + errcode_t err; + + err = ext2fs_xattrs_open(current_fs, ino, &h); + if (err) + return; + + err = ext2fs_xattrs_read(h); + if (err) + goto out; + + err = ext2fs_xattrs_count(h, &sz); + if (err || sz == 0) + goto out; + + fprintf(out, "Extended attributes:\n"); + err = ext2fs_xattrs_iterate(h, dump_attr, out); + if (err) + goto out; + +out: + err = ext2fs_xattrs_close(&h); +} + +void do_list_xattr(int argc, char **argv) +{ + ext2_ino_t ino; + + if (argc != 2) { + printf("%s: Usage: %s <file>\n", argv[0], + argv[0]); + return; + } + + if (check_fs_open(argv[0])) + return; + + ino = string_to_inode(argv[1]); + if (!ino) + return; + + dump_inode_attributes(stdout, ino); +} + +void do_get_xattr(int argc, char **argv) +{ + ext2_ino_t ino; + struct ext2_xattr_handle *h; + FILE *fp = NULL; + char *buf = NULL; + size_t buflen; + int i; + errcode_t err; + + reset_getopt(); + while ((i = getopt(argc, argv, "f:")) != -1) { + switch (i) { + case 'f': + fp = fopen(optarg, "w"); + if (fp == NULL) { + perror(optarg); + return; + } + break; + default: + printf("%s: Usage: %s <file> <attr> [-f outfile]\n", + argv[0], argv[0]); + return; + } + } + + if (optind != argc - 2) { + printf("%s: Usage: %s <file> <attr> [-f outfile]\n", argv[0], + argv[0]); + return; + } + + if (check_fs_open(argv[0])) + return; + + ino = string_to_inode(argv[optind]); + if (!ino) + return; + + err = ext2fs_xattrs_open(current_fs, ino, &h); + if (err) + return; + + err = ext2fs_xattrs_read(h); + if (err) + goto out; + + err = ext2fs_xattr_get(h, argv[optind + 1], (void **)&buf, &buflen); + if (err) + goto out; + + if (fp) { + fwrite(buf, buflen, 1, fp); + fclose(fp); + } else { + dump_xattr_string(stdout, buf, buflen); + printf("\n"); + } + + if (buf) + ext2fs_free_mem(&buf); +out: + ext2fs_xattrs_close(&h); + if (err) + com_err(argv[0], err, "while getting extended attribute"); +} + +void do_set_xattr(int argc, char **argv) +{ + ext2_ino_t ino; + struct ext2_xattr_handle *h; + FILE *fp = NULL; + char *buf = NULL; + size_t buflen; + int i; + errcode_t err; + + reset_getopt(); + while ((i = getopt(argc, argv, "f:")) != -1) { + switch (i) { + case 'f': + fp = fopen(optarg, "r"); + if (fp == NULL) { + perror(optarg); + return; + } + break; + default: + printf("%s: Usage: %s <file> <attr> [-f infile | " + "value]\n", argv[0], argv[0]); + return; + } + } + + if (optind != argc - 2 && optind != argc - 3) { + printf("%s: Usage: %s <file> <attr> [-f infile | value>]\n", + argv[0], argv[0]); + return; + } + + if (check_fs_open(argv[0])) + return; + if (check_fs_read_write(argv[0])) + return; + if (check_fs_bitmaps(argv[0])) + return; + + ino = string_to_inode(argv[optind]); + if (!ino) + return; + + err = ext2fs_xattrs_open(current_fs, ino, &h); + if (err) + return; + + err = ext2fs_xattrs_read(h); + if (err) + goto out; + + if (fp) { + err = ext2fs_get_mem(current_fs->blocksize, &buf); + if (err) + goto out; + buflen = fread(buf, 1, current_fs->blocksize, fp); + } else { + buf = argv[optind + 2]; + buflen = strlen(argv[optind + 2]); + } + + err = ext2fs_xattr_set(h, argv[optind + 1], buf, buflen); + if (err) + goto out; + + err = ext2fs_xattrs_write(h); + if (err) + goto out; + +out: + if (fp) { + fclose(fp); + ext2fs_free_mem(&buf); + } + ext2fs_xattrs_close(&h); + if (err) + com_err(argv[0], err, "while setting extended attribute"); +} + +void do_rm_xattr(int argc, char **argv) +{ + ext2_ino_t ino; + struct ext2_xattr_handle *h; + int i; + errcode_t err; + + if (argc < 3) { + printf("%s: Usage: %s <file> <attrs>...\n", argv[0], argv[0]); + return; + } + + if (check_fs_open(argv[0])) + return; + if (check_fs_read_write(argv[0])) + return; + if (check_fs_bitmaps(argv[0])) + return; + + ino = string_to_inode(argv[1]); + if (!ino) + return; + + err = ext2fs_xattrs_open(current_fs, ino, &h); + if (err) + return; + + err = ext2fs_xattrs_read(h); + if (err) + goto out; + + for (i = 2; i < argc; i++) { + size_t buflen; + char *buf; + + err = ext2fs_xattr_remove(h, argv[i]); + if (err) + goto out; + } + + err = ext2fs_xattrs_write(h); + if (err) + goto out; +out: + ext2fs_xattrs_close(&h); + if (err) + com_err(argv[0], err, "while removing extended attribute"); +} |
