示例#1
0
static void *
zpl_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	cred_t *cr = CRED();
	struct inode *ip = dentry->d_inode;
	struct iovec iov;
	uio_t uio;
	char *link;
	int error;

	crhold(cr);

	iov.iov_len = MAXPATHLEN;
	iov.iov_base = link = kmem_zalloc(MAXPATHLEN, KM_SLEEP);

	uio.uio_iov = &iov;
	uio.uio_iovcnt = 1;
	uio.uio_resid = (MAXPATHLEN - 1);
	uio.uio_segflg = UIO_SYSSPACE;

	error = -zfs_readlink(ip, &uio, cr);
	if (error) {
		kmem_free(link, MAXPATHLEN);
		nd_set_link(nd, ERR_PTR(error));
	} else {
		nd_set_link(nd, link);
	}

	crfree(cr);
	return (NULL);
}
示例#2
0
static void *
ospfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	ospfs_symlink_inode_t *oi =
		(ospfs_symlink_inode_t *) ospfs_inode(dentry->d_inode->i_ino);

	// check for conditional symlink
	if (strncmp(oi->oi_symlink, "root?", 5) == 0) {
		// find the pivot between first and second paths
		int pivot = strchr(oi->oi_symlink, ':') - oi->oi_symlink;

		// root user
		if (current->uid == 0) {
			// use null-terminator to indicate ending
			oi->oi_symlink[pivot] = '\0';
			nd_set_link(nd, oi->oi_symlink + 5 + 1); // use first path
		}
		// normal user
		else
			nd_set_link(nd, oi->oi_symlink + pivot + 1); // use second path
	}
	else
		nd_set_link(nd, oi->oi_symlink);

	return (void *) 0;
}
示例#3
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 void *
xfs_vn_follow_link(
	struct dentry		*dentry,
	struct nameidata	*nd)
{
	char			*link;
	int			error = -ENOMEM;

	link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
	if (!link)
		goto out_err;

	error = -xfs_readlink(XFS_I(dentry->d_inode), link);
	if (unlikely(error))
		goto out_kfree;

	nd_set_link(nd, link);
	return NULL;

 out_kfree:
	kfree(link);
 out_err:
	nd_set_link(nd, ERR_PTR(error));
	return NULL;
}
示例#4
0
static void *nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	struct inode *inode = dentry->d_inode;
	struct page *page;
	void *err = ERR_PTR(nfs_revalidate_inode(NFS_SERVER(inode), inode));
	if (err)
		goto read_failed;
	page = read_cache_page(&inode->i_data, 0,
				(filler_t *)nfs_symlink_filler, inode);
	if (IS_ERR(page)) {
		err = page;
		goto read_failed;
	}
	if (!PageUptodate(page)) {
		err = ERR_PTR(-EIO);
		goto getlink_read_error;
	}
	nd_set_link(nd, kmap(page));
	return page;

getlink_read_error:
	page_cache_release(page);
read_failed:
	nd_set_link(nd, err);
	return NULL;
}
/*
 * 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 void *
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(MAXPATHLEN+1, GFP_KERNEL);
	if (!link) {
		nd_set_link(nd, ERR_PTR(-ENOMEM));
		return NULL;
	}

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

	vp = LINVFS_GET_VP(dentry->d_inode);

	iov.iov_base = link;
	iov.iov_len = MAXPATHLEN;

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

	VOP_READLINK(vp, uio, 0, NULL, error);
	if (error) {
		kfree(link);
		link = ERR_PTR(-error);
	} else {
		link[MAXPATHLEN - uio->uio_resid] = '\0';
	}
	kfree(uio);

	nd_set_link(nd, link);
	return NULL;
}
示例#6
0
static void *
zpl_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	char *link = NULL;
	int error;

	error = zpl_get_link_common(dentry, dentry->d_inode, &link);
	if (error)
		nd_set_link(nd, ERR_PTR(error));
	else
		nd_set_link(nd, link);

	return (NULL);
}
static void *
v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd)
{
	int retval;
	struct p9_fid *fid;
	char *link = __getname();
	char *target;

	P9_DPRINTK(P9_DEBUG_VFS, "%s\n", dentry->d_name.name);

	if (!link) {
		link = ERR_PTR(-ENOMEM);
		goto ndset;
	}
	fid = v9fs_fid_lookup(dentry);
	if (IS_ERR(fid)) {
		__putname(link);
		link = ERR_CAST(fid);
		goto ndset;
	}
	retval = p9_client_readlink(fid, &target);
	if (!retval) {
		strcpy(link, target);
		kfree(target);
		goto ndset;
	}
	__putname(link);
	link = ERR_PTR(retval);
ndset:
	nd_set_link(nd, link);
	return NULL;
}
示例#8
0
static void
HgfsPutlink(struct dentry *dentry, // dentry
            struct nameidata *nd)  // lookup name information
#endif
{
   char *fileName = NULL;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
   fileName = cookie;
   LOG(6, (KERN_DEBUG "VMware hgfs: %s: put for %s\n",
           __func__, fileName));
#else
   LOG(6, (KERN_DEBUG "VMware hgfs: %s: put for %s\n",
           __func__, dentry->d_name.name));
   fileName = nd_get_link(nd);
#endif
   if (!IS_ERR(fileName)) {
      LOG(6, (KERN_DEBUG "VMware hgfs: %s: putting %s\n",
              __func__, fileName));
      kfree(fileName);
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
      nd_set_link(nd, NULL);
#endif
   }
}
示例#9
0
static int jffs2_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	unsigned char *buf;
	buf = jffs2_getlink(JFFS2_SB_INFO(dentry->d_inode->i_sb), JFFS2_INODE_INFO(dentry->d_inode));
	nd_set_link(nd, buf);
	return 0;
}
示例#10
0
static void *configfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	int error = -ENOMEM;
	unsigned long page = get_zeroed_page(GFP_KERNEL);

	if (page) {
		error = configfs_getlink(dentry, (char *)page);
		if (!error) {
			nd_set_link(nd, (char *)page);
			return (void *)page;
		}
	}

	nd_set_link(nd, ERR_PTR(error));
	return NULL;
}
示例#11
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);
	nd_set_link(np, vip->vii_immed.vi_immed);
	return 0;
}
示例#12
0
static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	char *buf;
	int len = PAGE_SIZE, rc;
	mm_segment_t old_fs;

	/* Released in ecryptfs_put_link(); only release here on error */
	buf = kmalloc(len, GFP_KERNEL);
	if (!buf) {
		buf = ERR_PTR(-ENOMEM);
		goto out;
	}
	old_fs = get_fs();
	set_fs(get_ds());
	rc = dentry->d_inode->i_op->readlink(dentry, (char __user *)buf, len);
	set_fs(old_fs);
	if (rc < 0) {
		kfree(buf);
		buf = ERR_PTR(rc);
	} else
		buf[rc] = '\0';
out:
	nd_set_link(nd, buf);
	return NULL;
}
示例#13
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 void *
vxfs_immed_follow_link(struct dentry *dp, struct nameidata *np)
{
	struct vxfs_inode_info		*vip = VXFS_INO(d_inode(dp));
	nd_set_link(np, vip->vii_immed.vi_immed);
	return NULL;
}
示例#14
0
static void *sf_follow_link(struct dentry *dentry, struct nameidata *nd)
# endif
{
    struct inode *inode = dentry->d_inode;
    struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb);
    struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
    int error = -ENOMEM;
    char *path = (char*)get_zeroed_page(GFP_KERNEL);
    int rc;

    if (path)
    {
        error = 0;
        rc = vboxReadLink(&client_handle, &sf_g->map, sf_i->path, PATH_MAX, path);
        if (RT_FAILURE(rc))
        {
            LogFunc(("vboxReadLink failed, caller=%s, rc=%Rrc\n", __func__, rc));
            free_page((unsigned long)path);
            error = -EPROTO;
        }
    }
# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
    return error ? ERR_PTR(error) : (*cookie = path);
# else
    nd_set_link(nd, error ? ERR_PTR(error) : path);
    return NULL;
# endif
}
static void *
CVE_2011_2928_linux2_6_23_befs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
	char *link;

	if (befs_ino->i_flags & BEFS_LONG_SYMLINK) {
		struct super_block *sb = dentry->d_sb;
		befs_data_stream *data = &befs_ino->i_data.ds;
		befs_off_t len = data->size;

		befs_debug(sb, "Follow long symlink");

		link = kmalloc(len, GFP_NOFS);
		if (!link) {
			link = ERR_PTR(-ENOMEM);
		} else if (befs_read_lsymlink(sb, data, link, len) != len) {
			kfree(link);
			befs_error(sb, "Failed to read entire long symlink");
			link = ERR_PTR(-EIO);
		}
	} else {
		link = befs_ino->i_data.symlink;
	}

	nd_set_link(nd, link);
	return NULL;
}
示例#16
0
static void *
befs_fast_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
	nd_set_link(nd, befs_ino->i_data.symlink);
	return NULL;
}
static void *wrapfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	char *buf;
	int len = PAGE_SIZE, err;
	mm_segment_t old_fs;

	/* This is freed by the put_link method assuming a successful call. */
	buf = kmalloc(len, GFP_KERNEL);
	if (!buf) {
		buf = ERR_PTR(-ENOMEM);
		goto out;
	}

	/* read the symlink, and then we will follow it */
	old_fs = get_fs();
	set_fs(KERNEL_DS);
	err = wrapfs_readlink(dentry, buf, len);
	set_fs(old_fs);
	if (err < 0) {
		kfree(buf);
		buf = ERR_PTR(err);
	} else {
		buf[err] = '\0';
	}
out:
	nd_set_link(nd, buf);
	return NULL;
}
示例#18
0
文件: symlink.c 项目: 383530895/linux
static void *exofs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	struct exofs_i_info *oi = exofs_i(dentry->d_inode);

	nd_set_link(nd, (char *)oi->i_data);
	return NULL;
}
示例#19
0
static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	char *buf;
	int len = PAGE_SIZE, rc;
	mm_segment_t old_fs;

	/* Released in ecryptfs_put_link(); only release here on error */
	buf = kmalloc(len, GFP_KERNEL);
	if (!buf) {
		rc = -ENOMEM;
		goto out;
	}
	old_fs = get_fs();
	set_fs(get_ds());
	ecryptfs_printk(KERN_DEBUG, "Calling readlink w/ "
			"dentry->d_name.name = [%s]\n", dentry->d_name.name);
	rc = dentry->d_inode->i_op->readlink(dentry, (char __user *)buf, len);
	set_fs(old_fs);
	if (rc < 0)
		goto out_free;
	else
		buf[rc] = '\0';
	rc = 0;
	nd_set_link(nd, buf);
	goto out;
out_free:
	kfree(buf);
out:
	return ERR_PTR(rc);
}
示例#20
0
static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode);
	char *p = (char *)f->target;

	/*
	 * We don't acquire the f->sem mutex here since the only data we
	 * use is f->target.
	 *
	 * 1. If we are here the inode has already built and f->target has
	 * to point to the target path.
	 * 2. Nobody uses f->target (if the inode is symlink's inode). The
	 * exception is inode freeing function which frees f->target. But
	 * it can't be called while we are here and before VFS has
	 * stopped using our f->target string which we provide by means of
	 * nd_set_link() call.
	 */

	if (!p) {
		printk(KERN_ERR "jffs2_follow_link(): can't find symlink target\n");
		p = ERR_PTR(-EIO);
	}
	D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->target));

	nd_set_link(nd, p);

	/*
	 * We will unlock the f->sem mutex but VFS will use the f->target string. This is safe
	 * since the only way that may cause f->target to be changed is iput() operation.
	 * But VFS will not use f->target after iput() has been called.
	 */
	return NULL;
}
示例#21
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 void *
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);
	befs_data_stream *data = &befs_ino->i_data.ds;
	befs_off_t len = data->size;
	char *link;

	if (len == 0) {
		befs_error(sb, "Long symlink with illegal length");
		link = ERR_PTR(-EIO);
	} else {
		befs_debug(sb, "Follow long symlink");

		link = kmalloc(len, GFP_NOFS);
		if (!link) {
			link = ERR_PTR(-ENOMEM);
		} else if (befs_read_lsymlink(sb, data, link, len) != len) {
			kfree(link);
			befs_error(sb, "Failed to read entire long symlink");
			link = ERR_PTR(-EIO);
		} else {
			link[len - 1] = '\0';
		}
	}
	nd_set_link(nd, link);
	return NULL;
}
示例#22
0
文件: zpl_inode.c 项目: 10144161/zfs
const char *
zpl_follow_link(struct dentry *dentry, void **symlink_cookie)
#endif
{
	cred_t *cr = CRED();
	struct inode *ip = dentry->d_inode;
	struct iovec iov;
	uio_t uio;
	char *link;
	int error;
	fstrans_cookie_t cookie;

	crhold(cr);

	iov.iov_len = MAXPATHLEN;
	iov.iov_base = link = kmem_zalloc(MAXPATHLEN, KM_SLEEP);

	uio.uio_iov = &iov;
	uio.uio_iovcnt = 1;
	uio.uio_skip = 0;
	uio.uio_resid = (MAXPATHLEN - 1);
	uio.uio_segflg = UIO_SYSSPACE;

	cookie = spl_fstrans_mark();
	error = -zfs_readlink(ip, &uio, cr);
	spl_fstrans_unmark(cookie);

	if (error)
		kmem_free(link, MAXPATHLEN);

	crfree(cr);

#ifdef HAVE_FOLLOW_LINK_NAMEIDATA
	if (error)
		nd_set_link(nd, ERR_PTR(error));
	else
		nd_set_link(nd, link);

	return (NULL);
#else
	if (error)
		return (ERR_PTR(error));
	else
		return (*symlink_cookie = link);
#endif
}
示例#23
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);
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
   ASSERT(nd);
#endif

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

   LOG(6, (KERN_DEBUG "VMware hgfs: %s: calling HgfsPrivateGetattr %s\n",
           __func__, dentry->d_name.name));
   error = HgfsPrivateGetattr(dentry, &attr, &fileName);
   LOG(6, (KERN_DEBUG "VMware hgfs: %s: HgfsPrivateGetattr %s ret %d\n",
           __func__, dentry->d_name.name, error));
   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;
         kfree(fileName);
      } else {
         LOG(6, (KERN_DEBUG "VMware hgfs: %s: calling nd_set_link %s\n",
                 __func__, fileName));
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
         *cookie = fileName;
#else
         nd_set_link(nd, fileName);
#endif
      }
   }

out:
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
   if (!error) {
      return *cookie;
   } else {
      return ERR_PTR(error);
   }
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
   return ERR_PTR(error);
#else
   return error;
#endif
}
示例#24
0
static int sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	int error = -ENOMEM;
	unsigned long page = get_zeroed_page(GFP_KERNEL);
	if (page)
		error = sysfs_getlink(dentry, (char *) page); 
	nd_set_link(nd, error ? ERR_PTR(error) : (char *)page);
	return 0;
}
示例#25
0
void *
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 = ERR_PTR(-ENOMEM);
	struct cifs_sb_info *cifs_sb;
	struct cifsTconInfo *pTcon;

	xid = GetXid();

	full_path = build_path_from_dentry(direntry);

	if (!full_path)
		goto out_no_free;

	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) {
		target_path = ERR_PTR(-ENOMEM);
		goto out;
	}

/* 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 Add MAC style xsymlink check here if enabled */
	}

	if (rc == 0) {

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

		target_path[PATH_MAX-1] = 0;
	} else {
		kfree(target_path);
		target_path = ERR_PTR(rc);
	}

out:
	kfree(full_path);
out_no_free:
	FreeXid(xid);
	nd_set_link(nd, target_path);
	return NULL;	/* No cookie */
}
示例#26
0
文件: link.c 项目: 3bsa/linux
void *
cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
{
	struct inode *inode = d_inode(direntry);
	int rc = -ENOMEM;
	unsigned int xid;
	char *full_path = NULL;
	char *target_path = NULL;
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
	struct tcon_link *tlink = NULL;
	struct cifs_tcon *tcon;
	struct TCP_Server_Info *server;

	xid = get_xid();

	tlink = cifs_sb_tlink(cifs_sb);
	if (IS_ERR(tlink)) {
		rc = PTR_ERR(tlink);
		tlink = NULL;
		goto out;
	}
	tcon = tlink_tcon(tlink);
	server = tcon->ses->server;

	full_path = build_path_from_dentry(direntry);
	if (!full_path)
		goto out;

	cifs_dbg(FYI, "Full path: %s inode = 0x%p\n", full_path, inode);

	rc = -EACCES;
	/*
	 * First try Minshall+French Symlinks, if configured
	 * and fallback to UNIX Extensions Symlinks.
	 */
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
		rc = query_mf_symlink(xid, tcon, cifs_sb, full_path,
				      &target_path);

	if (rc != 0 && server->ops->query_symlink)
		rc = server->ops->query_symlink(xid, tcon, full_path,
						&target_path, cifs_sb);

	kfree(full_path);
out:
	if (rc != 0) {
		kfree(target_path);
		target_path = ERR_PTR(rc);
	}

	free_xid(xid);
	if (tlink)
		cifs_put_tlink(tlink);
	nd_set_link(nd, target_path);
	return NULL;
}
示例#27
0
文件: ospfsmod.c 项目: Saqib117/Lab-3
static void *
ospfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	ospfs_symlink_inode_t *oi =
		(ospfs_symlink_inode_t *) ospfs_inode(dentry->d_inode->i_ino);
	// Exercise: Your code here.

	nd_set_link(nd, oi->oi_symlink);
	return (void *) 0;
}
示例#28
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
}
示例#29
0
static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	int error = -ENOMEM;
	unsigned long page = get_zeroed_page(GFP_KERNEL);
	if (page) {
		error = sysfs_getlink(dentry, (char *) page); 
		if (error < 0)
			free_page((unsigned long)page);
	}
	nd_set_link(nd, error ? ERR_PTR(error) : (char *)page);
	return NULL;
}
示例#30
0
/**
 * \<\<private\>\> Provides symlink resolution. 
 * Supplies the pathname of the target entry that the symlink refers to.
 * This code is adapted from sysfs/symlink.c.
 * - allocates a whole page for the pathname (faster than kmalloc)
 * - extracts the symlink from the dentry
 * - asks the symlink for path resolution
 *
 * @param *dentry - points to the dentry of the symlink that is to be
 * resolved
 * @param *nd - where the pathname is to be stored
 * @return NULL upon success
 */
static void* tcmi_ctlfs_symlink_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	int error = -ENOMEM;
	unsigned long page = get_zeroed_page(GFP_ATOMIC);
	struct tcmi_ctlfs_symlink *symlink;
	if (page) {
		symlink = TCMI_CTLFS_SYMLINK(TCMI_CTLFS_DENTRY_TO_ENTRY(dentry));
		error = tcmi_ctlfs_symlink_get_link(symlink, (char *) page, PAGE_SIZE); 
	}
	nd_set_link(nd, error ? ERR_PTR(error) : (char *)page);
	return NULL;
}