int vfs_readlink(struct vfs_fsal_obj_handle *myself, fsal_errors_t *fsal_error) { int retval = 0; int fd; ssize_t retlink; struct stat st; int flags = O_PATH | O_NOACCESS | O_NOFOLLOW; if (myself->u.symlink.link_content != NULL) { gsh_free(myself->u.symlink.link_content); myself->u.symlink.link_content = NULL; myself->u.symlink.link_size = 0; } fd = vfs_fsal_open(myself, flags, fsal_error); if (fd < 0) return fd; retval = vfs_stat_by_handle(fd, myself->handle, &st, flags); if (retval < 0) goto error; myself->u.symlink.link_size = st.st_size + 1; myself->u.symlink.link_content = gsh_malloc(myself->u.symlink.link_size); if (myself->u.symlink.link_content == NULL) goto error; retlink = vfs_readlink_by_handle(myself->handle, fd, "", myself->u.symlink.link_content, myself->u.symlink.link_size); if (retlink < 0) goto error; myself->u.symlink.link_content[retlink] = '\0'; close(fd); return retval; error: retval = -errno; *fsal_error = posix2fsal_error(errno); close(fd); if (myself->u.symlink.link_content != NULL) { gsh_free(myself->u.symlink.link_content); myself->u.symlink.link_content = NULL; myself->u.symlink.link_size = 0; } return retval; }
int vfs_readlink(struct vfs_fsal_obj_handle *myself, fsal_errors_t *fsal_error) { int retval = 0; int fd = -1; ssize_t retlink; struct stat st; #ifndef __FreeBSD__ int flags = O_PATH | O_NOACCESS | O_NOFOLLOW; #endif if (myself->u.symlink.link_content != NULL) { gsh_free(myself->u.symlink.link_content); myself->u.symlink.link_content = NULL; myself->u.symlink.link_size = 0; } #ifndef __FreeBSD__ fd = vfs_fsal_open(myself, flags, fsal_error); if (fd < 0) return fd; retval = vfs_stat_by_handle(fd, &st); if (retval < 0) goto error; #else struct fhandle *handle = v_to_fhandle(myself->handle->handle_data); retval = fhstat(handle, &st); if (retval < 0) goto error; #endif myself->u.symlink.link_size = st.st_size + 1; myself->u.symlink.link_content = gsh_malloc(myself->u.symlink.link_size); retlink = vfs_readlink_by_handle(myself->handle, fd, "", myself->u.symlink.link_content, myself->u.symlink.link_size); if (retlink < 0) goto error; myself->u.symlink.link_content[retlink] = '\0'; #ifndef __FreeBSD__ close(fd); #endif return retval; error: retval = -errno; *fsal_error = posix2fsal_error(errno); #ifndef __FreeBSD__ close(fd); #endif if (myself->u.symlink.link_content != NULL) { gsh_free(myself->u.symlink.link_content); myself->u.symlink.link_content = NULL; myself->u.symlink.link_size = 0; } return retval; }
static struct vfs_fsal_obj_handle *alloc_handle(int dirfd, vfs_file_handle_t *fh, struct fsal_filesystem *fs, struct stat *stat, vfs_file_handle_t *dir_fh, const char *path, struct fsal_export *exp_hdl) { struct vfs_fsal_export *myself = container_of(exp_hdl, struct vfs_fsal_export, export); struct vfs_fsal_obj_handle *hdl; fsal_status_t st; hdl = gsh_calloc(1, (sizeof(struct vfs_fsal_obj_handle) + sizeof(vfs_file_handle_t))); if (hdl == NULL) return NULL; hdl->handle = (vfs_file_handle_t *) &hdl[1]; memcpy(hdl->handle, fh, sizeof(vfs_file_handle_t)); hdl->obj_handle.type = posix2fsal_type(stat->st_mode); hdl->dev = posix2fsal_devt(stat->st_dev); hdl->up_ops = exp_hdl->up_ops; hdl->obj_handle.fs = fs; if (hdl->obj_handle.type == REGULAR_FILE) { hdl->u.file.fd = -1; /* no open on this yet */ hdl->u.file.openflags = FSAL_O_CLOSED; } else if (hdl->obj_handle.type == SYMBOLIC_LINK) { ssize_t retlink; size_t len = stat->st_size + 1; char *link_content = gsh_malloc(len); if (link_content == NULL) goto spcerr; retlink = vfs_readlink_by_handle(fh, dirfd, path, link_content, len); if (retlink < 0 || retlink == len) goto spcerr; link_content[retlink] = '\0'; hdl->u.symlink.link_content = link_content; hdl->u.symlink.link_size = len; } else if (vfs_unopenable_type(hdl->obj_handle.type)) { /* AF_UNIX sockets, character special, and block special files require craziness */ if (dir_fh == NULL) { int retval; vfs_alloc_handle(dir_fh); retval = vfs_fd_to_handle(dirfd, hdl->obj_handle.fs, fh); if (retval < 0) goto spcerr; } hdl->u.unopenable.dir = gsh_malloc(sizeof(vfs_file_handle_t)); if (hdl->u.unopenable.dir == NULL) goto spcerr; memcpy(hdl->u.unopenable.dir, dir_fh, sizeof(vfs_file_handle_t)); hdl->u.unopenable.name = gsh_strdup(path); if (hdl->u.unopenable.name == NULL) goto spcerr; } hdl->obj_handle.attributes.mask = exp_hdl->exp_ops.fs_supported_attrs(exp_hdl); st = posix2fsal_attributes(stat, &hdl->obj_handle.attributes); if (FSAL_IS_ERROR(st)) goto spcerr; hdl->obj_handle.attributes.fsid = fs->fsid; fsal_obj_handle_init(&hdl->obj_handle, exp_hdl, posix2fsal_type(stat->st_mode)); vfs_handle_ops_init(&hdl->obj_handle.obj_ops); vfs_sub_init_handle_ops(myself, &hdl->obj_handle.obj_ops); return hdl; spcerr: if (hdl->obj_handle.type == SYMBOLIC_LINK) { if (hdl->u.symlink.link_content != NULL) gsh_free(hdl->u.symlink.link_content); } else if (vfs_unopenable_type(hdl->obj_handle.type)) { if (hdl->u.unopenable.name != NULL) gsh_free(hdl->u.unopenable.name); if (hdl->u.unopenable.dir != NULL) gsh_free(hdl->u.unopenable.dir); } gsh_free(hdl); /* elvis has left the building */ return NULL; }