diff options
author | Theodore Ts'o <tytso@mit.edu> | 2004-12-21 20:37:36 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2004-12-21 20:37:36 -0500 |
commit | 7dec050a807eec171e29c9a7966347633a5992bf (patch) | |
tree | 7e3371fbf4ec3d72019337a6cb9198b742077a54 | |
parent | a06bd026c7f366c080db0a38ffbf1fe38abb0999 (diff) | |
download | android_external_e2fsprogs-7dec050a807eec171e29c9a7966347633a5992bf.tar.gz android_external_e2fsprogs-7dec050a807eec171e29c9a7966347633a5992bf.tar.bz2 android_external_e2fsprogs-7dec050a807eec171e29c9a7966347633a5992bf.zip |
Enhance debugfs so that set_super_value can now set the wtime, mtime,
lastcheck, and mkfs_time fields with date/time values.
Add the set_inode command to debugfs so that individual inode fields can
be more easily modified. We should probably make the modify_inode
command go away at some point.
-rw-r--r-- | debugfs/ChangeLog | 9 | ||||
-rw-r--r-- | debugfs/Makefile.in | 6 | ||||
-rw-r--r-- | debugfs/debug_cmds.ct | 3 | ||||
-rw-r--r-- | debugfs/debugfs.8.in | 11 | ||||
-rw-r--r-- | debugfs/debugfs.h | 3 | ||||
-rw-r--r-- | debugfs/set_fields.c (renamed from debugfs/setsuper.c) | 193 |
6 files changed, 191 insertions, 34 deletions
diff --git a/debugfs/ChangeLog b/debugfs/ChangeLog index 0b6c28f9..d8712626 100644 --- a/debugfs/ChangeLog +++ b/debugfs/ChangeLog @@ -1,3 +1,12 @@ +2004-12-21 Theodore Ts'o <tytso@mit.edu> + + * setfields.c: Renamed from setsuper.c + Added support to set date/time fields. + Added support for setting superblock values wtime, mtime, + lastcheck, and mkfs_time as date/time fields. + Added support for the set_inode command. + * debugfs.h, debug_cmds.ct, debugfs.8.in: Added set_inode command + 2004-12-16 Theodore Ts'o <tytso@mit.edu> * setsuper.c: Add definitions for newer superblock fields: diff --git a/debugfs/Makefile.in b/debugfs/Makefile.in index ccd32de8..e0085c1f 100644 --- a/debugfs/Makefile.in +++ b/debugfs/Makefile.in @@ -18,11 +18,11 @@ MANPAGES= debugfs.8 MK_CMDS= _SS_DIR_OVERRIDE=../lib/ss ../lib/ss/mk_cmds DEBUG_OBJS= debug_cmds.o debugfs.o util.o ncheck.o icheck.o ls.o \ - lsdel.o dump.o setsuper.o logdump.o htree.o unused.o + lsdel.o dump.o set_fields.o logdump.o htree.o unused.o SRCS= debug_cmds.c $(srcdir)/debugfs.c $(srcdir)/util.c $(srcdir)/ls.c \ $(srcdir)/ncheck.c $(srcdir)/icheck.c $(srcdir)/lsdel.c \ - $(srcdir)/dump.c $(srcdir)/setsuper.c ${srcdir}/logdump.c \ + $(srcdir)/dump.c $(srcdir)/set_fields.c ${srcdir}/logdump.c \ $(srcdir)/htree.c $(srcdir)/unused.c LIBS= $(LIBEXT2FS) $(LIBE2P) $(LIBSS) $(LIBCOM_ERR) $(LIBBLKID) \ @@ -130,7 +130,7 @@ dump.o: $(srcdir)/dump.c $(srcdir)/debugfs.h \ $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/et/com_err.h \ $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ $(top_srcdir)/lib/ext2fs/bitops.h -setsuper.o: $(srcdir)/setsuper.c $(srcdir)/debugfs.h \ +set_fields.o: $(srcdir)/set_fields.c $(srcdir)/debugfs.h \ $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/et/com_err.h \ $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ diff --git a/debugfs/debug_cmds.ct b/debugfs/debug_cmds.ct index cea56852..65ad9987 100644 --- a/debugfs/debug_cmds.ct +++ b/debugfs/debug_cmds.ct @@ -124,6 +124,9 @@ request do_rdump, "Recursively dump a directory to the native filesystem", request do_set_super, "Set superblock value", set_super_value, ssv; +request do_set_inode, "Set inode field", + set_inode, si; + request do_logdump, "Dump the contents of the journal", logdump; diff --git a/debugfs/debugfs.8.in b/debugfs/debugfs.8.in index 9bb33540..b640bf98 100644 --- a/debugfs/debugfs.8.in +++ b/debugfs/debugfs.8.in @@ -393,6 +393,17 @@ Mark inode .I filespec as in use in the inode bitmap. .TP +.I set_inode filespec field value +Modify the inode specified by +.I filespec +so that the inode field +.I field +has value +.I value. +The list of valid inode fields which can be set via this command +can be displayed by using the command: +.B set_inode -l +.TP .I set_super_value field value Set the superblock field .I field diff --git a/debugfs/debugfs.h b/debugfs/debugfs.h index cb6ba850..b54f8601 100644 --- a/debugfs/debugfs.h +++ b/debugfs/debugfs.h @@ -70,8 +70,9 @@ extern void do_icheck(int argc, char **argv); /* ncheck.c */ extern void do_ncheck(int argc, char **argv); -/* set_super.c */ +/* set_fields.c */ extern void do_set_super(int argc, char **); +extern void do_set_inode(int argc, char **); /* unused.c */ extern void do_dump_unused(int argc, char **argv); diff --git a/debugfs/setsuper.c b/debugfs/set_fields.c index 60104a2b..9cccceb7 100644 --- a/debugfs/setsuper.c +++ b/debugfs/set_fields.c @@ -1,5 +1,12 @@ /* - * setsuper.c --- set a superblock value + * set_fields.c --- set a superblock value + * + * Copyright (C) 2000, 2001, 2002, 2003, 2004 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% */ #include <stdio.h> @@ -21,21 +28,23 @@ #include "e2p/e2p.h" static struct ext2_super_block set_sb; +static struct ext2_inode set_inode; -struct super_set_info { +struct field_set_info { const char *name; void *ptr; unsigned int size; - errcode_t (*func)(struct super_set_info *info, char *arg); + errcode_t (*func)(struct field_set_info *info, char *arg); }; -static errcode_t parse_uint(struct super_set_info *info, char *arg); -static errcode_t parse_int(struct super_set_info *info, char *arg); -static errcode_t parse_string(struct super_set_info *info, char *arg); -static errcode_t parse_uuid(struct super_set_info *info, char *arg); -static errcode_t parse_hashalg(struct super_set_info *info, char *arg); +static errcode_t parse_uint(struct field_set_info *info, char *arg); +static errcode_t parse_int(struct field_set_info *info, char *arg); +static errcode_t parse_string(struct field_set_info *info, char *arg); +static errcode_t parse_uuid(struct field_set_info *info, char *arg); +static errcode_t parse_hashalg(struct field_set_info *info, char *arg); +static errcode_t parse_time(struct field_set_info *info, char *arg); -static struct super_set_info super_fields[] = { +static struct field_set_info super_fields[] = { { "inodes_count", &set_sb.s_inodes_count, 4, parse_uint }, { "blocks_count", &set_sb.s_blocks_count, 4, parse_uint }, { "r_blocks_count", &set_sb.s_r_blocks_count, 4, parse_uint }, @@ -47,15 +56,15 @@ static struct super_set_info super_fields[] = { { "blocks_per_group", &set_sb.s_blocks_per_group, 4, parse_uint }, { "frags_per_group", &set_sb.s_frags_per_group, 4, parse_uint }, { "inodes_per_group", &set_sb.s_inodes_per_group, 4, parse_uint }, - /* s_mtime (time_t) */ - /* s_wtime (time_t) */ + { "mtime", &set_sb.s_mtime, 4, parse_time }, + { "wtime", &set_sb.s_wtime, 4, parse_time }, { "mnt_count", &set_sb.s_mnt_count, 2, parse_uint }, { "max_mnt_count", &set_sb.s_max_mnt_count, 2, parse_int }, /* s_magic */ { "state", &set_sb.s_state, 2, parse_uint }, { "errors", &set_sb.s_errors, 2, parse_uint }, { "minor_rev_level", &set_sb.s_minor_rev_level, 2, parse_uint }, - /* s_lastcheck (time_t) */ + { "lastcheck", &set_sb.s_lastcheck, 4, parse_time }, { "checkinterval", &set_sb.s_checkinterval, 4, parse_uint }, { "creator_os", &set_sb.s_creator_os, 4, parse_uint }, { "rev_level", &set_sb.s_rev_level, 4, parse_uint }, @@ -89,24 +98,67 @@ static struct super_set_info super_fields[] = { /* s_reserved_word_pad */ { "default_mount_opts", &set_sb.s_default_mount_opts, 4, parse_uint }, { "first_meta_bg", &set_sb.s_first_meta_bg, 4, parse_uint }, - { "mkfs_time", &set_sb.s_mkfs_time, 4, parse_uint }, + { "mkfs_time", &set_sb.s_mkfs_time, 4, parse_time }, { 0, 0, 0, 0 } }; -static struct super_set_info *find_field(char *field) +static struct field_set_info inode_fields[] = { + { "inodes_count", &set_sb.s_inodes_count, 4, parse_uint }, + { "mode", &set_inode.i_mode, 2, parse_uint }, + { "uid", &set_inode.i_uid, 2, parse_uint }, + { "size", &set_inode.i_uid, 4, parse_uint }, + { "atime", &set_inode.i_atime, 4, parse_time }, + { "ctime", &set_inode.i_ctime, 4, parse_time }, + { "mtime", &set_inode.i_mtime, 4, parse_time }, + { "dtime", &set_inode.i_dtime, 4, parse_time }, + { "gid", &set_inode.i_gid, 2, parse_uint }, + { "links_count", &set_inode.i_links_count, 2, parse_uint }, + { "blocks", &set_inode.i_blocks, 4, parse_uint }, + { "flags", &set_inode.i_flags, 4, parse_uint }, + { "translator", &set_inode.osd1.hurd1.h_i_translator, 4, parse_uint }, + { "block[0]", &set_inode.i_block[0], 4, parse_uint }, + { "block[1]", &set_inode.i_block[1], 4, parse_uint }, + { "block[2]", &set_inode.i_block[2], 4, parse_uint }, + { "block[3]", &set_inode.i_block[3], 4, parse_uint }, + { "block[4]", &set_inode.i_block[4], 4, parse_uint }, + { "block[5]", &set_inode.i_block[5], 4, parse_uint }, + { "block[6]", &set_inode.i_block[6], 4, parse_uint }, + { "block[7]", &set_inode.i_block[7], 4, parse_uint }, + { "block[8]", &set_inode.i_block[8], 4, parse_uint }, + { "block[9]", &set_inode.i_block[9], 4, parse_uint }, + { "block[10]", &set_inode.i_block[10], 4, parse_uint }, + { "block[11]", &set_inode.i_block[11], 4, parse_uint }, + { "block[12]", &set_inode.i_block[12], 4, parse_uint }, + { "block[13]", &set_inode.i_block[13], 4, parse_uint }, + { "block[14]", &set_inode.i_block[14], 4, parse_uint }, + { "generation", &set_inode.i_generation, 4, parse_uint }, + { "file_acl", &set_inode.i_file_acl, 4, parse_uint }, + { "dir_acl", &set_inode.i_dir_acl, 4, parse_uint }, + { "faddr", &set_inode.i_faddr, 4, parse_uint }, + { "frag", &set_inode.osd2.linux2.l_i_frag, 8, parse_uint }, + { "fsize", &set_inode.osd2.linux2.l_i_fsize, 8, parse_uint }, + { "uid_high", &set_inode.osd2.linux2.l_i_uid_high, 8, parse_uint }, + { "gid_high", &set_inode.osd2.linux2.l_i_gid_high, 8, parse_uint }, + { "author", &set_inode.osd2.hurd2.h_i_author, 8, parse_uint }, + { 0, 0, 0, 0 } +}; + + +static struct field_set_info *find_field(struct field_set_info *fields, + char *field) { - struct super_set_info *ss; + struct field_set_info *ss; if (strncmp(field, "s_", 2) == 0) field += 2; - for (ss = super_fields ; ss->name ; ss++) { + for (ss = fields ; ss->name ; ss++) { if (strcmp(ss->name, field) == 0) return ss; } return NULL; } -static errcode_t parse_uint(struct super_set_info *info, char *arg) +static errcode_t parse_uint(struct field_set_info *info, char *arg) { unsigned long num; char *tmp; @@ -137,7 +189,7 @@ static errcode_t parse_uint(struct super_set_info *info, char *arg) return 0; } -static errcode_t parse_int(struct super_set_info *info, char *arg) +static errcode_t parse_int(struct field_set_info *info, char *arg) { long num; char *tmp; @@ -168,7 +220,7 @@ static errcode_t parse_int(struct super_set_info *info, char *arg) return 0; } -static errcode_t parse_string(struct super_set_info *info, char *arg) +static errcode_t parse_string(struct field_set_info *info, char *arg) { char *cp = (char *) info->ptr; @@ -181,7 +233,39 @@ static errcode_t parse_string(struct super_set_info *info, char *arg) return 0; } -static errcode_t parse_uuid(struct super_set_info *info, char *arg) +static errcode_t parse_time(struct field_set_info *info, char *arg) +{ + struct tm ts; + __u32 *ptr32; + + ptr32 = (__u32 *) info->ptr; + + if (strcmp(arg, "now") == 0) { + *ptr32 = time(0); + return 0; + } + memset(&ts, 0, sizeof(ts)); +#ifdef HAVE_STRPTIME + strptime(arg, "%Y%m%d%H%M%S", &ts); +#else + sscanf(arg, "%4d%2d%2d%2d%2d%2d", &ts.tm_year, &ts.tm_mon, + &ts.tm_mday, &ts.tm_hour, &ts.tm_min, &ts.tm_sec); + ts.tm_year -= 1900; + ts.tm_mon -= 1; + if (ts.tm_year < 0 || ts.tm_mon < 0 || ts.tm_mon > 11 || + ts.tm_mday < 0 || ts.tm_mday > 31 || ts.tm_hour > 23 || + ts.tm_min > 59 || ts.tm_sec > 61) + ts.tm_mday = 0; +#endif + if (ts.tm_mday == 0) { + /* Try it as an integer... */ + return parse_uint(info, arg); + } + *ptr32 = mktime(&ts); + return 0; +} + +static errcode_t parse_uuid(struct field_set_info *info, char *arg) { unsigned char * p = (unsigned char *) info->ptr; @@ -199,7 +283,7 @@ static errcode_t parse_uuid(struct super_set_info *info, char *arg) return 0; } -static errcode_t parse_hashalg(struct super_set_info *info, char *arg) +static errcode_t parse_hashalg(struct field_set_info *info, char *arg) { int hashv; unsigned char *p = (unsigned char *) info->ptr; @@ -214,13 +298,24 @@ static errcode_t parse_hashalg(struct super_set_info *info, char *arg) } -static void print_possible_fields(void) +static void print_possible_fields(struct field_set_info *fields) { - struct super_set_info *ss; - const char *type; + struct field_set_info *ss; + const char *type, *cmd; + FILE *f; - printf("Superblock fields supported by the set_super_value command:\n"); - for (ss = super_fields ; ss->name ; ss++) { + if (fields == super_fields) { + type = "Superblock"; + cmd = "set_super_value"; + } else { + type = "Inode"; + cmd = "set_inode"; + } + f = open_pager(); + + fprintf(f, "%s fields supported by the %s command:\n", type, cmd); + + for (ss = fields ; ss->name ; ss++) { type = "unknown"; if (ss->func == parse_string) type = "string"; @@ -232,8 +327,11 @@ static void print_possible_fields(void) type = "UUID"; else if (ss->func == parse_hashalg) type = "hash algorithm"; - printf("\t%-20s\t%s\n", ss->name, type); + else if (ss->func == parse_time) + type = "date/time"; + fprintf(f, "\t%-20s\t%s\n", ss->name, type); } + close_pager(f); } @@ -242,10 +340,10 @@ void do_set_super(int argc, char *argv[]) const char *usage = "<field> <value>\n" "\t\"set_super_value -l\" will list the names of " "superblock fields\n\twhich can be set."; - static struct super_set_info *ss; + static struct field_set_info *ss; if ((argc == 2) && !strcmp(argv[1], "-l")) { - print_possible_fields(); + print_possible_fields(super_fields); return; } @@ -253,7 +351,7 @@ void do_set_super(int argc, char *argv[]) usage, CHECK_FS_RW)) return; - if ((ss = find_field(argv[1])) == 0) { + if ((ss = find_field(super_fields, argv[1])) == 0) { com_err(argv[0], 0, "invalid field specifier: %s", argv[1]); return; } @@ -263,3 +361,38 @@ void do_set_super(int argc, char *argv[]) ext2fs_mark_super_dirty(current_fs); } } + +void do_set_inode(int argc, char *argv[]) +{ + const char *usage = "<inode> <field> <value>\n" + "\t\"set_inode -l\" will list the names of " + "the fields in an ext2 inode\n\twhich can be set."; + static struct field_set_info *ss; + ext2_ino_t ino; + + if ((argc == 2) && !strcmp(argv[1], "-l")) { + print_possible_fields(inode_fields); + return; + } + + if (common_args_process(argc, argv, 4, 4, "set_inode", + usage, CHECK_FS_RW)) + return; + + if ((ss = find_field(inode_fields, argv[2])) == 0) { + com_err(argv[0], 0, "invalid field specifier: %s", argv[2]); + return; + } + + ino = string_to_inode(argv[1]); + if (!ino) + return; + + if (debugfs_read_inode(ino, &set_inode, argv[1])) + return; + + if (ss->func(ss, argv[3]) == 0) { + if (debugfs_write_inode(ino, &set_inode, argv[1])) + return; + } +} |