Add --nid and --path options to fsck.erofs to allow users to check
or extract specific sub-directories or files instead of the entire
filesystem.

This is useful for targeted data recovery or verifying specific
image components without the overhead of a full traversal.

Signed-off-by: Inseob Kim <[email protected]>
---
 fsck/main.c | 50 ++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 40 insertions(+), 10 deletions(-)

diff --git a/fsck/main.c b/fsck/main.c
index ab697be..a7d9f46 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -39,6 +39,8 @@ struct erofsfsck_cfg {
        bool preserve_owner;
        bool preserve_perms;
        bool dump_xattrs;
+       erofs_nid_t nid;
+       const char *inode_path;
        bool nosbcrc;
 };
 static struct erofsfsck_cfg fsckcfg;
@@ -59,6 +61,8 @@ static struct option long_options[] = {
        {"offset", required_argument, 0, 12},
        {"xattrs", no_argument, 0, 13},
        {"no-xattrs", no_argument, 0, 14},
+       {"nid", required_argument, 0, 15},
+       {"path", required_argument, 0, 16},
        {"no-sbcrc", no_argument, 0, 512},
        {0, 0, 0, 0},
 };
@@ -110,6 +114,8 @@ static void usage(int argc, char **argv)
                " --extract[=X]          check if all files are well encoded, 
optionally\n"
                "                        extract to X\n"
                " --offset=#             skip # bytes at the beginning of 
IMAGE\n"
+               " --nid=#                check or extract from the target inode 
of nid #\n"
+               " --path=X               check or extract from the target inode 
of path X\n"
                " --no-sbcrc             bypass the superblock checksum 
verification\n"
                " --[no-]xattrs          whether to dump extended attributes 
(default off)\n"
                "\n"
@@ -245,6 +251,12 @@ static int erofsfsck_parse_options_cfg(int argc, char 
**argv)
                case 14:
                        fsckcfg.dump_xattrs = false;
                        break;
+               case 15:
+                       fsckcfg.nid = (erofs_nid_t)atoll(optarg);
+                       break;
+               case 16:
+                       fsckcfg.inode_path = optarg;
+                       break;
                case 512:
                        fsckcfg.nosbcrc = true;
                        break;
@@ -981,7 +993,8 @@ static int erofsfsck_check_inode(erofs_nid_t pnid, 
erofs_nid_t nid)
 
        if (S_ISDIR(inode.i_mode)) {
                struct erofs_dir_context ctx = {
-                       .flags = EROFS_READDIR_VALID_PNID,
+                       .flags = (pnid == nid && nid != g_sbi.root_nid) ?
+                               0 : EROFS_READDIR_VALID_PNID,
                        .pnid = pnid,
                        .dir = &inode,
                        .cb = erofsfsck_dirent_iter,
@@ -1033,6 +1046,8 @@ int main(int argc, char *argv[])
        fsckcfg.preserve_owner = fsckcfg.superuser;
        fsckcfg.preserve_perms = fsckcfg.superuser;
        fsckcfg.dump_xattrs = false;
+       fsckcfg.nid = 0;
+       fsckcfg.inode_path = NULL;
 
        err = erofsfsck_parse_options_cfg(argc, argv);
        if (err) {
@@ -1068,22 +1083,37 @@ int main(int argc, char *argv[])
        if (fsckcfg.extract_path)
                erofsfsck_hardlink_init();
 
-       if (erofs_sb_has_fragments(&g_sbi) && g_sbi.packed_nid > 0) {
-               err = erofs_packedfile_init(&g_sbi, false);
+       if (fsckcfg.inode_path) {
+               struct erofs_inode inode = { .sbi = &g_sbi };
+
+               err = erofs_ilookup(fsckcfg.inode_path, &inode);
                if (err) {
-                       erofs_err("failed to initialize packedfile: %s",
-                                 erofs_strerror(err));
+                       erofs_err("failed to lookup %s", fsckcfg.inode_path);
                        goto exit_hardlink;
                }
+               fsckcfg.nid = inode.nid;
+       } else if (!fsckcfg.nid) {
+               fsckcfg.nid = g_sbi.root_nid;
+       }
 
-               err = erofsfsck_check_inode(g_sbi.packed_nid, g_sbi.packed_nid);
-               if (err) {
-                       erofs_err("failed to verify packed file");
-                       goto exit_packedinode;
+       if (!fsckcfg.inode_path && fsckcfg.nid == g_sbi.root_nid) {
+               if (erofs_sb_has_fragments(&g_sbi) && g_sbi.packed_nid > 0) {
+                       err = erofs_packedfile_init(&g_sbi, false);
+                       if (err) {
+                               erofs_err("failed to initialize packedfile: %s",
+                                         erofs_strerror(err));
+                               goto exit_hardlink;
+                       }
+
+                       err = erofsfsck_check_inode(g_sbi.packed_nid, 
g_sbi.packed_nid);
+                       if (err) {
+                               erofs_err("failed to verify packed file");
+                               goto exit_packedinode;
+                       }
                }
        }
 
-       err = erofsfsck_check_inode(g_sbi.root_nid, g_sbi.root_nid);
+       err = erofsfsck_check_inode(fsckcfg.nid, fsckcfg.nid);
        if (fsckcfg.corrupted) {
                if (!fsckcfg.extract_path)
                        erofs_err("Found some filesystem corruption");
-- 
2.53.0.414.gf7e9f6c205-goog


Reply via email to