fsal_status_t ZFSFSAL_symlink(zfsfsal_handle_t * parent_directory_handle, /* IN */ fsal_name_t * p_linkname, /* IN */ fsal_path_t * p_linkcontent, /* IN */ zfsfsal_op_context_t * p_context, /* IN */ fsal_accessmode_t accessmode, /* IN (ignored) */ zfsfsal_handle_t * link_handle, /* OUT */ fsal_attrib_list_t * link_attributes /* [ IN/OUT ] */ ) { int rc; /* sanity checks. * note : link_attributes is optional. */ if(!parent_directory_handle || !p_context || !link_handle || !p_linkname || !p_linkcontent) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_symlink); /* Tests if symlinking is allowed by configuration. */ if(!global_fs_info.symlink_support) Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_symlink); TakeTokenFSCall(); inogen_t object; rc = libzfswrap_symlink(p_context->export_context->p_vfs, &p_context->user_credential.cred, parent_directory_handle->data.zfs_handle, p_linkname->name, p_linkcontent->path, &object); ReleaseTokenFSCall(); /* >> convert status and return on error << */ /* >> set output handle << */ link_handle->data.zfs_handle = object; link_handle->data.type = FSAL_TYPE_LNK; if(link_attributes) { fsal_status_t status = ZFSFSAL_getattrs(link_handle, p_context, link_attributes); /* On error, we set a flag in the returned attributes */ if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(link_attributes->asked_attributes); FSAL_SET_MASK(link_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } /* OK */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_symlink); }
fsal_status_t ZFSFSAL_symlink(fsal_handle_t * parent_directory_handle, /* IN */ fsal_name_t * p_linkname, /* IN */ fsal_path_t * p_linkcontent, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_accessmode_t accessmode, /* IN (ignored) */ fsal_handle_t * link_handle, /* OUT */ fsal_attrib_list_t * link_attributes /* [ IN/OUT ] */ ) { creden_t cred; /* sanity checks. * note : link_attributes is optional. */ if(!parent_directory_handle || !p_context || !link_handle || !p_linkname || !p_linkcontent) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_symlink); /* Tests if symlinking is allowed by configuration. */ if(!global_fs_info.symlink_support) Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_symlink); /* Hook to prevent creation of anything inside the snapshot */ if(((zfsfsal_handle_t *)parent_directory_handle)->data.i_snap != 0) { LogDebug(COMPONENT_FSAL, "Trying to create a symlink inside a snapshot"); Return(ERR_FSAL_ROFS, 0, INDEX_FSAL_symlink); } cred.uid = p_context->credential.user; cred.gid = p_context->credential.group; TakeTokenFSCall(); inogen_t object; libzfswrap_symlink(((zfsfsal_op_context_t *)p_context)->export_context->p_vfs, &cred, ((zfsfsal_handle_t *)parent_directory_handle)->data.zfs_handle, p_linkname->name, p_linkcontent->path, &object); ReleaseTokenFSCall(); /* >> convert status and return on error << */ /* >> set output handle << */ ((zfsfsal_handle_t *)link_handle)->data.zfs_handle = object; ((zfsfsal_handle_t *)link_handle)->data.type = FSAL_TYPE_LNK; ((zfsfsal_handle_t *)link_handle)->data.i_snap = 0; if(link_attributes) { fsal_status_t status = ZFSFSAL_getattrs(link_handle, p_context, link_attributes); /* On error, we set a flag in the returned attributes */ if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(link_attributes->asked_attributes); FSAL_SET_MASK(link_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } /* OK */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_symlink); }