]> git.neil.brown.name Git - lafs-utils.git/commitdiff
Add support for internal path lookup
authorNeilBrown <neilb@suse.de>
Mon, 21 Mar 2011 02:37:05 +0000 (13:37 +1100)
committerNeilBrown <neilb@suse.de>
Mon, 21 Mar 2011 02:37:05 +0000 (13:37 +1100)
Also auto-completion of 'internal' path names.

Signed-off-by: NeilBrown <neilb@suse.de>
include/lafs/lafs.h
lib/lafs_dir_lookup.c [new file with mode: 0644]
lib/lafs_lookup_path.c [new file with mode: 0644]
tools/lafs.c

index 6e5f3c5fd96532495e8dadef100098f94ffb3a6b..926c13f6afb312ebe03e287acec650662ddc4e5a 100644 (file)
@@ -92,6 +92,9 @@ uint64_t lafs_leaf_lookup(unsigned char *buf, int len, u32 startaddr,
                          u32 target, u32 *nextp);
 struct lafs_iblk *lafs_leaf_find(struct lafs_ino *inode,
                                 u32 addr, int adopt, u32 *next);
+u32 lafs_dir_lookup(struct lafs_ino *dir, char *name, int len);
+struct lafs_ino *lafs_lookup_path(struct lafs_ino *root, struct lafs_ino *cwd,
+                                 char *path);
 
 
 
diff --git a/lib/lafs_dir_lookup.c b/lib/lafs_dir_lookup.c
new file mode 100644 (file)
index 0000000..c8b0796
--- /dev/null
@@ -0,0 +1,40 @@
+#include <string.h>
+#include <lafs/lafs.h>
+#include "internal.h"
+
+u32 lafs_dir_lookup(struct lafs_ino *dir, char *name, int len)
+{
+       /* lookup a name and return ino number, or 0 if not found */
+       struct lafs_dblk *db;
+       u32 hash;
+
+       hash = lafs_hash_name(dir->md.file.seed, len, name);
+
+       while (1) {
+               u32 bnum;
+               int found;
+               u8 piece;
+               struct dir_ent de;
+               bnum = lafs_find_next(dir, hash+1);
+               if (bnum == LAFS_NOBLOCK)
+                       bnum = 0;
+
+               db = lafs_dblk(dir, bnum);
+               if (!db ||
+                   lafs_load_dblk(db))
+                       return 0;
+
+               found = lafs_dir_find(db->b.data, dir->fs->blockbits-8,
+                                     dir->md.file.seed,
+                                     hash, &piece);
+               if (!found)
+                       return 0;
+               lafs_dir_extract(db->b.data, dir->fs->blockbits-8,
+                                &de, piece, NULL);
+               if (de.target &&
+                   de.nlen == len &&
+                   strncmp(de.name, name, len) == 0)
+                       return de.target;
+               hash++;
+       }
+}
diff --git a/lib/lafs_lookup_path.c b/lib/lafs_lookup_path.c
new file mode 100644 (file)
index 0000000..cf29cb6
--- /dev/null
@@ -0,0 +1,30 @@
+#include <lafs/lafs.h>
+
+struct lafs_ino *lafs_lookup_path(struct lafs_ino *root, struct lafs_ino *cwd,
+                                 char *path)
+{
+       if (!path)
+               return cwd;
+       if (*path == '/') {
+               cwd = root;
+               while (*path == '/')
+                       path++;
+       }
+
+       while (cwd && *path) {
+               char *p = path;
+               int len;
+               u32 inum;
+               while (*path && *path != '/')
+                       path++;
+               len = path - p;
+               while (*path == '/')
+                       path++;
+
+               inum = lafs_dir_lookup(cwd, p, len);
+               if (!inum)
+                       return NULL;
+               cwd = lafs_get_inode(cwd->filesys, inum);
+       }
+       return cwd;
+}
index 94f3563e0ec3cebc1c39dd70f7724955d8702370..18c29dbe907826265abde9c8c0e40b8ffe2c85c0 100644 (file)
@@ -52,6 +52,8 @@ struct state {
        int verbose;
 };
 
+static struct state *gen_state;
+
 /* Every command can have arguments, both positional and
  * named.
  * Named arguments are specified with a leading hyphen, though
@@ -390,6 +392,7 @@ static void interact(void)
        asprintf(&hist, "%s/.lafs_history", home);
        read_history(hist);
        
+       gen_state = &st;
        while (!st.done) {
                char *line = readline("LaFS: ");
 
@@ -548,6 +551,49 @@ static char *choice_gen(const char *prefix, int state)
        return NULL;
 }
 
+static char *internal_gen(const char *prefix, int state)
+{
+       static char *cp;
+       static char *pre = NULL;
+       static struct lafs_ino *inode;
+       static u32 index;
+
+       u32 inum;
+       int type;
+       char name[257];
+
+       if (gen_state->lafs->ss.root == 0) {
+               rl_attempted_completion_over = 1;
+               return NULL;
+       }
+       if (state == 0) {
+               if (pre)
+                       free(pre);
+               pre = strdup(prefix);
+               cp = pre + strlen(pre);
+               while (cp > pre && cp[-1] != '/')
+                       cp--;
+               prefix = cp;
+               while (cp > pre && cp[-1] == '/')
+                       cp--;
+               cp[0] = 0;
+               /*pre is the directory, prefix is the component prefix */
+               inode = lafs_get_itable(gen_state->lafs);
+               inode = lafs_get_inode(inode, 2);
+               inode = lafs_lookup_path(inode, inode, pre);
+               index = -1;
+       } else {
+               if (index + 1 == 0) {
+                       rl_attempted_completion_over = 1;
+                       return NULL;
+               }
+       }
+       if (lafs_dir_next(inode, &index, name, &inum, &type) == 1)
+               return strdup(name);
+
+       rl_attempted_completion_over = 1;
+       return NULL;
+}
 /*
  * This is the brains of the completion handler.
  * We parse the line-so-far to determine way options have already
@@ -616,6 +662,9 @@ static char **complete_in_context(const char *prefix, int start, int end)
                        matches = rl_completion_matches(
                                prefix, rl_filename_completion_function);
                        break;
+               case internal:
+                       matches = rl_completion_matches(prefix, internal_gen);
+                       break;
                case choice:
                        gen_options = args[p].options;
                        matches = rl_completion_matches(
@@ -1208,36 +1257,40 @@ static struct args args_show_inode[] = {
 };
 static void c_show_inode(struct state *st, void **args)
 {
-       int ino;
        struct lafs_ino *inode;
        if (!args[2]) {
                printf("show inode: please give file name or inode number\n");
                return;
        }
+       if (st->lafs->ss.root == 0) {
+               printf("show inode: filesytem not ready\n");
+               return;
+       }
+       inode = lafs_get_itable(st->lafs);
        if (args[3]) {
                char *inostr = args[3];
                char *endp;
-               ino = strtoul(inostr, &endp, 10);
+               int ino = strtoul(inostr, &endp, 10);
                if (endp == inostr || *endp) {
                        printf("show inode: %s is not a valid inode number\n",
                               inostr);
                        return;
                }
+               if (ino)
+                       inode = lafs_get_inode(inode, ino);
+               if (!inode)
+                       printf("show inode: cannot find inode %d\n",ino);
        } else {
-               /* For now, path lookup always finds '0' */
-               ino = 0;
-       }
-       if (st->lafs->ss.root == 0) {
-               printf("show inode: filesytem not ready\n");
-               return;
+               char *path = args[2];
+               inode = lafs_get_inode(inode, 2);
+               inode = lafs_lookup_path(inode, inode, path);
+
+               if (!inode) {
+                       printf("show inode: cannot find inode for %s\n", path);
+                       return;
+               }
        }
-       inode = lafs_get_itable(st->lafs);
-       if (ino)
-               inode = lafs_get_inode(inode, ino);
-       if (inode)
-               lafs_print_inode(inode);
-       else
-               printf("show inode: cannot find inode %d\n",ino);
+       lafs_print_inode(inode);
 }
 
 /****** SHOW DEVICE ******/
@@ -1445,6 +1498,7 @@ static void c_ls(struct state *st, void **args)
        u32 inum;
        int type;
        int col;
+       char *path = args[1];
 
        if (st->lafs->ss.root == 0) {
                printf("ls: filesytem not ready\n");
@@ -1452,7 +1506,18 @@ static void c_ls(struct state *st, void **args)
        }
        ino = lafs_get_itable(st->lafs);
        ino = lafs_get_inode(ino, 2);
+       if (path)
+               ino = lafs_lookup_path(ino, ino, path);
 
+       if (!ino) {
+               printf("ls: cannot find inode for %s\n", path?:"/");
+               return;
+       }
+
+       if (ino->type != TypeDir) {
+               printf("ls: %s exists but is not a directory\n", path);
+               return;
+       }
        col = 0;
        while (lafs_dir_next(ino, &index, name, &inum, &type) == 1) {
                if (args[2]) {