Beispiel #1
0
/*
 * The inode of symbolic link is different to data stream.
 * The data stream become link name. Unless the LONG_SYMLINK
 * flag is set.
 */
static int
befs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	struct super_block *sb = dentry->d_sb;
	befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
	char *link;
	int res;

	if (befs_ino->i_flags & BEFS_LONG_SYMLINK) {
		befs_data_stream *data = &befs_ino->i_data.ds;
		befs_off_t linklen = data->size;

		befs_debug(sb, "Follow long symlink");

		link = kmalloc(linklen, GFP_NOFS);
		if (link == NULL)
			return -ENOMEM;

		if (befs_read_lsymlink(sb, data, link, linklen) != linklen) {
			kfree(link);
			befs_error(sb, "Failed to read entire long symlink");
			return -EIO;
		}

		res = vfs_follow_link(nd, link);

		kfree(link);
	} else {
		link = befs_ino->i_data.symlink;
		res = vfs_follow_link(nd, link);
	}

	return res;
}
Beispiel #2
0
static int
#endif
InodeOpFollowlink(struct dentry *dentry,  // IN : dentry of symlink
                  struct nameidata *nd)   // OUT: stores result
{
   int ret;
   VMBlockInodeInfo *iinfo;

   if (!dentry) {
      Warning("InodeOpReadlink: invalid args from kernel\n");
      ret = -EINVAL;
      goto out;
   }

   iinfo = INODE_TO_IINFO(dentry->d_inode);
   if (!iinfo) {
      ret = -EINVAL;
      goto out;
   }

   ret = vfs_follow_link(nd, iinfo->name);

out:
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
   return ERR_PTR(ret);
#else
   return ret;
#endif
}
Beispiel #3
0
int smb_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	char *link;
	int result;

	DEBUG1("followlink of %s/%s\n", DENTRY_PATH(dentry));

	result = -ENOMEM;
	link = kmalloc(SMB_MAXNAMELEN + 1, GFP_KERNEL);
	if (!link)
		goto out;

	result = smb_proc_read_link(server_from_dentry(dentry), dentry, link,
				    SMB_MAXNAMELEN);
	if (result < 0 || result >= SMB_MAXNAMELEN)
		goto out_free;
	link[result] = 0;

	result = vfs_follow_link(nd, link);

out_free:
	kfree(link);
out:
	return result;
}
Beispiel #4
0
static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
#endif
{
	unsigned char *alias;
	int ret;
	yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev;

	yaffs_GrossLock(dev);

	alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry));

	yaffs_GrossUnlock(dev);

	if (!alias)
        {
		ret = -ENOMEM;
		goto out;
        }

	ret = vfs_follow_link(nd, alias);
	kfree(alias);
out:
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
	return ERR_PTR (ret);
#else
	return ret;
#endif
}
Beispiel #5
0
/**
 * vxfs_immed_follow_link - follow immed symlink
 * @dp:		dentry for the link
 * @np:		pathname lookup data for the current path walk
 *
 * Description:
 *   vxfs_immed_follow_link restarts the pathname lookup with
 *   the data obtained from @dp.
 *
 * Returns:
 *   Zero on success, else a negative error code.
 */
static int
vxfs_immed_follow_link(struct dentry *dp, struct nameidata *np)
{
    struct vxfs_inode_info		*vip = VXFS_INO(dp->d_inode);

    return (vfs_follow_link(np, vip->vii_immed.vi_immed));
}
Beispiel #6
0
static void *ocfs2_follow_link(struct dentry *dentry,
			       struct nameidata *nd)
{
	int status;
	char *link;
	struct inode *inode = dentry->d_inode;
	struct page *page = NULL;
	struct buffer_head *bh = NULL;
	
	if (ocfs2_inode_is_fast_symlink(inode))
		link = ocfs2_fast_symlink_getlink(inode, &bh);
	else
		link = ocfs2_page_getlink(dentry, &page);
	if (IS_ERR(link)) {
		status = PTR_ERR(link);
		mlog_errno(status);
		goto bail;
	}

	status = vfs_follow_link(nd, link);

bail:
	if (page) {
		kunmap(page);
		page_cache_release(page);
	}
	brelse(bh);

	return ERR_PTR(status);
}
Beispiel #7
0
static int fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	int ret;
	char *link;

	link = read_link(dentry);
	ret = vfs_follow_link(nd, link);
	free_link(link);
	return ret;
}
Beispiel #8
0
int
#endif
vnode_iop_follow_link(
    DENT_T *dentry,            /* link */
    struct nameidata *nd       /* link resolution */
)
{
    INODE_T *ip;
    struct uio uio;
    iovec_t iov;
    int err = 0;
    char *buf = KMEM_ALLOC(PATH_MAX, KM_SLEEP);
    CALL_DATA_T cd;

    if (buf == NULL)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
        return ERR_PTR(-ENOMEM);
#else
        return -ENOMEM;
#endif
    uio.uio_iov = &iov;
    mfs_uioset(&uio, buf, PATH_MAX-1, 0, UIO_SYSSPACE);

    mdki_linux_init_call_data(&cd);
    ip = dentry->d_inode;

    ASSERT_KERNEL_UNLOCKED();
    ASSERT_I_SEM_NOT_MINE(ip);

    err = VOP_READLINK(ITOV(ip), &uio, &cd);
    err = mdki_errno_unix_to_linux(err);
    mdki_linux_destroy_call_data(&cd);
    if (err == 0) {
        if (uio.uio_resid == 0)
            err = -ENAMETOOLONG;
        else {
            /* readlink doesn't copy a NUL at the end, we must do it */
            buf[uio.uio_offset] = '\0';
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)
            /* follow the link */
            err = vfs_follow_link(nd, buf);
#else
            nd_set_link(nd, buf);
            return(buf); /* vnop_iop_put_link() will free this buf. */
#endif
        }
    }
    KMEM_FREE(buf, PATH_MAX);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
    return ERR_PTR(err);
#else
    return(err);
#endif
}
Beispiel #9
0
int jffs2_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	unsigned char *buf;
	int ret;

	buf = jffs2_getlink(JFFS2_SB_INFO(dentry->d_inode->i_sb), JFFS2_INODE_INFO(dentry->d_inode));

	if (IS_ERR(buf))
		return PTR_ERR(buf);

	ret = vfs_follow_link(nd, buf);
	kfree(buf);
	return ret;
}
Beispiel #10
0
int jffs2_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	unsigned char *buf;
	int ret;

	buf = jffs2_getlink(dentry);

	if (IS_ERR(buf))
		return PTR_ERR(buf);

	ret = vfs_follow_link(nd, buf);
	kfree(buf);
	return ret;
}
Beispiel #11
0
/*
 * careful here - this function can get called recursively, so
 * we need to be very careful about how much stack we use.
 * uio is kmalloced for this reason...
 */
STATIC int
linvfs_follow_link(
	struct dentry		*dentry,
	struct nameidata	*nd)
{
	vnode_t			*vp;
	uio_t			*uio;
	iovec_t			iov;
	int			error;
	char			*link;

	ASSERT(dentry);
	ASSERT(nd);

	link = (char *)kmalloc(MAXNAMELEN+1, GFP_KERNEL);
	if (!link)
		return -ENOMEM;

	uio = (uio_t *)kmalloc(sizeof(uio_t), GFP_KERNEL);
	if (!uio) {
		kfree(link);
		return -ENOMEM;
	}

	vp = LINVFS_GET_VP(dentry->d_inode);

	iov.iov_base = link;
	iov.iov_len = MAXNAMELEN;

	uio->uio_iov = &iov;
	uio->uio_offset = 0;
	uio->uio_segflg = UIO_SYSSPACE;
	uio->uio_resid = MAXNAMELEN;
	uio->uio_iovcnt = 1;

	VOP_READLINK(vp, uio, 0, NULL, error);
	if (error) {
		kfree(uio);
		kfree(link);
		return -error;
	}

	link[MAXNAMELEN - uio->uio_resid] = '\0';
	kfree(uio);

	/* vfs_follow_link returns (-) errors */
	error = vfs_follow_link(nd, link);
	kfree(link);
	return error;
}
Beispiel #12
0
static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
	char array[GFS2_FAST_NAME_SIZE], *buf = array;
	unsigned int len = GFS2_FAST_NAME_SIZE;
	int error;

	error = gfs2_readlinki(ip, &buf, &len);
	if (!error) {
		error = vfs_follow_link(nd, buf);
		if (buf != array)
			kfree(buf);
	}

	return ERR_PTR(error);
}
int sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	int error = 0;
	unsigned long page = get_zeroed_page(GFP_KERNEL);

	if (!page)
		return -ENOMEM;

	error = sysfs_getlink(dentry, (char *) page); 
	if (!error)
	        error = vfs_follow_link(nd, (char *) page);

	free_page(page);

	return error;
}
Beispiel #14
0
static int
HgfsFollowlink(struct dentry *dentry, // IN: Dentry containing link
               struct nameidata *nd)  // OUT: Contains target dentry
#endif
{
   HgfsAttrInfo attr;
   char *fileName = NULL;
   int error;

   ASSERT(dentry);
   ASSERT(nd);

   if (!dentry) {
      LOG(4, (KERN_DEBUG "VMware hgfs: HgfsFollowlink: null input\n"));
      error = -EINVAL;
      goto out;
   }

   LOG(6, (KERN_DEBUG "VMware hgfs: HgfsFollowlink: calling "
           "HgfsPrivateGetattr\n"));
   error = HgfsPrivateGetattr(dentry, &attr, &fileName);
   if (!error) {

      /* Let's make sure we got called on a symlink. */
      if (attr.type != HGFS_FILE_TYPE_SYMLINK || fileName == NULL) {
         LOG(6, (KERN_DEBUG "VMware hgfs: HgfsFollowlink: got called "
                 "on something that wasn't a symlink\n"));
         error = -EINVAL;
      } else {
         LOG(6, (KERN_DEBUG "VMware hgfs: HgfsFollowlink: calling "
                 "vfs_follow_link\n"));
         error = vfs_follow_link(nd, fileName);
      }
      kfree(fileName);
   }
  out:

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
   return ERR_PTR(error);
#else
   return error;
#endif
}
Beispiel #15
0
int
cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
{
	struct inode *inode = direntry->d_inode;
	int rc = -EACCES;
	int xid;
	char *full_path = NULL;
	char * target_path;
	struct cifs_sb_info *cifs_sb;
	struct cifsTconInfo *pTcon;

	xid = GetXid();

	down(&direntry->d_sb->s_vfs_rename_sem);
	full_path = build_path_from_dentry(direntry);
	up(&direntry->d_sb->s_vfs_rename_sem);

	if(full_path == NULL) {
		FreeXid(xid);
		return -ENOMEM;
	}
	cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
	cifs_sb = CIFS_SB(inode->i_sb);
	pTcon = cifs_sb->tcon;
	target_path = kmalloc(PATH_MAX, GFP_KERNEL);
	if(target_path == NULL) {
		if (full_path)
			kfree(full_path);
		FreeXid(xid);
		return -ENOMEM;
	}
	/* can not call the following line due to EFAULT in vfs_readlink which is presumably expecting a user space buffer */
	/* length = cifs_readlink(direntry,target_path, sizeof(target_path) - 1);    */

/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
	if (pTcon->ses->capabilities & CAP_UNIX)
		rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
					     target_path,
					     PATH_MAX-1,
					     cifs_sb->local_nls);
	else {
		/* rc = CIFSSMBQueryReparseLinkInfo */
		/* BB Add code to Query ReparsePoint info */
	}
	/* BB Anything else to do to handle recursive links? */
	/* BB Should we be using page symlink ops here? */

	if (rc == 0) {

/* BB Add special case check for Samba DFS symlinks */

		target_path[PATH_MAX-1] = 0;
		rc = vfs_follow_link(nd, target_path);
	}
	/* else EACCESS */

	if (target_path)
		kfree(target_path);
	if (full_path)
		kfree(full_path);
	FreeXid(xid);
	return rc;
}
Beispiel #16
0
static int ufs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	char *s = (char *)dentry->d_inode->u.ufs_i.i_u1.i_symlink;
	return vfs_follow_link(nd, s);
}
Beispiel #17
0
static int snd_info_card_followlink(struct dentry *dentry,
				    struct nameidata *nd)
{
        char *s = ((struct proc_dir_entry *) dentry->d_inode->u.generic_ip)->data;
        return vfs_follow_link(nd, s);
}
Beispiel #18
0
static int sysv_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	char *s = (char *)SYSV_I(dentry->d_inode)->i_data;
	return vfs_follow_link(nd, s);
}
Beispiel #19
0
/*
 * The follow_link operation is special: it must behave as a no-op
 * so that a bad root inode can at least be unmounted. To do this
 * we must dput() the base and return the dentry with a dget().
 */
static int bad_follow_link(struct dentry *dent, struct nameidata *nd)
{
   return vfs_follow_link(nd, ERR_PTR(-EIO));
}
Beispiel #20
0
static int jfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	char *s = JFS_IP(dentry->d_inode)->i_inline;
	return vfs_follow_link(nd, s);
}
Beispiel #21
0
int
#endif
vnode_shadow_iop_follow_link(
    DENT_T *dentry,            /* entry we are trying to resolve */
    struct nameidata *nd       /* Contains parent dentry */
)
{
    int err = 0;
    int len = PATH_MAX;
    char *buff;
    mm_segment_t old_fs;        /* Because we provide a kernel buffer. */
    INODE_T *real_inode;
    DENT_T *real_dentry;
    VNODE_T *cvp;

    /* this function must consume a reference on base */
    /* We only path_release on error. */

    err = 0;

    real_dentry = REALDENTRY_LOCKED(dentry, &cvp);
    if (real_dentry == NULL) {
	err = -ENOENT;
        MDKI_PATH_RELEASE(nd);
        goto out_nolock;
    }
    VNODE_DGET(real_dentry);             /* protect inode */
    if (real_dentry->d_inode == NULL) {
        /* delete race */
	err = -ENOENT;
        MDKI_PATH_RELEASE(nd);
        goto out;
    }
    real_inode = real_dentry->d_inode;
    /* If there are no underlying symlink functions, we are done */
    if (real_inode->i_op && real_inode->i_op->readlink &&
        real_inode->i_op->follow_link)
    {
        buff = KMEM_ALLOC(len, KM_SLEEP);
        if (!buff) {
            MDKI_PATH_RELEASE(nd);
            err = -ENOMEM;
            goto out;
        }
        /* We're providing a kernel buffer to copy into, so let everyone know. */
        old_fs = get_fs();
        set_fs(KERNEL_DS);
        err = vnode_shadow_iop_readlink(dentry, buff, len);
        set_fs(old_fs);
        if (err < 0) {
            KMEM_FREE(buff, len);
            MDKI_PATH_RELEASE(nd);
            goto out;
        }
        /* done with dentry */
        /* Make sure string is null terminated */
        buff[err] = 0;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)
        err = vfs_follow_link(nd, buff);
        KMEM_FREE(buff,len);
#else
        VNODE_DPUT(real_dentry);
        REALDENTRY_UNLOCK(dentry, cvp);
        nd_set_link(nd, buff);
        return(buff); /* vnop_iop_put_link() will free this buf. */
#endif
    }
out:
    VNODE_DPUT(real_dentry);
    REALDENTRY_UNLOCK(dentry, cvp);
out_nolock:
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
    return ERR_PTR(err);
#else
    return(err);
#endif
}