aboutsummaryrefslogtreecommitdiffstats
path: root/debugfs/xattrs.c
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2014-03-11 23:49:58 -0400
committerTheodore Ts'o <tytso@mit.edu>2014-03-11 23:50:08 -0400
commit227239b10b93bb51b6d8fc4023af77a94cdd7775 (patch)
treed40b7beef4a4f0ff6ff407c3448524e1e9821ee8 /debugfs/xattrs.c
parent2ddcee17711b37fe9fca7d2350f275789a014f86 (diff)
downloadplatform_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.c297
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");
+}