Added API to retrieve the full path of a struct dentry
authorDavide Libenzi <dlibenzi@google.com>
Sat, 24 Oct 2015 02:50:43 +0000 (19:50 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 18 Nov 2015 17:54:57 +0000 (09:54 -0800)
Added API to retrieve the full path of a struct dentry.

Signed-off-by: Davide Libenzi <dlibenzi@google.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/include/vfs.h
kern/src/vfs.c

index b3a09b5..276a372 100644 (file)
@@ -255,6 +255,10 @@ struct dentry {
        void                                            *d_fs_info;
 };
 
+/* Checks is a struct dentry pointer if the root.
+ */
+#define DENTRY_IS_ROOT(d) ((d) == (d)->d_parent)
+
 /* not sure yet if we want to call delete when refcnt == 0 (move it to LRU) or
  * when its time to remove it from the dcache. */
 struct dentry_operations {
@@ -430,10 +434,16 @@ extern struct kmem_cache *file_kcache;
 void vfs_init(void);
 void qstr_builder(struct dentry *dentry, char *l_name);
 char *file_name(struct file *file);
+char *dentry_path(struct dentry *dentry, char *path, size_t max_size);
 int path_lookup(char *path, int flags, struct nameidata *nd);
 void path_release(struct nameidata *nd);
 int mount_fs(struct fs_type *fs, char *dev_name, char *path, int flags);
 
+static inline char *file_abs_path(struct file *f, char *path, size_t max_size)
+{
+       return dentry_path(f->f_dentry, path, max_size);
+}
+
 /* Superblock functions */
 struct super_block *get_sb(void);
 void init_sb(struct super_block *sb, struct vfsmount *vmnt,
index feb2f2f..f783e91 100644 (file)
@@ -5,6 +5,7 @@
  * Default implementations and global values for the VFS. */
 
 #include <vfs.h> // keep this first
+#include <ros/errno.h>
 #include <sys/queue.h>
 #include <assert.h>
 #include <stdio.h>
@@ -142,6 +143,39 @@ char *file_name(struct file *file)
        return file->f_dentry->d_name.name;
 }
 
+static int prepend(char **pbuf, size_t *pbuflen, const char *str, size_t len)
+{
+       if (*pbuflen < len)
+               return -ENAMETOOLONG;
+       *pbuflen -= len;
+       *pbuf -= len;
+       memcpy(*pbuf, str, len);
+
+       return 0;
+}
+
+char *dentry_path(struct dentry *dentry, char *path, size_t max_size)
+{
+       size_t csize = max_size;
+       char *path_start = path + max_size, *base;
+
+       if (prepend(&path_start, &csize, "\0", 1) < 0 || csize < 1)
+               return NULL;
+       /* Handle the case that the passed dentry is the root. */
+       base = path_start - 1;
+       *base = '/';
+       while (!DENTRY_IS_ROOT(dentry)) {
+               if (prepend(&path_start, &csize, dentry->d_name.name,
+                                       dentry->d_name.len) < 0 ||
+                       prepend(&path_start, &csize, "/", 1) < 0)
+                       return NULL;
+               base = path_start;
+               dentry = dentry->d_parent;
+       }
+
+       return base;
+}
+
 /* Some issues with this, coupled closely to fs_lookup.
  *
  * Note the use of __dentry_free, instead of kref_put.  In those cases, we don't