static void serve_readlink(fuse_req_t req, fuse_ino_t ino) { Dprintf("%s(ino = %lu)\n", __FUNCTION__, ino); bool symlink_supported = feature_supported(reqcfs(req), FSTITCH_FEATURE_SYMLINK); char link_name[PATH_MAX + 1]; int r; if (!symlink_supported) { r = fuse_reply_err(req, ENOSYS); fuse_reply_assert(!r); return; } r = CALL(reqcfs(req), get_metadata, fusecfsino(req, ino), FSTITCH_FEATURE_SYMLINK, sizeof(link_name) - 1, link_name); if (r < 0) { r = fuse_reply_err(req, -r); fuse_reply_assert(!r); return; } link_name[r] = '\0'; r = fuse_reply_readlink(req, link_name); fuse_reply_assert(!r); }
static int zfsfuse_readlink(fuse_req_t req, fuse_ino_t ino) { vfs_t *vfs = (vfs_t *) fuse_req_userdata(req); zfsvfs_t *zfsvfs = vfs->vfs_data; ZFS_ENTER(zfsvfs); znode_t *znode; int error = zfs_zget(zfsvfs, ino, &znode, B_FALSE); if(error) { ZFS_EXIT(zfsvfs); /* If the inode we are trying to get was recently deleted dnode_hold_impl will return EEXIST instead of ENOENT */ return error == EEXIST ? ENOENT : error; } ASSERT(znode != NULL); vnode_t *vp = ZTOV(znode); ASSERT(vp != NULL); char buffer[PATH_MAX + 1]; iovec_t iovec; uio_t uio; uio.uio_iov = &iovec; uio.uio_iovcnt = 1; uio.uio_segflg = UIO_SYSSPACE; uio.uio_fmode = 0; uio.uio_llimit = RLIM64_INFINITY; iovec.iov_base = buffer; iovec.iov_len = sizeof(buffer) - 1; uio.uio_resid = iovec.iov_len; uio.uio_loffset = 0; cred_t cred; zfsfuse_getcred(req, &cred); error = VOP_READLINK(vp, &uio, &cred, NULL); VN_RELE(vp); ZFS_EXIT(zfsvfs); if(!error) { VERIFY(uio.uio_loffset < sizeof(buffer)); buffer[uio.uio_loffset] = '\0'; fuse_reply_readlink(req, buffer); } return error; }
static void lo_readlink(fuse_req_t req, fuse_ino_t ino) { char buf[PATH_MAX + 1]; int res; res = readlinkat(lo_fd(req, ino), "", buf, sizeof(buf)); if (res == -1) return (void) fuse_reply_err(req, errno); if (res == sizeof(buf)) return (void) fuse_reply_err(req, ENAMETOOLONG); buf[res] = '\0'; fuse_reply_readlink(req, buf); }
static void sqfs_ll_op_readlink(fuse_req_t req, fuse_ino_t ino) { char *dst; size_t size; sqfs_ll_i lli; if (sqfs_ll_iget(req, &lli, ino)) return; if (!S_ISLNK(lli.inode.base.mode)) { fuse_reply_err(req, EINVAL); } else if (sqfs_readlink(&lli.ll->fs, &lli.inode, NULL, &size)) { fuse_reply_err(req, EIO); } else if (!(dst = malloc(size))) { fuse_reply_err(req, ENOMEM); } else if (sqfs_readlink(&lli.ll->fs, &lli.inode, dst, &size)) { fuse_reply_err(req, EIO); free(dst); } else { fuse_reply_readlink(req, dst); free(dst); } }
static void workspace_nfs_readlink(fuse_req_t req, struct entry_struct *entry, struct call_info_struct *call_info) { struct resource_struct *resource=call_info->object->resource; struct net_nfs_export_struct *nfs_export=(struct net_nfs_export_struct *) resource->data; struct nfs_context *nfs_ctx=(struct nfs_context *) nfs_export->data; char *path=call_info->pathinfo.path + call_info->relpath; int result=0; int len=512; char buffer[len]; if (strlen(path)==0) path=(char *) rootpath; logoutput("workspace_nfs_readlink, path %s", path); /* TODO: make this buffer variable, only how to correct that? what error gives nfs_readlink back when buffer is too small? */ pthread_mutex_lock(&nfs_export->mutex); result=nfs_readlink(nfs_ctx, path, buffer, len); pthread_mutex_unlock(&nfs_export->mutex); if (result<0) { logoutput("workspace_nfs_readlink, error reading readlink of %s, error %i:%s", path, abs(result), nfs_get_error(nfs_ctx)); fuse_reply_err(req, abs(result)); } else { fuse_reply_readlink(req, buffer); } free_path_pathinfo(&call_info->pathinfo); }
void hsx_fuse_readlink(fuse_req_t req, fuse_ino_t ino) { int st = 0; int err = 0; struct hsfs_inode *hi = NULL; struct hsfs_super *hi_sb = NULL; char *link = NULL; DEBUG_IN("%s\n","THE HSX_FUSE_READLINK."); hi_sb = fuse_req_userdata(req); if(!hi_sb){ ERR("%s gets inode->sb fails \n", progname); err = ENOENT; goto out; } hi = hsfs_ilookup(hi_sb, ino); if(!hi){ ERR("%s gets inode fails \n", progname); err = ENOENT; goto out; } st = hsi_nfs3_readlink(hi,&link); if(st != 0){ err = st; goto out; } fuse_reply_readlink(req, link); out: if(link != NULL){ free(link); } if(st != 0){ fuse_reply_err(req, err); } DEBUG_OUT(" WITH ERRNO %d\n", err); return; }
static void overlay_readlink(fuse_req_t req, struct entry_struct *entry, struct call_info_struct *call_info) { struct resource_struct *resource=call_info->object->resource; struct localfile_struct *localfile=(struct localfile_struct *) resource->data; struct pathinfo_struct *pathinfo=&call_info->pathinfo; unsigned int len0=pathinfo->len - call_info->relpath, len1=localfile->pathinfo.len; char path[len0 + len1 + 1]; char *buff=NULL; size_t size=512; unsigned int error=0; memcpy(path, localfile->pathinfo.path, len1); if (len0>0) { memcpy(path+len1, pathinfo->path + call_info->relpath, len0); len1+=len0; } path[len1]='\0'; logoutput("overlayfs_readlink: path %s", call_info->pathinfo.path); while(size<=PATH_MAX) { ssize_t lenread=0; if (buff) { buff = realloc(buff, size); } else { buff = malloc(size); } if ( buff ) { if ((lenread=readlink(path, buff, size))==-1) { error=errno; free(buff); goto out; } if (lenread < size) { /* success */ buff[lenread] = '\0'; fuse_reply_readlink(req, buff); free(buff); free_path_pathinfo(&call_info->pathinfo); return; } size+=512; if (size>PATH_MAX) { error=ENAMETOOLONG; break; } } else { error=ENOMEM; break; } } out: logoutput("overlayfs_readlink: error %i", error); fuse_reply_err(req, error); free_path_pathinfo(&call_info->pathinfo); }