This patch adds a new member `filename' in inject_dentry to inject
dentry filename. The dentry is specified by nid option.

Note that `.' and `..' dentries are special, because they are not in the
parent directory of nid. So this patch also adds a new option `--dots'
to inject these two dentries.

Signed-off-by: Sheng Yong <shengy...@oppo.com>
---
 fsck/inject.c     | 94 ++++++++++++++++++++++++++++++++++++++++-------
 fsck/inject.h     |  1 +
 man/inject.f2fs.8 | 13 ++++++-
 3 files changed, 93 insertions(+), 15 deletions(-)

diff --git a/fsck/inject.c b/fsck/inject.c
index 4a811b3a3302..bc8f09a67c1a 100644
--- a/fsck/inject.c
+++ b/fsck/inject.c
@@ -104,7 +104,7 @@ void inject_usage(void)
        MSG(0, "  --sit <0|1|2> --mb <name> --blk <blk> [--idx <index>] --val 
<value> inject sit entry\n");
        MSG(0, "  --ssa --mb <name> --blk <blk> [--idx <index>] --val <value> 
inject summary entry\n");
        MSG(0, "  --node --mb <name> --nid <nid> [--idx <index>] --val <value> 
inject node\n");
-       MSG(0, "  --dent --mb <name> --nid <ino> [--idx <index>] --val <value> 
inject ino's dentry\n");
+       MSG(0, "  --dent --mb <name> --nid <ino> [--dots <1|2>] --val/str 
<value/string> inject ino's dentry\n");
        MSG(0, "  --dry-run do not really inject\n");
 
        exit(1);
@@ -211,12 +211,16 @@ static void inject_node_usage(void)
 
 static void inject_dent_usage(void)
 {
-       MSG(0, "inject.f2fs --dent --mb <name> --nid <nid> [--idx <index>] 
--val <value> inject dentry\n");
+       MSG(0, "inject.f2fs --dent --mb <name> --nid <nid> [--dots <1|2>] 
--val/str <value/string> inject dentry\n");
+       MSG(0, "[dots]:\n");
+       MSG(0, "  1: inject \".\" in directory which is specified by nid\n");
+       MSG(0, "  2: inject \"..\" in directory which is specified by nid\n");
        MSG(0, "[mb]:\n");
        MSG(0, "  d_bitmap: inject dentry block d_bitmap of nid\n");
        MSG(0, "  d_hash: inject dentry hash\n");
        MSG(0, "  d_ino: inject dentry ino\n");
        MSG(0, "  d_ftype: inject dentry ftype\n");
+       MSG(0, "  filename: inject dentry filename, its hash and len are 
updated implicitly\n");
 }
 
 int inject_parse_options(int argc, char *argv[], struct inject_option *opt)
@@ -240,6 +244,7 @@ int inject_parse_options(int argc, char *argv[], struct 
inject_option *opt)
                {"ssa", no_argument, 0, 12},
                {"node", no_argument, 0, 13},
                {"dent", no_argument, 0, 14},
+               {"dots", required_argument, 0, 15},
                {0, 0, 0, 0}
        };
 
@@ -336,6 +341,14 @@ int inject_parse_options(int argc, char *argv[], struct 
inject_option *opt)
                        opt->dent = true;
                        MSG(0, "Info: inject dentry\n");
                        break;
+               case 15:
+                       opt->dots = atoi(optarg);
+                       if (opt->dots != TYPE_DOT &&
+                           opt->dots != TYPE_DOTDOT)
+                               return -ERANGE;
+                       MSG(0, "Info: inject %s dentry\n",
+                           opt->dots == TYPE_DOT ? "dot" : "dotdot");
+                       break;
                case 'd':
                        if (optarg[0] == '-' || !is_digits(optarg))
                                return EWRONG_OPT;
@@ -368,6 +381,9 @@ int inject_parse_options(int argc, char *argv[], struct 
inject_option *opt)
                        } else if (opt->dent) {
                                inject_dent_usage();
                                exit(0);
+                       } else {
+                               MSG(0, "\tError: Wrong option -%c (%d) %s\n",
+                                       o, o, optarg);
                        }
                        return EUNKNOWN_OPT;
                }
@@ -1056,12 +1072,12 @@ static int find_dir_entry(struct f2fs_dentry_ptr *d, 
nid_t ino)
                }
 
                de = &d->dentry[slot];
-               if (le32_to_cpu(de->ino) == ino && de->hash_code != 0)
-                       return slot;
                if (de->name_len == 0) {
                        slot++;
                        continue;
                }
+               if (le32_to_cpu(de->ino) == ino)
+                       return slot;
                slot += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
        }
 
@@ -1074,14 +1090,15 @@ static int inject_dentry(struct f2fs_sb_info *sbi, 
struct inject_option *opt)
        struct f2fs_node *node_blk = NULL;
        struct f2fs_inode *inode;
        struct f2fs_dentry_ptr d;
-       void *inline_dentry;
+       void *buf = NULL, *inline_dentry;
        struct f2fs_dentry_block *dent_blk = NULL;
        block_t addr = 0;
-       void *buf = NULL;
        struct f2fs_dir_entry *dent = NULL;
        struct dnode_of_data dn;
        nid_t pino;
-       int slot = -ENOENT, ret;
+       int slot = -ENOENT, namelen, namecap, ret;
+       unsigned int dentry_hash;
+       char *name;
 
        node_blk = malloc(F2FS_BLKSIZE);
        ASSERT(node_blk != NULL);
@@ -1090,12 +1107,25 @@ static int inject_dentry(struct f2fs_sb_info *sbi, 
struct inject_option *opt)
        get_node_info(sbi, opt->nid, &ni);
        ret = dev_read_block(node_blk, ni.blk_addr);
        ASSERT(ret >= 0);
-       pino = le32_to_cpu(node_blk->i.i_pino);
 
-       /* get parent inode */
-       get_node_info(sbi, pino, &ni);
-       ret = dev_read_block(node_blk, ni.blk_addr);
-       ASSERT(ret >= 0);
+       if (opt->dots) {
+               if (!LINUX_S_ISDIR(le16_to_cpu(node_blk->i.i_mode))) {
+                       ERR_MSG("ino %u is not a directory, cannot inject "
+                               "its %s\n", opt->nid,
+                               opt->dots == TYPE_DOT ? "." : "..");
+                       ret = -EINVAL;
+                       goto out;
+               }
+               /* pino is itself */
+               pino = opt->nid;
+       } else {
+               pino = le32_to_cpu(node_blk->i.i_pino);
+
+               /* get parent inode */
+               get_node_info(sbi, pino, &ni);
+               ret = dev_read_block(node_blk, ni.blk_addr);
+               ASSERT(ret >= 0);
+       }
        inode = &node_blk->i;
 
        /* find child dentry */
@@ -1105,7 +1135,10 @@ static int inject_dentry(struct f2fs_sb_info *sbi, 
struct inject_option *opt)
                addr = ni.blk_addr;
                buf = node_blk;
 
-               slot = find_dir_entry(&d, opt->nid);
+               if (opt->dots == TYPE_DOTDOT)
+                       slot = find_dir_entry(&d, 
le32_to_cpu(node_blk->i.i_pino));
+               else
+                       slot = find_dir_entry(&d, opt->nid);
                if (slot >= 0)
                        dent = &d.dentry[slot];
        } else {
@@ -1141,7 +1174,10 @@ static int inject_dentry(struct f2fs_sb_info *sbi, 
struct inject_option *opt)
                        ASSERT(ret >= 0);
 
                        make_dentry_ptr(&d, node_blk, dent_blk, 1);
-                       slot = find_dir_entry(&d, opt->nid);
+                       if (opt->dots == TYPE_DOTDOT)
+                               slot = find_dir_entry(&d, 
le32_to_cpu(node_blk->i.i_pino));
+                       else
+                               slot = find_dir_entry(&d, opt->nid);
                        if (slot >= 0) {
                                dent = &d.dentry[slot];
                                buf = dent_blk;
@@ -1175,6 +1211,36 @@ static int inject_dentry(struct f2fs_sb_info *sbi, 
struct inject_option *opt)
                    "%d -> %d\n", opt->nid, dent->file_type,
                    (u8)opt->val);
                dent->file_type = (u8)opt->val;
+       } else if (!strcmp(opt->mb, "filename")) {
+               if (!opt->str) {
+                       ERR_MSG("option str is needed\n");
+                       ret = -EINVAL;
+                       goto out;
+               }
+               namecap = ALIGN_UP(le16_to_cpu(dent->name_len), F2FS_SLOT_LEN);
+               namelen = strlen(opt->str);
+               if (namelen > namecap) {
+                       ERR_MSG("option str too long\n");
+                       ret = -EINVAL;
+                       goto out;
+               }
+               name = (char *)d.filename[slot];
+               MSG(0, "Info: inject dentry filename of nid %u: "
+                   "%.*s -> %s\n", opt->nid, le16_to_cpu(dent->name_len),
+                   name, opt->str);
+               memcpy(name, opt->str, namelen);
+               MSG(0, "Info: inject dentry namelen of nid %u: "
+                   "%d -> %d\n", opt->nid, le16_to_cpu(dent->name_len),
+                   namelen);
+               dent->name_len = cpu_to_le16(namelen);
+               dentry_hash = f2fs_dentry_hash(get_encoding(sbi),
+                                               IS_CASEFOLDED(inode),
+                                               (unsigned char *)name,
+                                               namelen);
+               MSG(0, "Info: inject dentry d_hash of nid %u: "
+                   "0x%x -> 0x%x\n", opt->nid, le32_to_cpu(dent->hash_code),
+                   dentry_hash);
+               dent->hash_code = cpu_to_le32(dentry_hash);
        } else {
                ERR_MSG("unknown or unsupported member \"%s\"\n", opt->mb);
                ret = -EINVAL;
diff --git a/fsck/inject.h b/fsck/inject.h
index 43c21b56a7eb..706a211bc645 100644
--- a/fsck/inject.h
+++ b/fsck/inject.h
@@ -30,6 +30,7 @@ struct inject_option {
        int cp;                 /* which cp */
        int nat;                /* which nat pack */
        int sit;                /* which sit pack */
+       int dots;               /* . or .. dentry */
        bool ssa;
        bool node;
        bool dent;
diff --git a/man/inject.f2fs.8 b/man/inject.f2fs.8
index 691a40c889a0..3db3f4ecf85e 100644
--- a/man/inject.f2fs.8
+++ b/man/inject.f2fs.8
@@ -211,12 +211,20 @@ inode i_nid array specified by \fIidx\fP.
 .RE
 .TP
 .BI \-\-dent
-Inject dentry block or dir entry specified \fInid\fP.
+Inject dentry block or dir entry specified by \fInid\fP.
+.RS 1.2i
+.TP
+.BI \-\-dots " 1 or 2"
+The option means the "." or ".." directory entry of \fInid\fP is going to be 
injected.
+.RE
+.TP
+.BI ""
 The available \fImb\fP of \fIdent\fP are:
 .RS 1.2i
 .TP
 .BI d_bitmap
 dentry block d_bitmap.
+dentry block d_bitmap.
 .TP
 .BI d_hash
 dentry hash.
@@ -226,6 +234,9 @@ dentry ino.
 .TP
 .BI d_ftype
 dentry ftype.
+.TP
+.BI filename
+dentry filename, and corresponding d_hash and namelen are updated implicitly.
 .RE
 .TP
 .BI \-\-dry\-run
-- 
2.40.1



_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to