/** * @brief Create a hardlink. * * @param dir_hdl Handle of the target object. * @param gpfs_fh Pointer to the directory handle where hardlink is to be created. * @param linkname Pointer to the name of the hardlink to be created. * @param op_ctx Authentication context for the operation (user,...). * @return ERR_FSAL_NO_ERROR on success, error otherwise * */ fsal_status_t GPFSFSAL_link(struct fsal_obj_handle *dir_hdl, struct gpfs_file_handle *gpfs_fh, const char *linkname, const struct req_op_context *op_ctx) { struct gpfs_filesystem *gpfs_fs; fsal_status_t status; struct gpfs_fsal_obj_handle *dest_dir; /* note : fsal_attr is optional. */ if (!dir_hdl || !gpfs_fh || !op_ctx || !linkname) return fsalstat(ERR_FSAL_FAULT, 0); dest_dir = container_of(dir_hdl, struct gpfs_fsal_obj_handle, obj_handle); gpfs_fs = dir_hdl->fs->private_data; /* Tests if hardlinking is allowed by configuration. */ if (!op_ctx->fsal_export->exp_ops. fs_supports(op_ctx->fsal_export, fso_link_support)) return fsalstat(ERR_FSAL_NOTSUPP, 0); /* Create the link on the filesystem */ fsal_set_credentials(op_ctx->creds); status = fsal_internal_link_fh(gpfs_fs->root_fd, gpfs_fh, dest_dir->handle, linkname); fsal_restore_ganesha_credentials(); return status; }
/** * FSAL_link: * Create a hardlink. * * \param target_handle (input): * Handle of the target object. * \param dir_handle (input): * Pointer to the directory handle where * the hardlink is to be created. * \param p_link_name (input): * Pointer to the name of the hardlink to be created. * \param cred (input): * Authentication context for the operation (user,...). * \param accessmode (input): * Mode for the directory to be created. * (the umask defined into the FSAL configuration file * will be applied on it). * \param attributes (optionnal input/output): * The post_operation attributes of the linked object. * 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 GPFSFSAL_link(fsal_handle_t * p_target_handle, /* IN */ fsal_handle_t * p_dir_handle, /* IN */ fsal_name_t * p_link_name, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_attrib_list_t * p_attributes /* [ IN/OUT ] */ ) { fsal_status_t status; fsal_accessflags_t access_mask = 0; fsal_attrib_list_t parent_dir_attrs; /* sanity checks. * note : attributes is optional. */ if(!p_target_handle || !p_dir_handle || !p_context || !p_context->export_context || !p_link_name || !p_link_name->name) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_link); /* Tests if hardlinking is allowed by configuration. */ if(!global_fs_info.link_support) Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_link); /* retrieve target directory metadata */ parent_dir_attrs.asked_attributes = GPFS_SUPPORTED_ATTRIBUTES; status = GPFSFSAL_getattrs(p_dir_handle, p_context, &parent_dir_attrs); if(FSAL_IS_ERROR(status)) goto out_status_fsal_err; /* check permission on target directory */ /* Set both mode and ace4 mask */ access_mask = FSAL_MODE_MASK_SET(FSAL_W_OK | FSAL_X_OK) | FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_ADD_FILE); if(!p_context->export_context->fe_static_fs_info->accesscheck_support) status = fsal_internal_testAccess(p_context, access_mask, NULL, &parent_dir_attrs); else status = fsal_internal_access(p_context, p_dir_handle, access_mask, &parent_dir_attrs); if(FSAL_IS_ERROR(status)) goto out_status_fsal_err; /* Create the link on the filesystem */ TakeTokenFSCall(); status = fsal_internal_link_fh(p_context, p_target_handle, p_dir_handle, p_link_name); ReleaseTokenFSCall(); if(FSAL_IS_ERROR(status)) goto out_status_fsal_err; /* optionnaly get attributes */ if(p_attributes) { status = GPFSFSAL_getattrs(p_target_handle, p_context, p_attributes); /* on error, we set a special bit in the mask. */ if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(p_attributes->asked_attributes); FSAL_SET_MASK(p_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } /* OK */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_link); out_status_fsal_err: ReturnStatus(status, INDEX_FSAL_link); }