forked from rpms/e2fsprogs
245 lines
8.1 KiB
Diff
245 lines
8.1 KiB
Diff
From 5862f45c314aaf97ce098add06c42b5d592dc984 Mon Sep 17 00:00:00 2001
|
|
From: Theodore Ts'o <tytso@mit.edu>
|
|
Date: Thu, 13 Dec 2018 00:53:16 -0500
|
|
Subject: [PATCH 2/4] debugfs: fix set_inode_field so it can set the checksum
|
|
field
|
|
|
|
Previously, setting the inode field was a no-op, since the library
|
|
function ext2fs_write_inode_full() would override whatever value was
|
|
set by debugfs. Use the new ext2fs_write_inode2() interface so we can
|
|
in fact set the checksum to a potentially wrong value. Also, ignore
|
|
the inode checksum failures if we are setting the checksum, and if the
|
|
checksum value is "calc", set the inode checksum to the correct value.
|
|
|
|
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
|
|
---
|
|
debugfs/debugfs.c | 12 +++----
|
|
debugfs/debugfs.h | 8 ++---
|
|
debugfs/set_fields.c | 84 +++++++++++++++++++++++++++++++++++++++-----
|
|
debugfs/util.c | 17 +++++----
|
|
4 files changed, 94 insertions(+), 27 deletions(-)
|
|
|
|
diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c
|
|
index faae12da..06a93270 100644
|
|
--- a/debugfs/debugfs.c
|
|
+++ b/debugfs/debugfs.c
|
|
@@ -985,8 +985,8 @@ void do_stat(int argc, char *argv[])
|
|
return;
|
|
}
|
|
|
|
- if (debugfs_read_inode_full(inode, inode_buf, argv[0],
|
|
- EXT2_INODE_SIZE(current_fs->super))) {
|
|
+ if (debugfs_read_inode2(inode, inode_buf, argv[0],
|
|
+ EXT2_INODE_SIZE(current_fs->super), 0)) {
|
|
free(inode_buf);
|
|
return;
|
|
}
|
|
@@ -1608,12 +1608,12 @@ void do_copy_inode(int argc, char *argv[])
|
|
if (!dest_ino)
|
|
return;
|
|
|
|
- if (debugfs_read_inode_full(src_ino, (struct ext2_inode *) buf,
|
|
- argv[0], sizeof(buf)))
|
|
+ if (debugfs_read_inode2(src_ino, (struct ext2_inode *) buf,
|
|
+ argv[0], sizeof(buf), 0))
|
|
return;
|
|
|
|
- if (debugfs_write_inode_full(dest_ino, (struct ext2_inode *) buf,
|
|
- argv[0], sizeof(buf)))
|
|
+ if (debugfs_write_inode2(dest_ino, (struct ext2_inode *) buf,
|
|
+ argv[0], sizeof(buf), 0))
|
|
return;
|
|
}
|
|
|
|
diff --git a/debugfs/debugfs.h b/debugfs/debugfs.h
|
|
index 93f036de..97fdde7e 100644
|
|
--- a/debugfs/debugfs.h
|
|
+++ b/debugfs/debugfs.h
|
|
@@ -54,12 +54,12 @@ extern int common_block_args_process(int argc, char *argv[],
|
|
blk64_t *block, blk64_t *count);
|
|
extern int debugfs_read_inode(ext2_ino_t ino, struct ext2_inode * inode,
|
|
const char *cmd);
|
|
-extern int debugfs_read_inode_full(ext2_ino_t ino, struct ext2_inode * inode,
|
|
- const char *cmd, int bufsize);
|
|
+extern int debugfs_read_inode2(ext2_ino_t ino, struct ext2_inode * inode,
|
|
+ const char *cmd, int bufsize, int flags);
|
|
extern int debugfs_write_inode(ext2_ino_t ino, struct ext2_inode * inode,
|
|
const char *cmd);
|
|
-extern int debugfs_write_inode_full(ext2_ino_t ino, struct ext2_inode * inode,
|
|
- const char *cmd, int bufsize);
|
|
+extern int debugfs_write_inode2(ext2_ino_t ino, struct ext2_inode * inode,
|
|
+ const char *cmd, int bufsize, int flags);
|
|
extern int debugfs_write_new_inode(ext2_ino_t ino, struct ext2_inode * inode,
|
|
const char *cmd);
|
|
extern int ext2_file_type(unsigned int mode);
|
|
diff --git a/debugfs/set_fields.c b/debugfs/set_fields.c
|
|
index 3cdf617c..4f033249 100644
|
|
--- a/debugfs/set_fields.c
|
|
+++ b/debugfs/set_fields.c
|
|
@@ -53,6 +53,7 @@ static int array_idx;
|
|
|
|
#define FLAG_ARRAY 0x0001
|
|
#define FLAG_ALIAS 0x0002 /* Data intersects with other field */
|
|
+#define FLAG_CSUM 0x0004
|
|
|
|
struct field_set_info {
|
|
const char *name;
|
|
@@ -72,6 +73,8 @@ static errcode_t parse_hashalg(struct field_set_info *info, char *field, char *a
|
|
static errcode_t parse_time(struct field_set_info *info, char *field, char *arg);
|
|
static errcode_t parse_bmap(struct field_set_info *info, char *field, char *arg);
|
|
static errcode_t parse_gd_csum(struct field_set_info *info, char *field, char *arg);
|
|
+static errcode_t parse_inode_csum(struct field_set_info *info, char *field,
|
|
+ char *arg);
|
|
static errcode_t parse_mmp_clear(struct field_set_info *info, char *field,
|
|
char *arg);
|
|
|
|
@@ -218,7 +221,7 @@ static struct field_set_info inode_fields[] = {
|
|
{ "frag", &set_inode.osd2.hurd2.h_i_frag, NULL, 1, parse_uint, FLAG_ALIAS },
|
|
{ "fsize", &set_inode.osd2.hurd2.h_i_fsize, NULL, 1, parse_uint },
|
|
{ "checksum", &set_inode.osd2.linux2.l_i_checksum_lo,
|
|
- &set_inode.i_checksum_hi, 2, parse_uint },
|
|
+ &set_inode.i_checksum_hi, 2, parse_inode_csum, FLAG_CSUM },
|
|
{ "author", &set_inode.osd2.hurd2.h_i_author, NULL,
|
|
4, parse_uint, FLAG_ALIAS },
|
|
{ "extra_isize", &set_inode.i_extra_isize, NULL,
|
|
@@ -665,6 +668,68 @@ static errcode_t parse_gd_csum(struct field_set_info *info, char *field,
|
|
return parse_uint(info, field, arg);
|
|
}
|
|
|
|
+static errcode_t parse_inode_csum(struct field_set_info *info, char *field,
|
|
+ char *arg)
|
|
+{
|
|
+ errcode_t retval = 0;
|
|
+ __u32 crc;
|
|
+ int is_large_inode = 0;
|
|
+ struct ext2_inode_large *tmp_inode;
|
|
+
|
|
+ if (strcmp(arg, "calc") == 0) {
|
|
+ size_t sz = EXT2_INODE_SIZE(current_fs->super);
|
|
+ struct ext2_inode_large *tmp_inode = NULL;
|
|
+
|
|
+ retval = ext2fs_get_mem(sz, &tmp_inode);
|
|
+ if (retval)
|
|
+ goto out;
|
|
+
|
|
+ retval = ext2fs_read_inode_full(current_fs, set_ino,
|
|
+ (struct ext2_inode *) tmp_inode,
|
|
+ sz);
|
|
+ if (retval)
|
|
+ goto out;
|
|
+
|
|
+#ifdef WORDS_BIGENDIAN
|
|
+ ext2fs_swap_inode_full(current_fs, tmp_inode,
|
|
+ tmp_inode, 1, sz);
|
|
+#endif
|
|
+
|
|
+ if (sz > EXT2_GOOD_OLD_INODE_SIZE)
|
|
+ is_large_inode = 1;
|
|
+
|
|
+ retval = ext2fs_inode_csum_set(current_fs, set_ino,
|
|
+ tmp_inode);
|
|
+ if (retval)
|
|
+ goto out;
|
|
+#ifdef WORDS_BIGENDIAN
|
|
+ crc = set_inode.i_checksum_lo =
|
|
+ ext2fs_swab16(tmp_inode->i_checksum_lo);
|
|
+
|
|
+#else
|
|
+ crc = set_inode.i_checksum_lo = tmp_inode->i_checksum_lo;
|
|
+#endif
|
|
+ if (is_large_inode &&
|
|
+ set_inode.i_extra_isize >=
|
|
+ (offsetof(struct ext2_inode_large,
|
|
+ i_checksum_hi) -
|
|
+ EXT2_GOOD_OLD_INODE_SIZE)) {
|
|
+#ifdef WORDS_BIGENDIAN
|
|
+ set_inode.i_checksum_lo =
|
|
+ ext2fs_swab16(tmp_inode->i_checksum_lo);
|
|
+#else
|
|
+ set_inode.i_checksum_hi = tmp_inode->i_checksum_hi;
|
|
+#endif
|
|
+ crc |= ((__u32)set_inode.i_checksum_hi) << 16;
|
|
+ }
|
|
+ printf("Checksum set to 0x%08x\n", crc);
|
|
+ out:
|
|
+ ext2fs_free_mem(&tmp_inode);
|
|
+ return retval;
|
|
+ }
|
|
+ return parse_uint(info, field, arg);
|
|
+}
|
|
+
|
|
static void print_possible_fields(struct field_set_info *fields)
|
|
{
|
|
struct field_set_info *ss;
|
|
@@ -775,16 +840,19 @@ void do_set_inode(int argc, char *argv[])
|
|
if (!set_ino)
|
|
return;
|
|
|
|
- if (debugfs_read_inode_full(set_ino,
|
|
- (struct ext2_inode *) &set_inode, argv[1],
|
|
- sizeof(set_inode)))
|
|
+ if (debugfs_read_inode2(set_ino,
|
|
+ (struct ext2_inode *) &set_inode, argv[1],
|
|
+ sizeof(set_inode),
|
|
+ (ss->flags & FLAG_CSUM) ?
|
|
+ READ_INODE_NOCSUM : 0))
|
|
return;
|
|
|
|
if (ss->func(ss, argv[2], argv[3]) == 0) {
|
|
- if (debugfs_write_inode_full(set_ino,
|
|
- (struct ext2_inode *) &set_inode,
|
|
- argv[1], sizeof(set_inode)))
|
|
- return;
|
|
+ debugfs_write_inode2(set_ino,
|
|
+ (struct ext2_inode *) &set_inode,
|
|
+ argv[1], sizeof(set_inode),
|
|
+ (ss->flags & FLAG_CSUM) ?
|
|
+ WRITE_INODE_NOCSUM : 0);
|
|
}
|
|
}
|
|
|
|
diff --git a/debugfs/util.c b/debugfs/util.c
|
|
index 452de749..759bb392 100644
|
|
--- a/debugfs/util.c
|
|
+++ b/debugfs/util.c
|
|
@@ -420,12 +420,12 @@ int common_block_args_process(int argc, char *argv[],
|
|
return 0;
|
|
}
|
|
|
|
-int debugfs_read_inode_full(ext2_ino_t ino, struct ext2_inode * inode,
|
|
- const char *cmd, int bufsize)
|
|
+int debugfs_read_inode2(ext2_ino_t ino, struct ext2_inode * inode,
|
|
+ const char *cmd, int bufsize, int flags)
|
|
{
|
|
int retval;
|
|
|
|
- retval = ext2fs_read_inode_full(current_fs, ino, inode, bufsize);
|
|
+ retval = ext2fs_read_inode2(current_fs, ino, inode, bufsize, flags);
|
|
if (retval) {
|
|
com_err(cmd, retval, "while reading inode %u", ino);
|
|
return 1;
|
|
@@ -446,15 +446,14 @@ int debugfs_read_inode(ext2_ino_t ino, struct ext2_inode * inode,
|
|
return 0;
|
|
}
|
|
|
|
-int debugfs_write_inode_full(ext2_ino_t ino,
|
|
- struct ext2_inode *inode,
|
|
- const char *cmd,
|
|
- int bufsize)
|
|
+int debugfs_write_inode2(ext2_ino_t ino,
|
|
+ struct ext2_inode *inode,
|
|
+ const char *cmd,
|
|
+ int bufsize, int flags)
|
|
{
|
|
int retval;
|
|
|
|
- retval = ext2fs_write_inode_full(current_fs, ino,
|
|
- inode, bufsize);
|
|
+ retval = ext2fs_write_inode2(current_fs, ino, inode, bufsize, flags);
|
|
if (retval) {
|
|
com_err(cmd, retval, "while writing inode %u", ino);
|
|
return 1;
|
|
--
|
|
2.20.1
|
|
|