/**
* FSAL_access :
* Tests whether the user or entity identified by its cred
* can access the object identified by object_handle,
* as indicated by the access_type parameters.
*
* \param object_handle (input):
* The handle of the object to test permissions on.
* \param cred (input):
* Authentication context for the operation (user,...).
* \param access_type (input):
* Indicates the permissions to test.
* This is an inclusive OR of the permissions
* to be checked for the user identified by cred.
* Permissions constants are :
* - FSAL_R_OK : test for read permission
* - FSAL_W_OK : test for write permission
* - FSAL_X_OK : test for exec permission
* - FSAL_F_OK : test for file existence
* \param object_attributes (optional input/output):
* The post operation attributes for the 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 LUSTREFSAL_access(fsal_handle_t * p_object_handle, /* IN */
fsal_op_context_t * p_context, /* IN */
fsal_accessflags_t access_type, /* IN */
fsal_attrib_list_t * p_object_attributes /* [ IN/OUT ] */
)
{
fsal_status_t status;
/* sanity checks.
* note : object_attributes is optionnal in FSAL_getattrs.
*/
if(!p_object_handle || !p_context)
Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_access);
/*
* If an error occures during getattr operation,
* it is returned, even though the access operation succeeded.
*/
if(p_object_attributes)
{
FSAL_SET_MASK(p_object_attributes->asked_attributes,
FSAL_ATTR_OWNER | FSAL_ATTR_GROUP | FSAL_ATTR_ACL | FSAL_ATTR_MODE);
status = LUSTREFSAL_getattrs(p_object_handle, p_context, p_object_attributes);
/* on error, we set a special bit in the mask. */
if(FSAL_IS_ERROR(status))
{
FSAL_CLEAR_MASK(p_object_attributes->asked_attributes);
FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
Return(status.major, status.minor, INDEX_FSAL_access);
}
status =
fsal_internal_testAccess(p_context, access_type, NULL, p_object_attributes);
}
else
{ /* p_object_attributes is NULL */
fsal_attrib_list_t attrs;
FSAL_CLEAR_MASK(attrs.asked_attributes);
FSAL_SET_MASK(attrs.asked_attributes,
FSAL_ATTR_OWNER | FSAL_ATTR_GROUP | FSAL_ATTR_ACL | FSAL_ATTR_MODE);
status = LUSTREFSAL_getattrs(p_object_handle, p_context, &attrs);
/* on error, we set a special bit in the mask. */
if(FSAL_IS_ERROR(status))
Return(status.major, status.minor, INDEX_FSAL_access);
status = fsal_internal_testAccess(p_context, access_type, NULL, &attrs);
}
Return(status.major, status.minor, INDEX_FSAL_access);
}
/**
* FSAL_access :
* Tests whether the user or entity identified by the p_context structure
* can access the object identified by object_handle,
* as indicated by the access_type parameter.
*
* \param object_handle (input):
* The handle of the object to test permissions on.
* \param p_context (input):
* Authentication context for the operation (export entry, user,...).
* \param access_type (input):
* Indicates the permissions to be tested.
* This is an inclusive OR of the permissions
* to be checked for the user specified by p_context.
* Permissions constants are :
* - FSAL_R_OK : test for read permission
* - FSAL_W_OK : test for write permission
* - FSAL_X_OK : test for exec permission
* - FSAL_F_OK : test for file existence
* \param object_attributes (optional input/output):
* The post operation attributes for the 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).
* Can be NULL.
*
* \return Major error codes :
* - ERR_FSAL_NO_ERROR (no error, asked permission is granted)
* - ERR_FSAL_ACCESS (object permissions doesn't fit asked access type)
* - ERR_FSAL_STALE (object_handle does not address an existing object)
* - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument)
* - Other error codes when something anormal occurs.
*/
fsal_status_t SNMPFSAL_access(fsal_handle_t * object_handle, /* IN */
fsal_op_context_t * p_context, /* IN */
fsal_accessflags_t access_type, /* IN */
fsal_attrib_list_t * object_attributes /* [ IN/OUT ] */
)
{
fsal_attrib_list_t attrs;
fsal_status_t st;
/* sanity checks.
* note : object_attributes is optional in FSAL_access.
*/
if(!object_handle || !p_context)
Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_access);
FSAL_CLEAR_MASK(attrs.asked_attributes);
FSAL_SET_MASK(attrs.asked_attributes, global_fs_info.supported_attrs);
st = SNMPFSAL_getattrs(object_handle, p_context, &attrs);
if(FSAL_IS_ERROR(st))
Return(st.major, st.minor, INDEX_FSAL_access);
/* set attributes if needed, then call test_access.
*/
if(object_attributes)
{
*object_attributes = attrs;
}
st = SNMPFSAL_test_access(p_context, access_type, &attrs);
Return(st.major, st.minor, INDEX_FSAL_access);
}
/**
* FSAL_mkdir:
* Create a directory.
*
* \param parent_directory_handle (input):
* Handle of the parent directory where
* the subdirectory is to be created.
* \param p_dirname (input):
* Pointer to the name of the directory 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 object_handle (output):
* Pointer to the handle of the created directory.
* \param object_attributes (optionnal input/output):
* The attributes of the created directory.
* 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)
* - ERR_FSAL_STALE (parent_directory_handle does not address an existing object)
* - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument)
* - Other error codes can be returned :
* ERR_FSAL_ACCESS, ERR_FSAL_EXIST, ERR_FSAL_IO, ...
*
* NB: if getting postop attributes failed,
* the function does not return an error
* but the FSAL_ATTR_RDATTR_ERR bit is set in
* the object_attributes->asked_attributes field.
*/
fsal_status_t ZFSFSAL_mkdir(zfsfsal_handle_t * parent_directory_handle, /* IN */
fsal_name_t * p_dirname, /* IN */
zfsfsal_op_context_t * p_context, /* IN */
fsal_accessmode_t accessmode, /* IN */
zfsfsal_handle_t * object_handle, /* OUT */
fsal_attrib_list_t * object_attributes /* [ IN/OUT ] */
)
{
int rc;
mode_t unix_mode;
/* sanity checks.
* note : object_attributes is optional.
*/
if(!parent_directory_handle || !p_context || !object_handle || !p_dirname)
Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mkdir);
/* convert fsal args to ZFS args */
unix_mode = fsal2unix_mode(accessmode);
/* Applying FSAL umask */
unix_mode = unix_mode & ~global_fs_info.umask;
TakeTokenFSCall();
/* Create the directory */
inogen_t object;
rc = libzfswrap_mkdir(p_context->export_context->p_vfs, &p_context->user_credential.cred,
parent_directory_handle->data.zfs_handle, p_dirname->name, unix_mode, &object);
ReleaseTokenFSCall();
/* >> interpret returned error << */
if(rc)
Return(posix2fsal_error(rc), 0, INDEX_FSAL_create);
/* set output handle */
object_handle->data.zfs_handle = object;
object_handle->data.type = FSAL_TYPE_DIR;
if(object_attributes)
{
/**@TODO: skip this => libzfswrap_mkdir might return attributes */
fsal_status_t status = ZFSFSAL_getattrs(object_handle, p_context, object_attributes);
/* on error, we set a special bit in the mask. */
if(FSAL_IS_ERROR(status))
{
FSAL_CLEAR_MASK(object_attributes->asked_attributes);
FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
}
}
/* OK */
Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_mkdir);
}
/**
* FSAL_create:
* Create a regular file.
*
* \param parent_directory_handle (input):
* Handle of the parent directory where the file is to be created.
* \param p_filename (input):
* Pointer to the name of the file to be created.
* \param cred (input):
* Authentication context for the operation (user, export...).
* \param accessmode (input):
* Mode for the file to be created.
* (the umask defined into the FSAL configuration file
* will be applied on it).
* \param object_handle (output):
* Pointer to the handle of the created file.
* \param object_attributes (optionnal input/output):
* The postop attributes of the created file.
* 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).
* Can be NULL.
*
* \return Major error codes :
* - ERR_FSAL_NO_ERROR (no error)
* - ERR_FSAL_STALE (parent_directory_handle does not address an existing object)
* - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument)
* - Other error codes can be returned :
* ERR_FSAL_ACCESS, ERR_FSAL_EXIST, ERR_FSAL_IO, ...
*
* NB: if getting postop attributes failed,
* the function does not return an error
* but the FSAL_ATTR_RDATTR_ERR bit is set in
* the object_attributes->asked_attributes field.
*/
fsal_status_t ZFSFSAL_create(zfsfsal_handle_t * parent_directory_handle, /* IN */
fsal_name_t * p_filename, /* IN */
zfsfsal_op_context_t * p_context, /* IN */
fsal_accessmode_t accessmode, /* IN */
zfsfsal_handle_t * object_handle, /* OUT */
fsal_attrib_list_t * object_attributes /* [ IN/OUT ] */
)
{
int rc;
/* sanity checks.
* note : object_attributes is optional.
*/
if(!parent_directory_handle || !p_context || !object_handle || !p_filename)
Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_create);
/* >> convert fsal args to your fs args.
* Don't forget applying FSAL umask :
* mode = mode & ~global_fs_info.umask << */
TakeTokenFSCall();
inogen_t object;
rc = libzfswrap_create(p_context->export_context->p_vfs, &p_context->user_credential.cred,
parent_directory_handle->data.zfs_handle, p_filename->name,
fsal2unix_mode(accessmode), &object);
ReleaseTokenFSCall();
/* >> interpret returned error << */
if(rc)
Return(posix2fsal_error(rc), 0, INDEX_FSAL_create);
/* >> set output handle << */
object_handle->data.zfs_handle = object;
object_handle->data.type = FSAL_TYPE_FILE;
if(object_attributes)
{
fsal_status_t status = ZFSFSAL_getattrs(object_handle, p_context, object_attributes);
/* on error, we set a special bit in the mask. */
if(FSAL_IS_ERROR(status))
{
FSAL_CLEAR_MASK(object_attributes->asked_attributes);
FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
}
}
/* OK */
Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_create);
}
/**
* FSAL_link:
* Create a hardlink.
*
* \param exttarget (input):
* Handle of the target object.
* \param extdir (input):
* Pointer to the directory handle where
* the hardlink is to be created.
* \param link_name (input):
* Pointer to the name of the hardlink to be created.
* \param extcontext (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)
* - ERR_FSAL_STALE (target or dir does not address an existing object)
* - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument)
* - Other error codes can be returned :
* ERR_FSAL_ACCESS, ERR_FSAL_EXIST, ERR_FSAL_IO, ...
*
* NB: if getting postop attributes failed,
* the function does not return an error
* but the FSAL_ATTR_RDATTR_ERR bit is set in
* the attributes->asked_attributes field.
*/
fsal_status_t CEPHFSAL_link(fsal_handle_t * exttarget,
fsal_handle_t * extdir,
fsal_name_t * link_name,
fsal_op_context_t * extcontext,
fsal_attrib_list_t * attributes)
{
int rc;
struct stat st;
char strname[FSAL_MAX_NAME_LEN];
cephfsal_handle_t* target = (cephfsal_handle_t*) exttarget;
cephfsal_handle_t* dir = (cephfsal_handle_t*) extdir;
cephfsal_op_context_t* context = (cephfsal_op_context_t*) context;
struct ceph_mount_info *cmount = context->export_context->cmount;
int uid = FSAL_OP_CONTEXT_TO_UID(context);
int gid = FSAL_OP_CONTEXT_TO_GID(context);
/* sanity checks.
* note : attributes is optional.
*/
if(!target || !dir || !context || !link_name)
Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_link);
memset(target, 0, sizeof(cephfsal_handle_t));
/* Tests if hardlinking is allowed by configuration. */
if(!global_fs_info.link_support)
Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_link);
FSAL_name2str(link_name, strname, FSAL_MAX_NAME_LEN);
TakeTokenFSCall();
rc = ceph_ll_link(cmount, VINODE(target), VINODE(dir), strname, &st,
uid, gid);
ReleaseTokenFSCall();
if (rc < 0)
Return(posix2fsal_error(rc), 0, INDEX_FSAL_link);
if(attributes)
{
fsal_status_t status;
status = posix2fsal_attributes(&st, attributes);
if(FSAL_IS_ERROR(status))
{
FSAL_CLEAR_MASK(attributes->asked_attributes);
FSAL_SET_MASK(attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_link);
}
}
/* OK */
Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_link);
}
/**
* GPFSFSAL_getattrs:
* Get attributes for the object specified by its filehandle.
*
* \param filehandle (input):
* The handle of the object to get parameters.
* \param cred (input):
* Authentication context for the operation (user,...).
* \param object_attributes (mandatory input/output):
* The retrieved attributes for the 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).
*
* \return Major error codes :
* - ERR_FSAL_NO_ERROR (no error)
* - Another error code if an error occured.
*/
fsal_status_t GPFSFSAL_getattrs(fsal_handle_t * p_filehandle, /* IN */
fsal_op_context_t * p_context, /* IN */
fsal_attrib_list_t * p_object_attributes /* IN/OUT */
)
{
fsal_status_t st;
gpfsfsal_xstat_t buffxstat;
#ifdef _USE_NFS4_ACL
fsal_accessflags_t access_mask = 0;
#endif
/* sanity checks.
* note : object_attributes is mandatory in GPFSFSAL_getattrs.
*/
if(!p_filehandle || !p_context || !p_object_attributes)
Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_getattrs);
TakeTokenFSCall();
st = fsal_get_xstat_by_handle(p_context,
p_filehandle,
&buffxstat);
ReleaseTokenFSCall();
if(FSAL_IS_ERROR(st))
ReturnStatus(st, INDEX_FSAL_getattrs);
/* convert attributes */
st = gpfsfsal_xstat_2_fsal_attributes(&buffxstat, p_object_attributes);
if(FSAL_IS_ERROR(st))
{
FSAL_CLEAR_MASK(p_object_attributes->asked_attributes);
FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
ReturnStatus(st, INDEX_FSAL_getattrs);
}
#ifdef _USE_NFS4_ACL
if(p_object_attributes->acl)
{
/* Check permission to get attributes and ACL. */
access_mask = FSAL_MODE_MASK_SET(0) | /* Dummy */
FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_READ_ATTR |
FSAL_ACE_PERM_READ_ACL);
st = fsal_internal_testAccess(p_context, access_mask, NULL, p_object_attributes);
if(FSAL_IS_ERROR(st))
ReturnStatus(st, INDEX_FSAL_getattrs);
}
#endif
Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_getattrs);
}
/*
* Common code used by fsal_lookup and fsal_readdir -
* given the name try to stat an entry. If an entry is
* regular file or directory then open it and use fd2handle
* to get a real handle, otherwise use inum2handle to fake
* a handle.
*/
fsal_status_t
xfsfsal_stat_by_name(fsal_op_context_t * context,
int atfd,
const char *name,
fsal_handle_t *handle,
fsal_attrib_list_t * attributes)
{
int rc;
int errsv;
struct stat buffstat;
fsal_status_t st;
TakeTokenFSCall();
rc = fstatat(atfd, name, &buffstat, AT_SYMLINK_NOFOLLOW);
errsv = errno;
ReleaseTokenFSCall();
if(rc < 0)
ReturnCode(posix2fsal_error(errsv), errsv);
if(S_ISDIR(buffstat.st_mode) || S_ISREG(buffstat.st_mode))
{
int tmpfd;
TakeTokenFSCall();
tmpfd = openat(atfd, name, O_RDONLY | O_NOFOLLOW, 0600);
errsv = errno;
ReleaseTokenFSCall();
if(tmpfd < 0)
ReturnCode(posix2fsal_error(errsv), errsv);
st = fsal_internal_fd2handle(context, tmpfd, handle);
close(tmpfd);
}
else
{
st = fsal_internal_inum2handle(context, buffstat.st_ino, handle);
}
if(FSAL_IS_ERROR(st))
return st;
if(attributes)
{
st = posix2fsal_attributes(&buffstat, attributes);
if(FSAL_IS_ERROR(st))
{
FSAL_CLEAR_MASK(attributes->asked_attributes);
FSAL_SET_MASK(attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
}
}
return st;
}
/**
* FSAL_getattrs:
* Get attributes for the object specified by its filehandle.
*
* \param filehandle (input):
* The handle of the object to get parameters.
* \param cred (input):
* Authentication context for the operation (user,...).
* \param object_attributes (mandatory input/output):
* The retrieved attributes for the 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).
*
* \return Major error codes :
* - ERR_FSAL_NO_ERROR (no error)
* - Another error code if an error occured.
*/
fsal_status_t XFSFSAL_getattrs(fsal_handle_t * p_filehandle, /* IN */
fsal_op_context_t * p_context, /* IN */
fsal_attrib_list_t * p_object_attributes /* IN/OUT */
)
{
int rc, errsv;
fsal_status_t st;
int fd;
struct stat buffstat;
/* sanity checks.
* note : object_attributes is mandatory in FSAL_getattrs.
*/
if(!p_filehandle || !p_context || !p_object_attributes)
Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_getattrs);
TakeTokenFSCall();
st = fsal_internal_handle2fd(p_context, p_filehandle, &fd, O_RDONLY);
ReleaseTokenFSCall();
if(FSAL_IS_ERROR(st))
ReturnStatus(st, INDEX_FSAL_getattrs);
/* get file metadata */
TakeTokenFSCall();
rc = fstat(fd, &buffstat);
errsv = errno;
ReleaseTokenFSCall();
close(fd);
if(rc != 0)
{
if(errsv == ENOENT)
Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_getattrs);
else
Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_getattrs);
}
/* convert attributes */
st = posix2fsal_attributes(&buffstat, p_object_attributes);
if(FSAL_IS_ERROR(st))
{
FSAL_CLEAR_MASK(p_object_attributes->asked_attributes);
FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
ReturnStatus(st, INDEX_FSAL_getattrs);
}
Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_getattrs);
}
/**
* 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)
* - ERR_FSAL_STALE (target_handle or dir_handle does not address an existing object)
* - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument)
* - Other error codes can be returned :
* ERR_FSAL_ACCESS, ERR_FSAL_EXIST, ERR_FSAL_IO, ...
*
* NB: if getting postop attributes failed,
* the function does not return an error
* but the FSAL_ATTR_RDATTR_ERR bit is set in
* the attributes->asked_attributes field.
*/
fsal_status_t ZFSFSAL_link(zfsfsal_handle_t * target_handle, /* IN */
zfsfsal_handle_t * dir_handle, /* IN */
fsal_name_t * p_link_name, /* IN */
zfsfsal_op_context_t * p_context, /* IN */
fsal_attrib_list_t * attributes /* [ IN/OUT ] */
)
{
int rc;
/* sanity checks.
* note : attributes is optional.
*/
if(!target_handle || !dir_handle || !p_context || !p_link_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);
TakeTokenFSCall();
rc = libzfswrap_link(p_context->export_context->p_vfs, &p_context->user_credential.cred,
dir_handle->data.zfs_handle, target_handle->data.zfs_handle, p_link_name->name);
ReleaseTokenFSCall();
/* >> interpret returned error << */
if(rc)
Return(posix2fsal_error(rc), 0, INDEX_FSAL_link);
if(attributes)
{
fsal_status_t status = ZFSFSAL_getattrs(target_handle, p_context, attributes);
/* on error, we set a special bit in the mask. */
if(FSAL_IS_ERROR(status))
{
FSAL_CLEAR_MASK(attributes->asked_attributes);
FSAL_SET_MASK(attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
}
}
/* OK */
Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_link);
}
/**
* 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);
}
请发表评论