fsal_status_t tank_getextattr_value_by_id(struct fsal_obj_handle *obj_hdl, unsigned int xattr_id, caddr_t buffer_addr, size_t buffer_size, size_t *p_output_size) { struct zfs_fsal_obj_handle *obj_handle = NULL; int retval = -1; creden_t cred; obj_handle = container_of(obj_hdl, struct zfs_fsal_obj_handle, obj_handle); /* sanity checks */ if (!obj_hdl || !p_output_size || !buffer_addr) return fsalstat(ERR_FSAL_FAULT, 0); cred.uid = op_ctx->creds->caller_uid; cred.gid = op_ctx->creds->caller_gid; /* check that this index match the type of entry */ if ((xattr_id < XATTR_COUNT) && !do_match_type(xattr_list[xattr_id].flags, obj_hdl->type)) { return fsalstat(ERR_FSAL_INVAL, 0); } else if (xattr_id >= XATTR_COUNT) { char attr_name[MAXPATHLEN]; /* get the name for this attr */ retval = xattr_id_to_name(ZFSFSAL_GetVFS(obj_handle->handle), &cred, obj_handle->handle->zfs_handle, xattr_id, attr_name); if (retval) return fsalstat(retval, 0); retval = libzfswrap_getxattr(ZFSFSAL_GetVFS(obj_handle->handle), &cred, obj_handle->handle->zfs_handle, attr_name, &buffer_addr); if (retval) return fsalstat(posix2fsal_error(retval), retval); /* the xattr value can be a binary, or a string. * trying to determine its type... */ *p_output_size = strnlen(buffer_addr, buffer_size); xattr_format_value(buffer_addr, p_output_size, buffer_size); return fsalstat(ERR_FSAL_NO_ERROR, 0); } else { /* built-in attr */ /* get the value */ retval = xattr_list[xattr_id].get_func(obj_hdl, buffer_addr, buffer_size, p_output_size, xattr_list[xattr_id] .arg); return fsalstat(retval, 0); } }
fsal_status_t tank_remove_extattr_by_id(struct fsal_obj_handle *obj_hdl, unsigned int xattr_id) { char name[MAXNAMLEN]; struct zfs_fsal_obj_handle *obj_handle = NULL; int retval = 0; creden_t cred; obj_handle = container_of(obj_hdl, struct zfs_fsal_obj_handle, obj_handle); cred.uid = op_ctx->creds->caller_uid; cred.gid = op_ctx->creds->caller_gid; retval = xattr_id_to_name(ZFSFSAL_GetVFS(obj_handle->handle), &cred, obj_handle->handle->zfs_handle, xattr_id, name); if (retval) return fsalstat(retval, 0); retval = libzfswrap_removexattr(ZFSFSAL_GetVFS(obj_handle->handle), &cred, obj_handle->handle->zfs_handle, name); if (retval != 0) return fsalstat(posix2fsal_error(retval), retval); return fsalstat(ERR_FSAL_NO_ERROR, 0); }
fsal_status_t tank_setextattr_value_by_id(struct fsal_obj_handle *obj_hdl, unsigned int xattr_id, caddr_t buffer_addr, size_t buffer_size) { char name[MAXNAMLEN]; struct zfs_fsal_obj_handle *obj_handle = NULL; int retval = -1; creden_t cred; obj_handle = container_of(obj_hdl, struct zfs_fsal_obj_handle, obj_handle); if (attr_is_read_only(xattr_id)) return fsalstat(ERR_FSAL_PERM, 0); else if (xattr_id < XATTR_COUNT) return fsalstat(ERR_FSAL_PERM, 0); cred.uid = op_ctx->creds->caller_uid; cred.gid = op_ctx->creds->caller_gid; retval = xattr_id_to_name(ZFSFSAL_GetVFS(obj_handle->handle), &cred, obj_handle->handle->zfs_handle, xattr_id, name); if (retval) return fsalstat(retval, 0); return tank_setextattr_value(obj_hdl, name, buffer_addr, buffer_size, false); }
fsal_status_t tank_setextattr_value(struct fsal_obj_handle *obj_hdl, const char *xattr_name, caddr_t buffer_addr, size_t buffer_size, int create) { struct zfs_fsal_obj_handle *obj_handle = NULL; int rc = 0; creden_t cred; obj_handle = container_of(obj_hdl, struct zfs_fsal_obj_handle, obj_handle); /* remove final '\n', if any */ chomp_attr_value((char *)buffer_addr, buffer_size); cred.uid = op_ctx->creds->caller_uid; cred.gid = op_ctx->creds->caller_gid; rc = libzfswrap_setxattr(ZFSFSAL_GetVFS(obj_handle->handle), &cred, obj_handle->handle->zfs_handle, xattr_name, buffer_addr); if (rc != 0) return fsalstat(posix2fsal_error(rc), rc); else return fsalstat(ERR_FSAL_NO_ERROR, 0); }
/** * Get the value of an extended attribute from its name. * * \param p_objecthandle Handle of the object you want to get attribute for. * \param xattr_name the name of the attribute to be read. * \param p_context pointer to the current security context. * \param buffer_addr address of the buffer where the xattr value is to be stored. * \param buffer_size size of the buffer where the xattr value is to be stored. * \param p_output_size size of the data actually stored into the buffer. */ fsal_status_t ZFSFSAL_GetXAttrValueByName(fsal_handle_t * obj_handle, /* IN */ const fsal_name_t * xattr_name, /* IN */ fsal_op_context_t * p_context, /* IN */ caddr_t buffer_addr, /* IN/OUT */ size_t buffer_size, /* IN */ size_t * p_output_size /* OUT */ ) { unsigned int index; char *psz_value; int rc; creden_t cred; zfsfsal_handle_t *p_objecthandle = (zfsfsal_handle_t *)obj_handle; /* sanity checks */ if(!p_objecthandle || !p_context || !p_output_size || !buffer_addr || !xattr_name) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_GetXAttrValue); /* look for this name */ for(index = 0; index < XATTR_COUNT; index++) { if(do_match_type(xattr_list[index].flags, p_objecthandle->data.type) && !strcmp(xattr_list[index].xattr_name, xattr_name->name)) { return ZFSFSAL_GetXAttrValueById((fsal_handle_t *)p_objecthandle, index, p_context, buffer_addr, buffer_size, p_output_size); } } /* Get the right VFS */ libzfswrap_vfs_t *p_vfs = ZFSFSAL_GetVFS(p_objecthandle); if(!p_vfs) { ZFSFSAL_VFS_Unlock(); Return(ERR_FSAL_NOENT, 0, INDEX_FSAL_GetXAttrValue); } cred.uid = p_context->credential.user; cred.gid = p_context->credential.group; TakeTokenFSCall(); if((rc = libzfswrap_getxattr(p_vfs, &cred, p_objecthandle->data.zfs_handle, xattr_name->name, &psz_value))) { ZFSFSAL_VFS_Unlock(); Return(posix2fsal_error(rc), 0, INDEX_FSAL_GetXAttrValue); } ZFSFSAL_VFS_Unlock(); /* Copy the string (remove this call by changing the libzfswrap API) */ strncpy(buffer_addr, psz_value, buffer_size); buffer_addr[buffer_size - 1] = '\0'; *p_output_size = strlen(psz_value); free(psz_value); Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_GetXAttrValue); }
/** * Get the index of an xattr based on its name * * \param p_objecthandle Handle of the object you want to get attribute for. * \param xattr_name the name of the attribute to be read. * \param pxattr_id found xattr_id * * \return ERR_FSAL_NO_ERROR if xattr_name exists, ERR_FSAL_NOENT otherwise */ fsal_status_t ZFSFSAL_GetXAttrIdByName(fsal_handle_t * obj_handle, /* IN */ const fsal_name_t * xattr_name, /* IN */ fsal_op_context_t * context, /* IN */ unsigned int *pxattr_id /* OUT */ ) { unsigned int index; int rc; int found = FALSE; zfsfsal_handle_t *p_objecthandle = (zfsfsal_handle_t *)obj_handle; zfsfsal_op_context_t *p_context = (zfsfsal_op_context_t *)context; /* sanity checks */ if(!p_objecthandle || !xattr_name) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_GetXAttrValue); for(index = 0; index < XATTR_COUNT; index++) { if(!strcmp(xattr_list[index].xattr_name, xattr_name->name)) { found = TRUE; break; } } if(!found) { /* Get the right VFS */ ZFSFSAL_VFS_RDLock(); libzfswrap_vfs_t *p_vfs = ZFSFSAL_GetVFS(p_objecthandle); if(!p_vfs) { ZFSFSAL_VFS_Unlock(); Return(ERR_FSAL_NOENT, 0, INDEX_FSAL_access); } if((rc = xattr_name_to_id(p_vfs, p_context, p_objecthandle, xattr_name->name, &index))) { ZFSFSAL_VFS_Unlock(); Return(rc, 0, INDEX_FSAL_GetXAttrValue); } found = TRUE; } if(found) { *pxattr_id = index; Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_GetXAttrValue); } else Return(ERR_FSAL_NOENT, ENOENT, INDEX_FSAL_GetXAttrValue); }
fsal_status_t tank_getextattr_value_by_name(struct fsal_obj_handle *obj_hdl, const char *xattr_name, caddr_t buffer_addr, size_t buffer_size, size_t *p_output_size) { struct zfs_fsal_obj_handle *obj_handle = NULL; unsigned int index; creden_t cred; int retval = 0; obj_handle = container_of(obj_hdl, struct zfs_fsal_obj_handle, obj_handle); /* sanity checks */ if (!obj_hdl || !p_output_size || !buffer_addr || !xattr_name) return fsalstat(ERR_FSAL_FAULT, 0); cred.uid = op_ctx->creds->caller_uid; cred.gid = op_ctx->creds->caller_gid; /* look for this name */ for (index = 0; index < XATTR_COUNT; index++) { if (do_match_type(xattr_list[index].flags, obj_hdl->attributes.type) && !strcmp(xattr_list[index].xattr_name, xattr_name)) { return tank_getextattr_value_by_id(obj_hdl, index, buffer_addr, buffer_size, p_output_size); } } /* is it an xattr? */ retval = libzfswrap_getxattr(ZFSFSAL_GetVFS(obj_handle->handle), &cred, obj_handle->handle->zfs_handle, xattr_name, &buffer_addr); if (retval) return fsalstat(posix2fsal_error(retval), retval); /* the xattr value can be a binary, or a string. * trying to determine its type... */ *p_output_size = strnlen(buffer_addr, buffer_size); xattr_format_value(buffer_addr, p_output_size, buffer_size); return fsalstat(ERR_FSAL_NO_ERROR, 0); }
fsal_status_t tank_getextattr_id_by_name(struct fsal_obj_handle *obj_hdl, const char *xattr_name, unsigned int *pxattr_id) { unsigned int index; int rc; bool found = false; struct zfs_fsal_obj_handle *obj_handle = NULL; creden_t cred; /* sanity checks */ if (!obj_hdl || !xattr_name) return fsalstat(ERR_FSAL_FAULT, 0); obj_handle = container_of(obj_hdl, struct zfs_fsal_obj_handle, obj_handle); cred.uid = op_ctx->creds->caller_uid; cred.gid = op_ctx->creds->caller_gid; for (index = 0; index < XATTR_COUNT; index++) { if (!strcmp(xattr_list[index].xattr_name, xattr_name)) { found = true; break; } } /* search in xattrs */ if (!found) { rc = xattr_name_to_id(ZFSFSAL_GetVFS(obj_handle->handle), &cred, obj_handle->handle->zfs_handle, (char *)xattr_name); if (rc) return fsalstat(posix2fsal_error(rc), rc); else { index = rc; found = true; } } *pxattr_id = index; return fsalstat(ERR_FSAL_NO_ERROR, 0); }
fsal_status_t tank_remove_extattr_by_name(struct fsal_obj_handle *obj_hdl, const char *xattr_name) { struct zfs_fsal_obj_handle *obj_handle = NULL; int retval = 0; creden_t cred; obj_handle = container_of(obj_hdl, struct zfs_fsal_obj_handle, obj_handle); cred.uid = op_ctx->creds->caller_uid; cred.gid = op_ctx->creds->caller_gid; retval = libzfswrap_removexattr(ZFSFSAL_GetVFS(obj_handle->handle), &cred, obj_handle->handle->zfs_handle, xattr_name); if (retval != 0) return fsalstat(posix2fsal_error(retval), retval); return fsalstat(ERR_FSAL_NO_ERROR, 0); }
fsal_status_t ZFSFSAL_close(fsal_file_t * file_desc /* IN */ ) { int rc = 0; zfsfsal_file_t * file_descriptor = (zfsfsal_file_t *)file_desc; /* sanity checks. */ if(!file_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_close); TakeTokenFSCall(); if(!file_descriptor->is_closed) { /* Test that the vfs still exist */ ZFSFSAL_VFS_RDLock(); libzfswrap_vfs_t *p_vfs = ZFSFSAL_GetVFS(&file_descriptor->handle); if(!p_vfs) { ZFSFSAL_VFS_Unlock(); ReleaseTokenFSCall(); Return(ERR_FSAL_NOENT, 0, INDEX_FSAL_close); } rc = libzfswrap_close(p_vfs, &file_descriptor->cred, file_descriptor->p_vnode, file_descriptor->flags); ZFSFSAL_VFS_Unlock(); file_descriptor->is_closed = 1; } ReleaseTokenFSCall(); if(rc) Return(posix2fsal_error(rc), rc, INDEX_FSAL_close); Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close); }
fsal_status_t tank_list_ext_attrs(struct fsal_obj_handle *obj_hdl, unsigned int argcookie, fsal_xattrent_t *xattrs_tab, unsigned int xattrs_tabsize, unsigned int *p_nb_returned, int *end_of_list) { unsigned int index; unsigned int out_index; unsigned int cookie = argcookie; struct zfs_fsal_obj_handle *obj_handle = NULL; char names[MAXPATHLEN], *ptr; size_t namesize; int xattr_idx; int retval; creden_t cred; /* sanity checks */ if (!obj_hdl || !xattrs_tab || !p_nb_returned || !end_of_list) return fsalstat(ERR_FSAL_FAULT, 0); obj_handle = container_of(obj_hdl, struct zfs_fsal_obj_handle, obj_handle); cred.uid = op_ctx->creds->caller_uid; cred.gid = op_ctx->creds->caller_gid; /* Deal with special cookie */ if (cookie == XATTR_RW_COOKIE) cookie = XATTR_COUNT; for (index = cookie, out_index = 0; index < XATTR_COUNT && out_index < xattrs_tabsize; index++) { if (do_match_type(xattr_list[index].flags, obj_hdl->attributes.type)) { /* fills an xattr entry */ xattrs_tab[out_index].xattr_id = index; strncpy(xattr_list[index].xattr_name, xattrs_tab[out_index].xattr_name, MAXNAMLEN); xattr_list[index].xattr_name[MAXNAMLEN] = '\0'; xattrs_tab[out_index].xattr_cookie = index + 1; /* set asked attributes (all supported) */ xattrs_tab[out_index].attributes.mask = obj_hdl->attributes.mask; if (file_attributes_to_xattr_attrs(&obj_hdl->attributes, &xattrs_tab [out_index] .attributes, index)) { /* set error flag */ xattrs_tab[out_index].attributes.mask = ATTR_RDATTR_ERR; } /* next output slot */ out_index++; } } /* save a call if output array is full */ if (out_index == xattrs_tabsize) { *end_of_list = false; *p_nb_returned = out_index; return fsalstat(ERR_FSAL_NO_ERROR, 0); } /* get the path of the file in Lustre */ /* get xattrs */ retval = libzfswrap_listxattr(ZFSFSAL_GetVFS(obj_handle->handle), &cred, obj_handle->handle->zfs_handle, (char **)&names, &namesize); if (retval) return fsalstat(posix2fsal_error(retval), retval); if (namesize > 0) { size_t len = 0; errno = 0; for (ptr = names, xattr_idx = 0; (ptr < names + namesize) && (out_index < xattrs_tabsize); xattr_idx++, ptr += len + 1) { len = strlen(ptr); index = XATTR_COUNT + xattr_idx; /* skip if index is before cookie */ if (index < cookie) continue; /* fills an xattr entry */ xattrs_tab[out_index].xattr_id = index; strncpy(xattrs_tab[out_index].xattr_name, ptr, len + 1); xattrs_tab[out_index].xattr_cookie = index + 1; /* set asked attributes (all supported) */ xattrs_tab[out_index].attributes.mask = obj_hdl->attributes.mask; if (file_attributes_to_xattr_attrs (&obj_hdl->attributes, &xattrs_tab[out_index].attributes, index)) { /* set error flag */ xattrs_tab[out_index].attributes.mask = ATTR_RDATTR_ERR; } /* next output slot */ out_index++; } /* all xattrs are in the output array */ if (ptr >= names + namesize) *end_of_list = true; else *end_of_list = false; } else /* no xattrs */ *end_of_list = true; *p_nb_returned = out_index; return fsalstat(ERR_FSAL_NO_ERROR, 0); }
/** * Get the value of an extended attribute from its index. * * \param p_objecthandle Handle of the object you want to get attribute for. * \param xattr_name the name of the attribute to be read. * \param p_context pointer to the current security context. * \param buffer_addr address of the buffer where the xattr value is to be stored. * \param buffer_size size of the buffer where the xattr value is to be stored. * \param p_output_size size of the data actually stored into the buffer. */ fsal_status_t ZFSFSAL_GetXAttrValueById(fsal_handle_t * obj_handle, /* IN */ unsigned int xattr_id, /* IN */ fsal_op_context_t * context, /* IN */ caddr_t buffer_addr, /* IN/OUT */ size_t buffer_size, /* IN */ size_t * p_output_size /* OUT */ ) { int rc; char buff[MAXNAMLEN]; zfsfsal_handle_t *p_objecthandle = (zfsfsal_handle_t *)obj_handle; zfsfsal_op_context_t *p_context = (zfsfsal_op_context_t *)context; /* sanity checks */ if(!p_objecthandle || !p_context || !p_output_size || !buffer_addr) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_GetXAttrValue); /* check that this index match the type of entry */ if(xattr_id < XATTR_COUNT && !do_match_type(xattr_list[xattr_id].flags, p_objecthandle->data.type)) { Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_GetXAttrValue); } /* Get the right VFS */ ZFSFSAL_VFS_RDLock(); libzfswrap_vfs_t *p_vfs = ZFSFSAL_GetVFS(p_objecthandle); if(!p_vfs) { ZFSFSAL_VFS_Unlock(); Return(ERR_FSAL_NOENT, 0, INDEX_FSAL_GetXAttrValue); } if(xattr_id >= XATTR_COUNT) { char psz_attr_name[MAXPATHLEN]; char *psz_value; creden_t cred; if((rc = xattr_id_to_name(p_vfs, p_context, p_objecthandle, xattr_id, psz_attr_name))) { ZFSFSAL_VFS_Unlock(); Return(rc, errno, INDEX_FSAL_GetXAttrValue); } cred.uid = p_context->credential.user; cred.gid = p_context->credential.group; if((rc = libzfswrap_getxattr(p_vfs, &cred, p_objecthandle->data.zfs_handle, psz_attr_name, &psz_value))) { ZFSFSAL_VFS_Unlock(); Return(posix2fsal_error(rc), 0, INDEX_FSAL_GetXAttrValue); } /* Copy the string (remove this call by changing the libzfswrap API) */ strncpy(buffer_addr, psz_value, buffer_size); buffer_addr[buffer_size - 1] = '\0'; *p_output_size = strlen(psz_value); free(psz_value); } else { rc = xattr_list[xattr_id].get_func(p_objecthandle, p_context, buffer_addr, buffer_size, p_output_size); /* Get the value */ if(xattr_list[xattr_id].print_func == NULL) rc = xattr_list[xattr_id].get_func(p_objecthandle, p_context, buffer_addr, buffer_size, p_output_size); else { rc = xattr_list[xattr_id].get_func(p_objecthandle, p_context, buff, MAXNAMLEN, p_output_size); xattr_list[xattr_id].print_func(buff, MAXNAMLEN, buffer_addr, p_output_size); } } ZFSFSAL_VFS_Unlock(); Return(rc, 0, INDEX_FSAL_GetXAttrValue); }
/** * Retrieves the list of extended attributes for an object in the filesystem. * * \param p_objecthandle Handle of the object we want to get extended attributes. * \param cookie index of the next entry to be returned. * \param p_context pointer to the current security context. * \param xattrs_tab a table for storing extended attributes list to. * \param xattrs_tabsize the maximum number of xattr entries that xattrs_tab * can contain. * \param p_nb_returned the number of xattr entries actually stored in xattrs_tab. * \param end_of_list this boolean indicates that the end of xattrs list has been reached. */ fsal_status_t ZFSFSAL_ListXAttrs(fsal_handle_t * obj_handle, /* IN */ unsigned int argcookie, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_xattrent_t * xattrs_tab, /* IN/OUT */ unsigned int xattrs_tabsize, /* IN */ unsigned int *p_nb_returned, /* OUT */ int *end_of_list /* OUT */ ) { unsigned int index; unsigned int out_index; fsal_status_t st; fsal_attrib_list_t file_attrs; int rc; creden_t cred; zfsfsal_handle_t *p_objecthandle = (zfsfsal_handle_t *)obj_handle; unsigned int cookie = argcookie ; /* sanity checks */ if(!p_objecthandle || !p_context || !xattrs_tab || !p_nb_returned || !end_of_list) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_ListXAttrs); /* Deal with special cookie */ if( argcookie == FSAL_XATTR_RW_COOKIE ) cookie = XATTR_COUNT ; /* object attributes we want to retrieve from parent */ file_attrs.asked_attributes = FSAL_ATTR_MODE | FSAL_ATTR_FILEID | FSAL_ATTR_OWNER | FSAL_ATTR_GROUP | FSAL_ATTR_ATIME | FSAL_ATTR_MTIME | FSAL_ATTR_TYPE | FSAL_ATTR_CTIME | FSAL_ATTR_CREATION | FSAL_ATTR_CHGTIME | FSAL_ATTR_FSID; /* don't retrieve unsuipported attributes */ file_attrs.asked_attributes &= global_fs_info.supported_attrs; st = ZFSFSAL_getattrs(obj_handle, p_context, &file_attrs); if(FSAL_IS_ERROR(st)) Return(st.major, st.minor, INDEX_FSAL_ListXAttrs); /* Get the right VFS */ ZFSFSAL_VFS_RDLock(); libzfswrap_vfs_t *p_vfs = ZFSFSAL_GetVFS(p_objecthandle); if(!p_vfs) { ZFSFSAL_VFS_Unlock(); Return(ERR_FSAL_NOENT, 0, INDEX_FSAL_ListXAttrs); } for(index = cookie, out_index = 0; index < XATTR_COUNT && out_index < xattrs_tabsize; index++) { if(do_match_type(xattr_list[index].flags, p_objecthandle->data.type)) { /* fills an xattr entry */ xattrs_tab[out_index].xattr_id = index; FSAL_str2name(xattr_list[index].xattr_name, FSAL_MAX_NAME_LEN, &xattrs_tab[out_index].xattr_name); xattrs_tab[out_index].xattr_cookie = index + 1; /* set asked attributes (all supported) */ xattrs_tab[out_index].attributes.asked_attributes = global_fs_info.supported_attrs; if(file_attributes_to_xattr_attrs (&file_attrs, &xattrs_tab[out_index].attributes, index)) { /* set error flag */ xattrs_tab[out_index].attributes.asked_attributes = FSAL_ATTR_RDATTR_ERR; } /* next output slot */ out_index++; } } /* Save a call if the output array is full */ if(out_index == xattrs_tabsize) { *end_of_list = FALSE; *p_nb_returned = out_index; ZFSFSAL_VFS_Unlock(); Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_ListXAttrs); } /* List the extended attributes */ char *psz_buffer; size_t i_size; cred.uid = p_context->credential.user; cred.gid = p_context->credential.group; TakeTokenFSCall(); rc = libzfswrap_listxattr(p_vfs, &cred, p_objecthandle->data.zfs_handle, &psz_buffer, &i_size); ReleaseTokenFSCall(); ZFSFSAL_VFS_Unlock(); if(rc) Return(posix2fsal_error(rc), 0, INDEX_FSAL_ListXAttrs); if(i_size > 0) { size_t len = 0; char *ptr; int xattr_idx; for(ptr = psz_buffer, xattr_idx = 0; (ptr < psz_buffer + i_size) && (out_index < xattrs_tabsize); xattr_idx++, ptr += len + 1) { len = strlen(ptr); index = XATTR_COUNT + xattr_idx; /* Skip if the index is before the cookie */ if(index < cookie) continue; xattrs_tab[out_index].xattr_id = index; FSAL_str2name(ptr, len + 1, &xattrs_tab[out_index].xattr_name); xattrs_tab[out_index].xattr_cookie = index + 1; /* set asked attributes (all supported) */ xattrs_tab[out_index].attributes.asked_attributes = global_fs_info.supported_attrs; if(file_attributes_to_xattr_attrs(&file_attrs, &xattrs_tab[out_index].attributes, index)) { /* set error flag */ xattrs_tab[out_index].attributes.asked_attributes = FSAL_ATTR_RDATTR_ERR; } /* next output slot */ out_index++; } /* Every xattrs are in the output array */ if(ptr >= psz_buffer + i_size) *end_of_list = TRUE; else *end_of_list = FALSE; } else *end_of_list = TRUE; free(psz_buffer); *p_nb_returned = out_index; Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_ListXAttrs); }
/** * FSAL_open: * Open a regular file for reading/writing its data content. * * \param filehandle (input): * Handle of the file to be read/modified. * \param cred (input): * Authentication context for the operation (user,...). * \param openflags (input): * Flags that indicates behavior for file opening and access. * This is an inclusive OR of the following values * ( such of them are not compatible) : * - FSAL_O_RDONLY: opening file for reading only. * - FSAL_O_RDWR: opening file for reading and writing. * - FSAL_O_WRONLY: opening file for writting only. * - FSAL_O_APPEND: always write at the end of the file. * - FSAL_O_TRUNC: truncate the file to 0 on opening. * \param file_descriptor (output): * The file descriptor to be used for FSAL_read/write operations. * \param file_attributes (optionnal input/output): * Post operation attributes. * 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) * - ERR_FSAL_ACCESS (user doesn't have the permissions for opening the file) * - ERR_FSAL_STALE (filehandle does not address an existing object) * - ERR_FSAL_INVAL (filehandle does not address a regular file, * or open flags are conflicting) * - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument) * - Other error codes can be returned : * ERR_FSAL_IO, ... */ fsal_status_t ZFSFSAL_open(fsal_handle_t * file_hdl, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_openflags_t openflags, /* IN */ fsal_file_t * file_desc, /* OUT */ fsal_attrib_list_t * file_attributes /* [ IN/OUT ] */ ) { int rc; creden_t cred; zfsfsal_handle_t * filehandle = (zfsfsal_handle_t *)file_hdl; zfsfsal_file_t * file_descriptor = ( zfsfsal_file_t *)file_desc; /* sanity checks. * note : file_attributes is optional. */ if(!filehandle || !p_context || !file_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open); /* Check if this is a file */ if(filehandle->data.type != FSAL_TYPE_FILE) Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_open); /* Get the right VFS */ ZFSFSAL_VFS_RDLock(); libzfswrap_vfs_t *p_vfs = ZFSFSAL_GetVFS(filehandle); if(!p_vfs) { ZFSFSAL_VFS_Unlock(); Return(ERR_FSAL_NOENT, 0, INDEX_FSAL_open); } /* >> convert fsal open flags to your FS open flags * Take care of conflicting flags << */ int posix_flags; rc = fsal2posix_openflags(openflags, &posix_flags); if(rc) Return(rc, 0, INDEX_FSAL_open); cred.uid = p_context->credential.user; cred.gid = p_context->credential.group; TakeTokenFSCall(); /* >> call your FS open function << */ libzfswrap_vnode_t *p_vnode; rc = libzfswrap_open(p_vfs, &cred, filehandle->data.zfs_handle, posix_flags, &p_vnode); ReleaseTokenFSCall(); ZFSFSAL_VFS_Unlock(); /* >> interpret returned status << */ if(rc) Return(posix2fsal_error(rc), 0, INDEX_FSAL_open); /* >> fill output struct << */ file_descriptor->flags = posix_flags; file_descriptor->current_offset = 0; file_descriptor->p_vnode = p_vnode; file_descriptor->handle = *filehandle; file_descriptor->cred = cred; file_descriptor->is_closed = 0; if(file_attributes) { fsal_status_t status = ZFSFSAL_getattrs(file_hdl, p_context, file_attributes); /* On error, we set a flag in the returned attributes */ if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(file_attributes->asked_attributes); FSAL_SET_MASK(file_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_open); }
/** * FSAL_write: * Perform a write operation on an opened file. * * \param file_descriptor (input): * The file descriptor returned by FSAL_open. * \param p_context (input): * Authentication context for the operation (user,...). * \param seek_descriptor (optional input): * Specifies the position where data is to be written. * If not specified, data will be written at the current position. * \param buffer_size (input): * Amount (in bytes) of data to be written. * \param buffer (input): * Address in memory of the data to write to file. * \param write_amount (output): * Pointer to the amount of data (in bytes) that have been written * during this call. * * \return Major error codes: * - ERR_FSAL_NO_ERROR (no error) * - ERR_FSAL_INVAL (invalid parameter) * - ERR_FSAL_NOT_OPENED (tried to write in a non-opened zfsfsal_file_t) * - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument) * - Other error codes can be returned : * ERR_FSAL_IO, ERR_FSAL_NOSPC, ERR_FSAL_DQUOT... */ fsal_status_t ZFSFSAL_write(fsal_file_t * file_desc, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_seek_t * seek_descriptor, /* IN */ fsal_size_t buffer_size, /* IN */ caddr_t buffer, /* IN */ fsal_size_t * write_amount /* OUT */ ) { int rc, behind = 0; off_t offset; zfsfsal_file_t * file_descriptor = (zfsfsal_file_t *)file_desc; /* sanity checks. */ if(!file_descriptor || !buffer || !write_amount) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_write); /* Hook to prevent writing into a snapshot */ if(file_descriptor->handle.data.i_snap != 0) { LogDebug(COMPONENT_FSAL, "Trying to write to a file inside a snapshot"); Return(ERR_FSAL_ROFS, 0, INDEX_FSAL_write); } TakeTokenFSCall(); if(seek_descriptor) { switch(seek_descriptor->whence) { case FSAL_SEEK_CUR: offset = file_descriptor->current_offset + seek_descriptor->offset; break; case FSAL_SEEK_SET: offset = seek_descriptor->offset; break; case FSAL_SEEK_END: behind = 1; offset = seek_descriptor->offset; break; } } /* Test that the vfs still exist */ ZFSFSAL_VFS_RDLock(); libzfswrap_vfs_t *p_vfs = ZFSFSAL_GetVFS(&file_descriptor->handle); if(!p_vfs) { ZFSFSAL_VFS_Unlock(); ReleaseTokenFSCall(); Return(ERR_FSAL_NOENT, 0, INDEX_FSAL_write); } rc = libzfswrap_write(p_vfs, &file_descriptor->cred, file_descriptor->p_vnode, buffer, buffer_size, behind, offset); ZFSFSAL_VFS_Unlock(); ReleaseTokenFSCall(); /* >> interpreted returned status << */ if(rc) Return(posix2fsal_error(rc), 0, INDEX_FSAL_write); /* >> dont forget setting output vars : write_amount << */ *write_amount = buffer_size; Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_write); }
/** * FSAL_read: * Perform a read operation on an opened file. * * \param file_descriptor (input): * The file descriptor returned by FSAL_open. * \param seek_descriptor (optional input): * Specifies the position where data is to be read. * If not specified, data will be read at the current position. * \param buffer_size (input): * Amount (in bytes) of data to be read. * \param buffer (output): * Address where the read data is to be stored in memory. * \param read_amount (output): * Pointer to the amount of data (in bytes) that have been read * during this call. * \param end_of_file (output): * Pointer to a boolean that indicates whether the end of file * has been reached during this call. * * \return Major error codes: * - ERR_FSAL_NO_ERROR (no error) * - ERR_FSAL_INVAL (invalid parameter) * - ERR_FSAL_NOT_OPENED (tried to read in a non-opened zfsfsal_file_t) * - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument) * - Other error codes can be returned : * ERR_FSAL_IO, ... */ fsal_status_t ZFSFSAL_read(fsal_file_t * file_desc, /* IN */ fsal_seek_t * seek_descriptor, /* [IN] */ fsal_size_t buffer_size, /* IN */ caddr_t buffer, /* OUT */ fsal_size_t * read_amount, /* OUT */ fsal_boolean_t * end_of_file /* OUT */ ) { off_t offset = 0; int rc; int behind = 0; zfsfsal_file_t * file_descriptor = (zfsfsal_file_t *)file_desc; /* sanity checks. */ if(!file_descriptor || !buffer || !read_amount || !end_of_file) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_read); TakeTokenFSCall(); if(seek_descriptor) { switch(seek_descriptor->whence) { case FSAL_SEEK_CUR: offset = file_descriptor->current_offset + seek_descriptor->offset; break; case FSAL_SEEK_SET: offset = seek_descriptor->offset; break; case FSAL_SEEK_END: behind = 1; offset = seek_descriptor->offset; break; } } /* Test that the vfs still exist */ ZFSFSAL_VFS_RDLock(); libzfswrap_vfs_t *p_vfs = ZFSFSAL_GetVFS(&file_descriptor->handle); if(!p_vfs) { ZFSFSAL_VFS_Unlock(); ReleaseTokenFSCall(); Return(ERR_FSAL_NOENT, 0, INDEX_FSAL_read); } rc = libzfswrap_read(p_vfs, &file_descriptor->cred, file_descriptor->p_vnode, buffer, buffer_size, behind, offset); ZFSFSAL_VFS_Unlock(); ReleaseTokenFSCall(); /* >> interpreted returned status << */ if(!rc) *end_of_file = 1; /* >> dont forget setting output vars : read_amount, end_of_file << */ *read_amount = buffer_size; Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_read); }