diff options
Diffstat (limited to 'drivers/staging/pohmelfs/path_entry.c')
-rw-r--r-- | drivers/staging/pohmelfs/path_entry.c | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/drivers/staging/pohmelfs/path_entry.c b/drivers/staging/pohmelfs/path_entry.c new file mode 100644 index 000000000000..3bad888ced13 --- /dev/null +++ b/drivers/staging/pohmelfs/path_entry.c @@ -0,0 +1,114 @@ +/* + * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/fs.h> +#include <linux/ktime.h> +#include <linux/fs_struct.h> +#include <linux/pagemap.h> +#include <linux/writeback.h> +#include <linux/mount.h> +#include <linux/mm.h> + +#include "netfs.h" + +#define UNHASHED_OBSCURE_STRING_SIZE sizeof(" (deleted)") + +/* + * Create path from root for given inode. + * Path is formed as set of stuctures, containing name of the object + * and its inode data (mode, permissions and so on). + */ +int pohmelfs_construct_path_string(struct pohmelfs_inode *pi, void *data, int len) +{ + struct path path; + struct dentry *d; + char *ptr; + int err = 0, strlen, reduce = 0; + + d = d_find_alias(&pi->vfs_inode); + if (!d) { + printk("%s: no alias, list_empty: %d.\n", __func__, list_empty(&pi->vfs_inode.i_dentry)); + return -ENOENT; + } + + read_lock(¤t->fs->lock); + path.mnt = mntget(current->fs->root.mnt); + read_unlock(¤t->fs->lock); + + path.dentry = d; + + if (!IS_ROOT(d) && d_unhashed(d)) + reduce = 1; + + ptr = d_path(&path, data, len); + if (IS_ERR(ptr)) { + err = PTR_ERR(ptr); + goto out; + } + + if (reduce && len >= UNHASHED_OBSCURE_STRING_SIZE) { + char *end = data + len - UNHASHED_OBSCURE_STRING_SIZE; + *end = '\0'; + } + + strlen = len - (ptr - (char *)data); + memmove(data, ptr, strlen); + ptr = data; + + err = strlen; + + dprintk("%s: dname: '%s', len: %u, maxlen: %u, name: '%s', strlen: %d.\n", + __func__, d->d_name.name, d->d_name.len, len, ptr, strlen); + +out: + dput(d); + mntput(path.mnt); + + return err; +} + +int pohmelfs_path_length(struct pohmelfs_inode *pi) +{ + struct dentry *d, *root, *first; + int len = 1; /* Root slash */ + + first = d = d_find_alias(&pi->vfs_inode); + if (!d) { + dprintk("%s: ino: %llu, mode: %o.\n", __func__, pi->ino, pi->vfs_inode.i_mode); + return -ENOENT; + } + + read_lock(¤t->fs->lock); + root = dget(current->fs->root.dentry); + read_unlock(¤t->fs->lock); + + spin_lock(&dcache_lock); + + if (!IS_ROOT(d) && d_unhashed(d)) + len += UNHASHED_OBSCURE_STRING_SIZE; /* Obscure " (deleted)" string */ + + while (d && d != root && !IS_ROOT(d)) { + len += d->d_name.len + 1; /* Plus slash */ + d = d->d_parent; + } + spin_unlock(&dcache_lock); + + dput(root); + dput(first); + + return len + 1; /* Including zero-byte */ +} |