static int befs_readlink(struct dentry *dentry, char __user *buffer, int buflen) { 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, "Read 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_readlink(dentry, buffer, buflen, link); kfree(link); } else { link = befs_ino->i_data.symlink; res = vfs_readlink(dentry, buffer, buflen, link); } return res; }
int xfs_readlink_by_handle( struct file *parfilp, xfs_fsop_handlereq_t *hreq) { struct dentry *dentry; __u32 olen; int error; if (!capable(CAP_SYS_ADMIN)) return -EPERM; dentry = xfs_handlereq_to_dentry(parfilp, hreq); if (IS_ERR(dentry)) return PTR_ERR(dentry); /* Restrict this handle operation to symlinks only. */ if (!d_is_symlink(dentry)) { error = -EINVAL; goto out_dput; } if (copy_from_user(&olen, hreq->ohandlen, sizeof(__u32))) { error = -EFAULT; goto out_dput; } error = vfs_readlink(dentry, hreq->ohandle, olen); out_dput: dput(dentry); return error; }
/** * vxfs_immed_readlink - read immed symlink * @dp: dentry for the link * @bp: output buffer * @buflen: length of @bp * * Description: * vxfs_immed_readlink calls vfs_readlink to read the link * described by @dp into userspace. * * Returns: * Number of bytes successfully copied to userspace. */ static int vxfs_immed_readlink(struct dentry *dp, char *bp, int buflen) { struct vxfs_inode_info *vip = VXFS_INO(dp->d_inode); return (vfs_readlink(dp, bp, buflen, vip->vii_immed.vi_immed)); }
static int ocfs2_readlink(struct dentry *dentry, char __user *buffer, int buflen) { int ret; char *link; struct buffer_head *bh = NULL; struct inode *inode = dentry->d_inode; mlog_entry_void(); link = ocfs2_fast_symlink_getlink(inode, &bh); if (IS_ERR(link)) { ret = PTR_ERR(link); goto out; } /* * Without vfsmount we can't update atime now, * but we will update atime here ultimately. */ ret = vfs_readlink(dentry, buffer, buflen, link); brelse(bh); out: mlog_exit(ret); return ret; }
static int ocfs2_readlink(struct dentry *dentry, char __user *buffer, int buflen) { int ret; char *link; struct buffer_head *bh = NULL; struct inode *inode = dentry->d_inode; link = ocfs2_fast_symlink_getlink(inode, &bh); if (IS_ERR(link)) { ret = PTR_ERR(link); goto out; } /* */ ret = vfs_readlink(dentry, buffer, buflen, link); brelse(bh); out: if (ret < 0) mlog_errno(ret); return ret; }
/* * /proc/self: */ static int proc_self_readlink(struct dentry *dentry, char __user *buffer, int buflen) { struct pid_namespace *ns = dentry->d_sb->s_fs_info; pid_t tgid = task_tgid_nr_ns(current, ns); char tmp[PROC_NUMBUF]; if (!tgid) return -ENOENT; sprintf(tmp, "%d", tgid); return vfs_readlink(dentry,buffer,buflen,tmp); }
static int fuse_readlink(struct dentry *dentry, char __user *buffer, int buflen) { int ret; char *link; link = read_link(dentry); ret = vfs_readlink(dentry, buffer, buflen, link); free_link(link); return ret; }
int jffs2_readlink(struct dentry *dentry, char *buffer, int buflen) { unsigned char *kbuf; int ret; kbuf = jffs2_getlink(dentry); if (IS_ERR(kbuf)) return PTR_ERR(kbuf); ret = vfs_readlink(dentry, buffer, buflen, kbuf); kfree(kbuf); return ret; }
int jffs2_readlink(struct dentry *dentry, char *buffer, int buflen) { unsigned char *kbuf; int ret; kbuf = jffs2_getlink(JFFS2_SB_INFO(dentry->d_inode->i_sb), JFFS2_INODE_INFO(dentry->d_inode)); if (IS_ERR(kbuf)) return PTR_ERR(kbuf); ret = vfs_readlink(dentry, buffer, buflen, kbuf); kfree(kbuf); return ret; }
static int hmfs_readlink(struct dentry *dentry, char __user * buffer, int buflen) { struct inode *inode = dentry->d_inode; void *data_blk[1]; int err = 0; int size = 0; err = get_data_blocks(inode, 0, 1, data_blk, &size, RA_DB_END); if (err || size != 1 || data_blk[0] == NULL) return -ENODATA; return vfs_readlink(dentry, buffer, buflen, data_blk[0]); }
static fsal_status_t readsymlink(struct fsal_obj_handle *obj_hdl, struct gsh_buffdesc *link_content, bool refresh) { struct vfs_fsal_obj_handle *myself = NULL; int retval = 0; fsal_errors_t fsal_error = ERR_FSAL_NO_ERROR; if (obj_hdl->type != SYMBOLIC_LINK) { fsal_error = ERR_FSAL_INVAL; goto out; } myself = container_of(obj_hdl, struct vfs_fsal_obj_handle, obj_handle); if (obj_hdl->fsal != obj_hdl->fs->fsal) { LogDebug(COMPONENT_FSAL, "FSAL %s operation for handle belonging to FSAL %s, return EXDEV", obj_hdl->fsal->name, obj_hdl->fs->fsal != NULL ? obj_hdl->fs->fsal->name : "(none)"); retval = EXDEV; goto hdlerr; } if (refresh) { /* lazy load or LRU'd storage */ retval = vfs_readlink(myself, &fsal_error); if (retval < 0) { retval = -retval; goto hdlerr; } } if (myself->u.symlink.link_content == NULL) { fsal_error = ERR_FSAL_FAULT; /* probably a better error?? */ goto out; } link_content->len = myself->u.symlink.link_size; link_content->addr = gsh_malloc(myself->u.symlink.link_size); if (link_content->addr == NULL) { fsal_error = ERR_FSAL_NOMEM; goto out; } memcpy(link_content->addr, myself->u.symlink.link_content, link_content->len); hdlerr: fsal_error = posix2fsal_error(retval); out: return fsalstat(fsal_error, retval); }
int sysfs_readlink(struct dentry *dentry, char __user *buffer, int buflen) { 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_readlink(dentry, buffer, buflen, (char *) page); free_page(page); return error; }
static int snd_info_card_readlink(struct dentry *dentry, char *buffer, int buflen) { char *s = ((struct proc_dir_entry *) dentry->d_inode->u.generic_ip)->data; #ifdef LINUX_2_3 return vfs_readlink(dentry, buffer, buflen, s); #else int len; if (s == NULL) return -EIO; len = strlen(s); if (len > buflen) len = buflen; if (copy_to_user(buffer, s, len)) return -EFAULT; return len; #endif }
static int InodeOpReadlink(struct dentry *dentry, // IN : dentry of symlink char __user *buffer, // OUT: output buffer (user space) int buflen) // IN : length of output buffer { VMBlockInodeInfo *iinfo; if (!dentry || !buffer) { Warning("InodeOpReadlink: invalid args from kernel\n"); return -EINVAL; } iinfo = INODE_TO_IINFO(dentry->d_inode); if (!iinfo) { return -EINVAL; } return vfs_readlink(dentry, buffer, buflen, iinfo->name); }
static int yaffs_readlink(struct dentry *dentry, char __user * buffer, int buflen) { 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) return -ENOMEM; ret = vfs_readlink(dentry, buffer, buflen, alias); kfree(alias); return ret; }
int smb_read_link(struct dentry *dentry, char *buffer, int len) { char *link; int result; DEBUG1("read link buffer len = %d\n", len); 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) goto out_free; result = vfs_readlink(dentry, buffer, len, link); out_free: kfree(link); out: return result; }
static int HgfsReadlink(struct dentry *dentry, // IN: Dentry containing link char __user *buffer, // OUT: User buffer to copy link into int buflen) // IN: Length of user buffer { HgfsAttrInfo attr; char *fileName = NULL; int error; ASSERT(dentry); ASSERT(buffer); if (!dentry) { LOG(4, (KERN_DEBUG "VMware hgfs: HgfsReadlink: null input\n")); return -EINVAL; } LOG(6, (KERN_DEBUG "VMware hgfs: HgfsReadlink: 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: HgfsReadlink: got called " "on something that wasn't a symlink\n")); error = -EINVAL; } else { LOG(6, (KERN_DEBUG "VMware hgfs: HgfsReadlink: calling " "vfs_readlink\n")); error = vfs_readlink(dentry, buffer, buflen, fileName); } kfree(fileName); } return error; }
int cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) { struct inode *inode = direntry->d_inode; int rc = -EACCES; int xid; int oplock = FALSE; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; char *full_path = NULL; char *tmp_path = NULL; char *tmpbuffer; unsigned char *referrals = NULL; unsigned int num_referrals = 0; int len; __u16 fid; xid = GetXid(); cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; /* BB would it be safe against deadlock to grab this sem even though rename itself grabs the sem and calls lookup? */ /* mutex_lock(&inode->i_sb->s_vfs_rename_mutex);*/ full_path = build_path_from_dentry(direntry); /* mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);*/ if (full_path == NULL) { FreeXid(xid); return -ENOMEM; } cFYI(1, ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d", full_path, inode, pBuffer, buflen)); if (buflen > PATH_MAX) len = PATH_MAX; else len = buflen; tmpbuffer = kmalloc(len, GFP_KERNEL); if (tmpbuffer == NULL) { kfree(full_path); FreeXid(xid); return -ENOMEM; } /* BB add read reparse point symlink code and Unix extensions symlink code here BB */ /* We could disable this based on pTcon->unix_ext flag instead ... but why? */ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path, tmpbuffer, len - 1, cifs_sb->local_nls); else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { cERROR(1, ("SFU style symlinks not implemented yet")); /* add open and read as in fs/cifs/inode.c */ } else { rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ, OPEN_REPARSE_POINT, &fid, &oplock, NULL, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (!rc) { rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path, tmpbuffer, len - 1, fid, cifs_sb->local_nls); if (CIFSSMBClose(xid, pTcon, fid)) { cFYI(1, ("Error closing junction point " "(open for ioctl)")); } if (rc == -EIO) { /* Query if DFS Junction */ tmp_path = kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1, GFP_KERNEL); if (tmp_path) { strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); strncat(tmp_path, full_path, MAX_PATHCONF); rc = get_dfs_path(xid, pTcon->ses, tmp_path, cifs_sb->local_nls, &num_referrals, &referrals, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cFYI(1, ("Get DFS for %s rc = %d ", tmp_path, rc)); if ((num_referrals == 0) && (rc == 0)) rc = -EACCES; else { cFYI(1, ("num referral: %d", num_referrals)); if (referrals) { cFYI(1,("referral string: %s", referrals)); strncpy(tmpbuffer, referrals, len-1); } } kfree(referrals); kfree(tmp_path); } /* BB add code like else decode referrals then memcpy to tmpbuffer and free referrals string array BB */ } } } /* BB Anything else to do to handle recursive links? */ /* BB Should we be using page ops here? */ /* BB null terminate returned string in pBuffer? BB */ if (rc == 0) { rc = vfs_readlink(direntry, pBuffer, len, tmpbuffer); cFYI(1, ("vfs_readlink called from cifs_readlink returned %d", rc)); } kfree(tmpbuffer); kfree(full_path); FreeXid(xid); return rc; }
static int jfs_readlink(struct dentry *dentry, char *buffer, int buflen) { char *s = JFS_IP(dentry->d_inode)->i_inline; return vfs_readlink(dentry, buffer, buflen, s); }
int cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) { struct inode *inode = direntry->d_inode; int rc = -EACCES; int xid; int oplock = 0; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; char *full_path = NULL; char *tmpbuffer; int len; __u16 fid; xid = GetXid(); cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; /* BB would it be safe against deadlock to grab this sem even though rename itself grabs the sem and calls lookup? */ /* mutex_lock(&inode->i_sb->s_vfs_rename_mutex);*/ full_path = build_path_from_dentry(direntry); /* mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);*/ if (full_path == NULL) { FreeXid(xid); return -ENOMEM; } cFYI(1, ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d", full_path, inode, pBuffer, buflen)); if (buflen > PATH_MAX) len = PATH_MAX; else len = buflen; tmpbuffer = kmalloc(len, GFP_KERNEL); if (tmpbuffer == NULL) { kfree(full_path); FreeXid(xid); return -ENOMEM; } /* BB add read reparse point symlink code and Unix extensions symlink code here BB */ /* We could disable this based on pTcon->unix_ext flag instead ... but why? */ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path, tmpbuffer, len - 1, cifs_sb->local_nls); else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { cERROR(1, ("SFU style symlinks not implemented yet")); /* add open and read as in fs/cifs/inode.c */ } else { rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ, FILE_SHARE_ALL, OPEN_REPARSE_POINT, &fid, &oplock, NULL, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (!rc) { rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path, tmpbuffer, len - 1, fid, cifs_sb->local_nls); if (CIFSSMBClose(xid, pTcon, fid)) { cFYI(1, ("Error closing junction point " "(open for ioctl)")); } /* If it is a DFS junction earlier we would have gotten PATH_NOT_COVERED returned from server so we do not need to request the DFS info here */ } } /* BB Anything else to do to handle recursive links? */ /* BB Should we be using page ops here? */ /* BB null terminate returned string in pBuffer? BB */ if (rc == 0) { rc = vfs_readlink(direntry, pBuffer, len, tmpbuffer); cFYI(1, ("vfs_readlink called from cifs_readlink returned %d", rc)); } kfree(tmpbuffer); kfree(full_path); FreeXid(xid); return rc; }
SYSCALL_HANDLER3(sys_readlink, const char *path, char *buf, ssize_t *ret) { *ret = vfs_readlink(path, buf, (size_t)*ret); }
static int sysv_readlink(struct dentry *dentry, char *buffer, int buflen) { char *s = (char *)SYSV_I(dentry->d_inode)->i_data; return vfs_readlink(dentry, buffer, buflen, s); }
static int ufs_readlink(struct dentry *dentry, char *buffer, int buflen) { char *s = (char *)dentry->d_inode->u.ufs_i.i_u1.i_symlink; return vfs_readlink(dentry, buffer, buflen, s); }