[Ocfs2-tools-devel] [PATCH 7/7] debugfs: add set/get xattr commands

Tiger Yang tiger.yang at oracle.com
Tue Oct 20 01:42:30 PDT 2009


This patch add do_setxattr and do_getxattr commands
for setting and getting xattrs of a file.
This patch also add a new option "l" for list all xattrs' name
for command do_xattr.

Signed-off-by: Tiger Yang <tiger.yang at oracle.com>
---
 debugfs.ocfs2/commands.c     |  179 ++++++++++++++++++++++++++++++++++++++++--
 debugfs.ocfs2/dump.c         |   45 +++++++++--
 debugfs.ocfs2/include/dump.h |    4 +-
 3 files changed, 212 insertions(+), 16 deletions(-)

diff --git a/debugfs.ocfs2/commands.c b/debugfs.ocfs2/commands.c
index c0bf85a..63894b1 100644
--- a/debugfs.ocfs2/commands.c
+++ b/debugfs.ocfs2/commands.c
@@ -75,6 +75,8 @@ static void do_dlm_locks (char **args);
 static void do_controld(char **args);
 static void do_dirblocks(char **args);
 static void do_xattr(char **args);
+static void do_setxattr(char **args);
+static void do_getxattr(char **args);
 static void do_frag(char **args);
 
 dbgfs_gbls gbls;
@@ -110,6 +112,8 @@ static Command commands[] = {
 	{ "stat",	do_stat },
 	{ "stats",	do_stats },
 	{ "xattr",	do_xattr },
+	{ "setxattr",	do_setxattr },
+	{ "getxattr",	do_getxattr },
 	{ "encode",	do_encode_lockres },
 	{ "decode",	do_decode_lockres },
 	{ "dirblocks",	do_dirblocks },
@@ -1784,10 +1788,11 @@ static void do_xattr(char **args)
 	struct ocfs2_dinode *inode;
 	char *buf = NULL;
 	FILE *out;
-	char *usage = "usage: xattr [-v] <filespec>";
+	char *usage = "usage: xattr [-v] [-l] <filespec>";
 	uint64_t blkno, xattrs_bucket = 0;
 	uint32_t xattrs_ibody = 0, xattrs_block = 0;
-	int ind = 1, verbose = 0;
+	int ind = 0, verbose = 0, listxattr = 0;
+	int argc, c;
 	errcode_t ret = 0;
 
 	if (check_device_open())
@@ -1798,11 +1803,23 @@ static void do_xattr(char **args)
 		return;
 	}
 
-	if (!strcmp(args[1], "-v")) {
-		++ind;
-		++verbose;
+	for (argc = 0; (args[argc]); ++argc);
+
+	optind = 0;
+	while ((c = getopt(argc, args, "vl")) != -1) {
+		switch (c) {
+		case 'v':
+			verbose = 1;
+			break;
+		case 'l':
+			listxattr = 1;
+			break;
+		default:
+			break;
+		}
 	}
 
+	ind = optind;
 	if (!args[ind]) {
 		fprintf(stderr, "%s\n", usage);
 		return;
@@ -1828,11 +1845,12 @@ static void do_xattr(char **args)
 
 	out = open_pager(gbls.interactive);
 
-	xattrs_ibody = dump_xattr_ibody(out, gbls.fs, inode, verbose);
+	xattrs_ibody = dump_xattr_ibody(out, gbls.fs, inode, verbose,
+					listxattr);
 
 	if (inode->i_xattr_loc)
 		ret = dump_xattr_block(out, gbls.fs, inode, &xattrs_block,
-				       &xattrs_bucket, verbose);
+				       &xattrs_bucket, verbose, listxattr);
 
 	if (ret)
 		com_err(args[0], ret, "while traversing inode at block "
@@ -1845,6 +1863,153 @@ static void do_xattr(char **args)
 	return ;
 }
 
+static void do_setxattr(char **args)
+{
+	ocfs2_cached_inode *ci = NULL;
+	char *usage = "usage: setxattr -n xxxx -v xxxx <filespec>";
+	uint64_t blkno;
+	int ind = 0;
+	errcode_t ret = 0;
+	char *name = NULL;
+	char *value = NULL;
+	int argc, c;
+	int value_len;
+
+	if (check_device_open())
+		return;
+
+	if (!args[1]) {
+		fprintf(stderr, "%s\n", usage);
+		return;
+	}
+
+	for (argc = 0; (args[argc]); ++argc);
+
+	optind = 0;
+	while ((c = getopt(argc, args, "n:v:")) != -1) {
+		switch (c) {
+		case 'n':
+			name = optarg;
+			break;
+		case 'v':
+			value = optarg;
+			break;
+		default:
+			break;
+		}
+	}
+
+	ind = optind;
+	if (!args[ind]) {
+		fprintf(stderr, "%s\n", usage);
+		return;
+	}
+
+	ret = string_to_inode(gbls.fs, gbls.root_blkno, gbls.cwd_blkno,
+			      args[ind], &blkno);
+	if (ret) {
+		com_err(args[0], ret, "while translating %s", args[ind]);
+		return;
+	}
+	value_len = strlen(value);
+
+	ret = ocfs2_read_cached_inode(gbls.fs, blkno, &ci);
+	if (ret) {
+		com_err(args[0], ret, "while reading inode %"PRIu64"", blkno);
+		return;
+	}
+
+	ret = ocfs2_xattr_set(ci, name, value, value_len);
+	if (ret) {
+		com_err(args[0], ret, "while set xattr in inode %"PRIu64"",
+			blkno);
+		return;
+	}
+	ret = ocfs2_write_cached_inode(gbls.fs, ci);
+	if (ret) {
+		com_err(args[0], ret, "while write xattr in inode %"PRIu64"",
+			blkno);
+		return;
+	}
+
+	if (ci)
+		ocfs2_free_cached_inode(gbls.fs, ci);
+
+	return ;
+}
+
+static void do_getxattr(char **args)
+{
+	ocfs2_cached_inode *ci = NULL;
+	char *usage = "usage: getxattr -n xxxx <filespec>";
+	uint64_t blkno;
+	int ind = 0;
+	errcode_t ret = 0;
+	char *name = NULL;
+	char *value = NULL;
+	int argc, c;
+	int value_len;
+	size_t got = 0;
+
+	if (check_device_open())
+		return;
+
+	if (!args[1]) {
+		fprintf(stderr, "%s\n", usage);
+		return;
+	}
+
+	for (argc = 0; (args[argc]); ++argc);
+
+	optind = 0;
+	while ((c = getopt(argc, args, "n:")) != -1) {
+		switch (c) {
+		case 'n':
+			name = optarg;
+			break;
+		default:
+			break;
+		}
+	}
+
+	ind = optind;
+	if (!args[ind]) {
+		fprintf(stderr, "%s\n", usage);
+		return;
+	}
+
+	ret = string_to_inode(gbls.fs, gbls.root_blkno, gbls.cwd_blkno,
+			      args[ind], &blkno);
+	if (ret) {
+		com_err(args[0], ret, "while translating %s", args[ind]);
+		return;
+	}
+	ret = ocfs2_malloc_blocks(gbls.fs->fs_io,
+				  65536 / gbls.fs->fs_blocksize, &value);
+	if (ret)
+		return;
+	value_len = 65536;
+
+	ret = ocfs2_read_cached_inode(gbls.fs, blkno, &ci);
+	if (ret) {
+		com_err(args[0], ret, "while reading inode %"PRIu64"", blkno);
+		return;
+	}
+
+	ret = ocfs2_xattr_get(ci, name, value, value_len, &got);
+	if (ret < 0) {
+		com_err(args[0], ret, "while get xattr in inode %"PRIu64"",
+			blkno);
+		return;
+	}
+
+	if (ci)
+		ocfs2_free_cached_inode(gbls.fs, ci);
+
+	ocfs2_free(&value);
+	return ;
+}
+
 static errcode_t calc_num_extents(ocfs2_filesys *fs,
 				  struct ocfs2_extent_list *el,
 				  uint32_t *ne)
diff --git a/debugfs.ocfs2/dump.c b/debugfs.ocfs2/dump.c
index 4c6891a..ba1b515 100644
--- a/debugfs.ocfs2/dump.c
+++ b/debugfs.ocfs2/dump.c
@@ -829,6 +829,28 @@ void dump_icheck(FILE *out, int hdr, uint64_t blkno, uint64_t inode,
 	fprintf(out, "\t%-15"PRIu64"   %-15s   %-15s\n", blkno, inostr, offstr);
 }
 
+static void list_xattr(FILE *out, struct ocfs2_xattr_header *xh)
+{
+	int i, type;
+	const char *prefix, *name;
+	char xname[400];
+
+	for (i = 0 ; i < xh->xh_count; i++) {
+		struct ocfs2_xattr_entry *xe = &xh->xh_entries[i];
+		int pre_len;
+		type = ocfs2_xattr_get_type(xe);
+		prefix = ocfs2_xattr_get_prefix(type);
+		if (prefix) {
+			pre_len = strlen(prefix);
+			name = (const char *)xh + xe->xe_name_offset;
+			memcpy(xname, prefix, pre_len);
+			memcpy(xname + pre_len, name, xe->xe_name_len);
+			xname[pre_len + xe->xe_name_len] = '\0';
+			fprintf(out, "%s\n", xname);
+		}
+	}
+}
+
 static void dump_xattr(FILE *out, struct ocfs2_xattr_header *xh)
 {
 	int i;
@@ -861,7 +883,8 @@ static errcode_t dump_xattr_buckets(FILE *out,
 				    uint64_t blkno,
 				    uint32_t clusters,
 				    uint64_t *xattrs_bucket,
-				    int verbose)
+				    int verbose,
+				    int listxattr)
 {
 	int i;
 	errcode_t ret = 0;
@@ -895,6 +918,8 @@ static errcode_t dump_xattr_buckets(FILE *out,
 			i, xh->xh_count);
 		if (verbose)
 			dump_xattr(out, xh);
+		else if (listxattr)
+			list_xattr(out, xh);
 		*xattrs_bucket += xh->xh_count;
 	}
 
@@ -911,7 +936,8 @@ static errcode_t dump_xattr_index_block(FILE *out,
 					struct ocfs2_dinode *di,
 					struct ocfs2_xattr_block *xb,
 					uint64_t *xattrs_bucket,
-					int verbose)
+					int verbose,
+					int listxattr)
 {
 	struct ocfs2_extent_list *el = &xb->xb_attrs.xb_root.xt_list;
 	errcode_t ret = 0;
@@ -934,7 +960,7 @@ static errcode_t dump_xattr_index_block(FILE *out,
 			goto out;
 
 		ret = dump_xattr_buckets(out, fs, p_blkno, num_clusters,
-					 xattrs_bucket, verbose);
+					 xattrs_bucket, verbose, listxattr);
 		if (ret)
 			goto out;
 
@@ -956,7 +982,8 @@ errcode_t dump_xattr_block(FILE *out, ocfs2_filesys *fs,
 			   struct ocfs2_dinode *in,
 			   uint32_t *xattrs_block,
 			   uint64_t *xattrs_bucket,
-			   int verbose)
+			   int verbose,
+			   int listxattr)
 {
 	errcode_t ret;
 	char *blk = NULL;
@@ -979,9 +1006,11 @@ errcode_t dump_xattr_block(FILE *out, ocfs2_filesys *fs,
 			(uint64_t)in->i_xattr_loc, *xattrs_block);
 		if (verbose)
 			dump_xattr(out, xh);
+		else if (listxattr)
+			list_xattr(out, xh);
 	} else {
-		ret = dump_xattr_index_block(out, fs, in, xb,
-					     xattrs_bucket, verbose);
+		ret = dump_xattr_index_block(out, fs, in, xb, xattrs_bucket,
+					     verbose, listxattr);
 	}
 
 out:
@@ -994,7 +1023,7 @@ out:
  *
  */
 uint32_t dump_xattr_ibody(FILE *out, ocfs2_filesys *fs,
-			  struct ocfs2_dinode *in, int verbose)
+			  struct ocfs2_dinode *in, int verbose, int listxattr)
 {
 	if (in->i_dyn_features & OCFS2_INLINE_XATTR_FL) {
 		struct ocfs2_xattr_header *xh = (struct ocfs2_xattr_header *)
@@ -1005,6 +1034,8 @@ uint32_t dump_xattr_ibody(FILE *out, ocfs2_filesys *fs,
 			xh->xh_count);
 		if (verbose)
 			dump_xattr(out, xh);
+		else if (listxattr)
+			list_xattr(out, xh);
 		return xh->xh_count;
 	} else {
 		fprintf(out, "\tExtended Attributes inline: 0\n");
diff --git a/debugfs.ocfs2/include/dump.h b/debugfs.ocfs2/include/dump.h
index 8cd9a97..ea0cbcf 100644
--- a/debugfs.ocfs2/include/dump.h
+++ b/debugfs.ocfs2/include/dump.h
@@ -70,12 +70,12 @@ void dump_icheck(FILE *out, int hdr, uint64_t blkno, uint64_t inode,
 		 int validoffset, uint64_t offset, int status);
 void dump_block_check(FILE *out, struct ocfs2_block_check *bc);
 uint32_t dump_xattr_ibody(FILE *out, ocfs2_filesys *fs,
-			  struct ocfs2_dinode *in, int verbose);
+			  struct ocfs2_dinode *in, int verbose, int listxattr);
 errcode_t dump_xattr_block(FILE *out, ocfs2_filesys *fs,
 			   struct ocfs2_dinode *in,
 			   uint32_t *xattrs_block,
 			   uint64_t *xattrs_bucket,
-			   int verbose);
+			   int verbose, int listxattr);
 void dump_frag(FILE *out, uint64_t ino, uint32_t clusters,
 	       uint32_t extents);
 
-- 
1.5.4.1




More information about the Ocfs2-tools-devel mailing list