/** * FSAL_readlink: * Read the content of a symbolic link. * * \param dir_hdl (input): * Handle of the link to be read. * \param p_context (input): * Authentication context for the operation (user,...). * \param p_link_content (output): * Pointer to an fsal path structure where * the link content is to be stored.. * \param link_len (input/output): * In pointer to len of content buff. . Out actual len of content. * \param link_attributes (optionnal input/output): * The post operation attributes of the symlink link. * As input, it defines the attributes that the caller * wants to retrieve (by positioning flags into this structure) * and the output is built considering this input * (it fills the structure according to the flags it contains). * May be NULL. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - Another error code if an error occured. */ fsal_status_t PTFSAL_readlink(struct fsal_obj_handle *dir_hdl, /* IN */ const struct req_op_context *p_context, /* IN */ char *p_link_content, /* OUT */ size_t *link_len, /* IN/OUT */ struct attrlist *p_link_attributes) { /* IN/OUT */ fsal_status_t status; struct pt_fsal_obj_handle *pt_hdl; char link_content_out[PATH_MAX]; /* sanity checks. * note : link_attributes is optional. */ if (!dir_hdl || !p_context || !p_link_content) return fsalstat(ERR_FSAL_FAULT, 0); pt_hdl = container_of(dir_hdl, struct pt_fsal_obj_handle, obj_handle); memset(link_content_out, 0, sizeof(link_content_out)); /* Read the link on the filesystem */ status = fsal_readlink_by_handle(p_context, p_context->fsal_export, pt_hdl->handle, p_link_content, *link_len); if (FSAL_IS_ERROR(status)) return status; /* retrieves object attributes, if asked */ if (p_link_attributes) { status = PTFSAL_getattrs(p_context->fsal_export, p_context, pt_hdl->handle, p_link_attributes); /* On error, we set a flag in the returned attributes */ if (FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(p_link_attributes->mask); FSAL_SET_MASK(p_link_attributes->mask, ATTR_RDATTR_ERR); } } return fsalstat(ERR_FSAL_NO_ERROR, 0); }
/** * @brief Read the content of a symbolic link. * * @param dir_hdl Handle of the link to be read. * @param op_ctx Authentication context for the operation (user,...). * @param link_content Fsal path struct where the link content is to be stored * @param link_len Len of content buff. Out actual len of content. * * @return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - Another error code if an error occured. */ fsal_status_t GPFSFSAL_readlink(struct fsal_obj_handle *dir_hdl, const struct req_op_context *op_ctx, char *link_content, size_t link_len) { struct gpfs_fsal_obj_handle *gpfs_hdl; struct gpfs_fsal_export *exp = container_of(op_ctx->fsal_export, struct gpfs_fsal_export, export); int export_fd = exp->export_fd; gpfs_hdl = container_of(dir_hdl, struct gpfs_fsal_obj_handle, obj_handle); /* Read the link on the filesystem */ return fsal_readlink_by_handle(export_fd, gpfs_hdl->handle, link_content, link_len); }
/** * @brief Read the content of a symbolic link. * * @param dir_hdl Handle of the link to be read. * @param op_ctx Authentication context for the operation (user,...). * @param link_content Fsal path struct where the link content is to be stored * @param link_len Len of content buff. Out actual len of content. * * @return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - Another error code if an error occured. */ fsal_status_t GPFSFSAL_readlink(struct fsal_obj_handle *dir_hdl, const struct req_op_context *op_ctx, char *link_content, size_t *link_len) { struct gpfs_fsal_obj_handle *gpfs_hdl; struct gpfs_filesystem *gpfs_fs; /* note : link_attr is optional. */ if (!dir_hdl || !op_ctx || !link_content) return fsalstat(ERR_FSAL_FAULT, 0); gpfs_hdl = container_of(dir_hdl, struct gpfs_fsal_obj_handle, obj_handle); gpfs_fs = dir_hdl->fs->private_data; /* Read the link on the filesystem */ return fsal_readlink_by_handle(gpfs_fs->root_fd, gpfs_hdl->handle, link_content, link_len); }
/** * @brief create GPFS handle * * @param exp_hdl export handle * @param hdl_desc handle description * @param handle object handle * @return status * * Does what original FSAL_ExpandHandle did (sort of) * returns a ref counted handle to be later used in cache_inode etc. * NOTE! you must release this thing when done with it! * BEWARE! Thanks to some holes in the *AT syscalls implementation, * we cannot get an fd on an AF_UNIX socket, nor reliably on block or * character special devices. Sorry, it just doesn't... * we could if we had the handle of the dir it is in, but this method * is for getting handles off the wire for cache entries that have LRU'd. * Ideas and/or clever hacks are welcome... */ fsal_status_t gpfs_create_handle(struct fsal_export *exp_hdl, struct gsh_buffdesc *hdl_desc, struct fsal_obj_handle **handle, struct attrlist *attrs_out) { int retval = 0; fsal_status_t status; struct gpfs_fsal_obj_handle *hdl; struct gpfs_file_handle *fh; struct attrlist attrib; char *link_content = NULL; ssize_t retlink = PATH_MAX - 1; char link_buff[PATH_MAX]; struct fsal_fsid__ fsid; struct fsal_filesystem *fs; struct gpfs_filesystem *gpfs_fs; *handle = NULL; /* poison it first */ if ((hdl_desc->len > (sizeof(struct gpfs_file_handle)))) return fsalstat(ERR_FSAL_FAULT, 0); fh = alloca(hdl_desc->len); memcpy(fh, hdl_desc->addr, hdl_desc->len); /* struct aligned copy */ gpfs_extract_fsid(fh, &fsid); fs = lookup_fsid(&fsid, GPFS_FSID_TYPE); if (fs == NULL) { LogInfo(COMPONENT_FSAL, "Could not find filesystem for fsid=0x%016"PRIx64 ".0x%016"PRIx64" from handle", fsid.major, fsid.minor); return fsalstat(ERR_FSAL_STALE, ESTALE); } if (fs->fsal != exp_hdl->fsal) { LogInfo(COMPONENT_FSAL, "Non GPFS filesystem fsid=0x%016"PRIx64 ".0x%016"PRIx64" from handle", fsid.major, fsid.minor); return fsalstat(ERR_FSAL_STALE, ESTALE); } gpfs_fs = fs->private_data; fsal_prepare_attrs(&attrib, ATTR_GPFS_ALLOC_HANDLE); if (attrs_out != NULL) attrib.mask |= attrs_out->mask; status = GPFSFSAL_getattrs(exp_hdl, gpfs_fs, op_ctx, fh, &attrib); if (FSAL_IS_ERROR(status)) return status; if (attrib.type == SYMBOLIC_LINK) { /* I could lazy eval this... */ status = fsal_readlink_by_handle(gpfs_fs->root_fd, fh, link_buff, &retlink); if (FSAL_IS_ERROR(status)) return status; if (retlink < 0 || retlink == PATH_MAX) { retval = errno; if (retlink == PATH_MAX) retval = ENAMETOOLONG; return fsalstat(posix2fsal_error(retval), retval); } link_buff[retlink] = '\0'; link_content = link_buff; } hdl = alloc_handle(fh, fs, &attrib, link_content, exp_hdl); if (attrs_out != NULL) { /* Copy the attributes to caller, passing ACL ref. */ fsal_copy_attrs(attrs_out, &attrib, true); } else { /* Done with the attrs */ fsal_release_attrs(&attrib); } *handle = &hdl->obj_handle; return status; }