/** * FSAL_closedir : * Free the resources allocated for reading directory entries. * * \param dir_descriptor (input): * Pointer to a directory descriptor filled by FSAL_opendir. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument) * - Other error codes can be returned : * ERR_FSAL_IO, ... */ fsal_status_t FUSEFSAL_closedir(fsal_dir_t * dir_desc /* IN */ ) { int rc; char dir_path[FSAL_MAX_PATH_LEN]; fusefsal_dir_t * dir_descriptor = (fusefsal_dir_t *)dir_desc; /* sanity checks */ if(!dir_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_closedir); /* get the full path for dir inode */ rc = NamespacePath(dir_descriptor->dir_handle.data.inode, dir_descriptor->dir_handle.data.device, dir_descriptor->dir_handle.data.validator, dir_path); if(rc) Return(ERR_FSAL_STALE, rc, INDEX_FSAL_closedir); if(!p_fs_ops->releasedir) /* ignore this call */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_closedir); /* set context so it can be retrieved by FS */ fsal_set_thread_context((fsal_op_context_t *) &dir_descriptor->context); /* release the resources used for reading directory */ TakeTokenFSCall(); rc = p_fs_ops->releasedir(dir_path, &dir_descriptor->dir_info); ReleaseTokenFSCall(); if(rc) Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_closedir); Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_closedir); }
fsal_status_t FUSEFSAL_close(fsal_file_t * file_desc /* IN */ ) { int rc; char file_path[FSAL_MAX_PATH_LEN]; fusefsal_file_t * file_descriptor = (fusefsal_file_t *)file_desc; /* sanity checks. */ if(!file_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_close); /* get the full path for file inode */ rc = NamespacePath(file_descriptor->file_handle.data.inode, file_descriptor->file_handle.data.device, file_descriptor->file_handle.data.validator, file_path); if(rc) Return(ERR_FSAL_STALE, rc, INDEX_FSAL_close); if(!p_fs_ops->release) /* ignore this call */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close); /* set context so it can be retrieved by FS */ fsal_set_thread_context((fsal_op_context_t *) &file_descriptor->context); LogFullDebug(COMPONENT_FSAL, "FSAL_close: FH=%"PRId64, file_descriptor->file_info.fh); TakeTokenFSCall(); rc = p_fs_ops->release(file_path, &file_descriptor->file_info); ReleaseTokenFSCall(); if(rc) Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_close); Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close); }
/** * 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 FUSEFSAL_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 = 0; char object_path[FSAL_MAX_PATH_LEN]; int file_info_provided = FALSE; fusefsal_handle_t * filehandle = (fusefsal_handle_t *)file_hdl; fusefsal_file_t * file_descriptor = (fusefsal_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); /* get the full path for this file */ rc = NamespacePath(filehandle->data.inode, filehandle->data.device, filehandle->data.validator, object_path); if(rc) Return(ERR_FSAL_STALE, rc, INDEX_FSAL_open); memset(file_descriptor, 0, sizeof(fusefsal_file_t)); /* set access mode flags */ file_descriptor->file_info.flags = 0; if(openflags & FSAL_O_RDONLY) file_descriptor->file_info.flags |= O_RDONLY; if(openflags & FSAL_O_WRONLY) file_descriptor->file_info.flags |= O_WRONLY; if(openflags & FSAL_O_RDWR) file_descriptor->file_info.flags |= O_RDWR; /* set context for the next operation, so it can be retrieved by FS thread */ fsal_set_thread_context(p_context); /* check open call */ if(p_fs_ops->open) { LogFullDebug(COMPONENT_FSAL, "Call to open( %s, %#X )", object_path, file_descriptor->file_info.flags); TakeTokenFSCall(); rc = p_fs_ops->open(object_path, &(file_descriptor->file_info)); ReleaseTokenFSCall(); if(rc) Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_open); file_info_provided = TRUE; } else { LogFullDebug(COMPONENT_FSAL, "no open command provided"); /* ignoring open */ memset(&(file_descriptor->file_info), 0, sizeof(struct ganefuse_file_info)); } /* check open flags (only FSAL_O_TRUNC and FSAL_O_APPEND are used for FUSE filesystems) */ if(openflags & FSAL_O_TRUNC) { if(file_info_provided && p_fs_ops->ftruncate) { LogFullDebug(COMPONENT_FSAL, "call to ftruncate on file since FSAL_O_TRUNC was set"); /* ftruncate the file */ TakeTokenFSCall(); rc = p_fs_ops->ftruncate(object_path, 0, &(file_descriptor->file_info)); ReleaseTokenFSCall(); if(rc) Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_open); } else if(p_fs_ops->truncate) { LogFullDebug(COMPONENT_FSAL, "call to truncate on file since FSAL_O_TRUNC was set"); /* truncate the file */ TakeTokenFSCall(); rc = p_fs_ops->truncate(object_path, 0); ReleaseTokenFSCall(); if(rc) Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_open); } /* else: ignoring flag */ } if(openflags & FSAL_O_APPEND) { struct stat stbuf; /* In this case, this only solution is to get file attributes */ if(file_info_provided && p_fs_ops->fgetattr) { rc = p_fs_ops->fgetattr(object_path, &stbuf, &(file_descriptor->file_info)); } else { rc = p_fs_ops->getattr(object_path, &stbuf); } if(rc) Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_open); file_descriptor->current_offset = stbuf.st_size; } else { file_descriptor->current_offset = 0; } /* fill the file descriptor structure */ file_descriptor->file_handle = *filehandle; /* backup context */ file_descriptor->context = *(fusefsal_op_context_t *)p_context; if(file_info_provided) LogFullDebug(COMPONENT_FSAL, "FSAL_open: FH=%"PRId64, file_descriptor->file_info.fh); if(file_attributes) { fsal_status_t status; status = FUSEFSAL_getattrs((fsal_handle_t *)filehandle, p_context, file_attributes); /* on error, we set a special bit in the mask. */ 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 fusefsal_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 FUSEFSAL_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 */ ) { size_t req_size; int rc; off_t seekoffset = 0; struct stat stbuf; char object_path[FSAL_MAX_PATH_LEN]; fusefsal_file_t * file_descriptor = (fusefsal_file_t *)file_desc; /* sanity checks. */ if(!file_descriptor || !buffer || !write_amount) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_write); if(!p_fs_ops->write) Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_write); /* initialize returned values */ *write_amount = 0; req_size = (size_t) buffer_size; /* set context so it can be retrieved by FS */ fsal_set_thread_context((fsal_op_context_t *) &file_descriptor->context); LogFullDebug(COMPONENT_FSAL, "FSAL_write: FH=%"PRId64, file_descriptor->file_info.fh); /* get file's full path */ rc = NamespacePath(file_descriptor->file_handle.data.inode, file_descriptor->file_handle.data.device, file_descriptor->file_handle.data.validator, object_path); if(rc) Return(ERR_FSAL_STALE, rc, INDEX_FSAL_write); if(seek_descriptor) { switch (seek_descriptor->whence) { case FSAL_SEEK_SET: /* set absolute position to offset */ seekoffset = seek_descriptor->offset; break; case FSAL_SEEK_CUR: /* current position + offset */ seekoffset = file_descriptor->current_offset + seek_descriptor->offset; break; case FSAL_SEEK_END: /* set end of file + offset */ /* in this case, the only solution is to get entry attributes */ if(p_fs_ops->fgetattr) { rc = p_fs_ops->fgetattr(object_path, &stbuf, &(file_descriptor->file_info)); } else { rc = p_fs_ops->getattr(object_path, &stbuf); } if(rc) Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_write); seekoffset = (off_t) stbuf.st_size + seek_descriptor->offset; break; default: LogCrit(COMPONENT_FSAL, "FSAL_write: Invalid seek parameter: whence=%d", seek_descriptor->whence); Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_write); } } else { seekoffset = file_descriptor->current_offset; } TakeTokenFSCall(); rc = p_fs_ops->write(object_path, buffer, req_size, seekoffset, &(file_descriptor->file_info)); ReleaseTokenFSCall(); if(rc < 0) Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_write); file_descriptor->current_offset = seekoffset + (off_t) rc; *write_amount = (fsal_size_t) rc; Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_write); }
/** * FSAL_opendir : * Opens a directory for reading its content. * * \param dir_handle (input) * the handle of the directory to be opened. * \param p_context (input) * Permission context for the operation (user, export context...). * \param dir_descriptor (output) * pointer to an allocated structure that will receive * directory stream informations, on successfull completion. * \param dir_attributes (optional output) * On successfull completion,the structure pointed * by dir_attributes receives the new directory attributes. * Can be NULL. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - ERR_FSAL_ACCESS (user does not have read permission on directory) * - ERR_FSAL_STALE (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_IO, ... */ fsal_status_t FUSEFSAL_opendir(fsal_handle_t * dir_hdl, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_dir_t * dir_desc, /* OUT */ fsal_attrib_list_t * dir_attributes /* [ IN/OUT ] */ ) { int rc; char object_path[FSAL_MAX_PATH_LEN]; fusefsal_dir_t * dir_descriptor = (fusefsal_dir_t *)dir_desc; fusefsal_handle_t * dir_handle = (fusefsal_handle_t *)dir_hdl; /* sanity checks * note : dir_attributes is optionnal. */ if(!dir_handle || !p_context || !dir_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_opendir); /* get the full path for this directory */ rc = NamespacePath(dir_handle->data.inode, dir_handle->data.device, dir_handle->data.validator, object_path); if(rc) Return(ERR_FSAL_STALE, rc, INDEX_FSAL_opendir); memset(dir_descriptor, 0, sizeof(fsal_dir_t)); /* set context for the next operation, so it can be retrieved by FS thread */ fsal_set_thread_context(p_context); /* check opendir call */ if(p_fs_ops->opendir) { TakeTokenFSCall(); rc = p_fs_ops->opendir(object_path, &(dir_descriptor->dir_info)); ReleaseTokenFSCall(); if(rc) Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_opendir); } else { /* ignoring opendir */ memset(&(dir_descriptor->dir_info), 0, sizeof(struct ganefuse_file_info)); } /* fill the dir descriptor structure */ dir_descriptor->dir_handle = *dir_handle; /* backup context */ dir_descriptor->context = *(fusefsal_op_context_t *)p_context; /* optionaly get attributes */ if(dir_attributes) { fsal_status_t status; status = FUSEFSAL_getattrs(dir_hdl, p_context, dir_attributes); /* on error, we set a special bit in the mask. */ if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(dir_attributes->asked_attributes); FSAL_SET_MASK(dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_opendir); }
/** * FSAL_readdir : * Read the entries of an opened directory. * * \param dir_descriptor (input): * Pointer to the directory descriptor filled by FSAL_opendir. * \param start_position (input): * Cookie that indicates the first object to be read during * this readdir operation. * This should be : * - FSAL_READDIR_FROM_BEGINNING for reading the content * of the directory from the beginning. * - The end_position parameter returned by the previous * call to FSAL_readdir. * \param get_attr_mask (input) * Specify the set of attributes to be retrieved for directory entries. * \param buffersize (input) * The size (in bytes) of the buffer where * the direntries are to be stored. * \param pdirent (output) * Adresse of the buffer where the direntries are to be stored. * \param end_position (output) * Cookie that indicates the current position in the directory. * \param nb_entries (output) * Pointer to the number of entries read during the call. * \param end_of_dir (output) * Pointer to a boolean that indicates if the end of dir * has been reached during the call. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument) * - Other error codes can be returned : * ERR_FSAL_IO, ... */ fsal_status_t FUSEFSAL_readdir(fsal_dir_t * dir_desc, /* IN */ fsal_cookie_t start_position, /* IN */ fsal_attrib_mask_t get_attr_mask, /* IN */ fsal_mdsize_t buffersize, /* IN */ fsal_dirent_t * pdirent, /* OUT */ fsal_cookie_t * end_position, /* OUT */ fsal_count_t * nb_entries, /* OUT */ fsal_boolean_t * end_of_dir /* OUT */ ) { int rc; char dir_path[FSAL_MAX_PATH_LEN]; fsal_dirbuff_t reqbuff; unsigned int i; fsal_status_t st; fusefsal_dir_t * dir_descriptor = (fusefsal_dir_t *)dir_desc; /* sanity checks */ if(!dir_descriptor || !pdirent || !end_position || !nb_entries || !end_of_dir) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readdir); /* get the full path for dir inode */ rc = NamespacePath(dir_descriptor->dir_handle.data.inode, dir_descriptor->dir_handle.data.device, dir_descriptor->dir_handle.data.validator, dir_path); if(rc) Return(ERR_FSAL_STALE, rc, INDEX_FSAL_readdir); if(!p_fs_ops->readdir && !p_fs_ops->getdir) Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_readdir); /* set context so it can be retrieved by FS */ fsal_set_thread_context((fsal_op_context_t *) &dir_descriptor->context); /* prepare reaadir structure */ reqbuff.getattr_mask = get_attr_mask; reqbuff.nb_entries = 0; reqbuff.max_entries = (buffersize / sizeof(fsal_dirent_t)); reqbuff.p_entries = pdirent; reqbuff.status.major = 0; reqbuff.status.minor = 0; memcpy( (char *)&reqbuff.begin_off, (char *)&start_position.data, sizeof( off_t ) ) ; reqbuff.curr_off = 0 ; TakeTokenFSCall(); if(p_fs_ops->readdir) rc = p_fs_ops->readdir(dir_path, (void *)&reqbuff, ganefuse_fill_dir, (off_t)start_position.data, &dir_descriptor->dir_info); else rc = p_fs_ops->getdir(dir_path, (ganefuse_dirh_t) & reqbuff, ganefuse_dirfil_old); ReleaseTokenFSCall(); if(rc) Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_readdir); else if(FSAL_IS_ERROR(reqbuff.status)) Return(reqbuff.status.major, reqbuff.status.minor, INDEX_FSAL_readdir); /* if no entry found */ if(reqbuff.nb_entries == 0) { *end_position = start_position; *end_of_dir = TRUE; *nb_entries = 0; LogFullDebug(COMPONENT_FSAL, "No entries found"); Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readdir); } /* at least 1 entry found */ /* we must do some operations on the final dirent array: * - chaining entries together * - if the filesystem did not provide stat buffers, * we must do lookup operations. * - adding dir entries to namespace */ for(i = 0; i < reqbuff.nb_entries; i++) { /* 1) chaining entries together */ if(i == reqbuff.nb_entries - 1) { /* last entry */ pdirent[i].nextentry = NULL; *end_position = pdirent[i].cookie; } else pdirent[i].nextentry = &(pdirent[i + 1]); /* 2) check weither the filesystem provided stat buff */ if(((fusefsal_handle_t *) &pdirent[i].handle)->data.inode == INODE_TO_BE_COMPLETED) { /* If not, make a lookup operation for this entry. * (this with automatically add it to namespace) */ pdirent[i].attributes.asked_attributes = get_attr_mask; LogFullDebug(COMPONENT_FSAL, "Inode to be completed"); st = FUSEFSAL_lookup((fsal_handle_t *) &dir_descriptor->dir_handle, &pdirent[i].name, (fsal_op_context_t *) &dir_descriptor->context, &pdirent[i].handle, &pdirent[i].attributes); if(FSAL_IS_ERROR(st)) Return(st.major, st.minor, INDEX_FSAL_readdir); } else { /* 3) just add entry to namespace except for '.' and '..' * Also set a validator for this entry. */ if(strcmp(pdirent[i].name.name, ".") && strcmp(pdirent[i].name.name, "..")) { LogFullDebug(COMPONENT_FSAL, "adding entry to namespace: %lX.%ld %s", ((fusefsal_handle_t *) &pdirent[i].handle)->data.device, ((fusefsal_handle_t *) &pdirent[i].handle)->data.inode, pdirent[i].name.name); ((fusefsal_handle_t *) &pdirent[i].handle)->data.validator = pdirent[i].attributes.ctime.seconds; NamespaceAdd(dir_descriptor->dir_handle.data.inode, dir_descriptor->dir_handle.data.device, dir_descriptor->dir_handle.data.validator, pdirent[i].name.name, ((fusefsal_handle_t *) &pdirent[i].handle)->data.inode, ((fusefsal_handle_t *) &pdirent[i].handle)->data.device, &(((fusefsal_handle_t *) &pdirent[i].handle)->data.validator)); } } } /* end of dir was reached if not enough entries were provided */ *end_of_dir = (reqbuff.nb_entries < reqbuff.max_entries); *nb_entries = reqbuff.nb_entries; LogFullDebug(COMPONENT_FSAL, "EOD = %d", *end_of_dir); Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readdir); }
fsal_status_t FUSEFSAL_rename(fusefsal_handle_t * old_parentdir_handle, /* IN */ fsal_name_t * p_old_name, /* IN */ fusefsal_handle_t * new_parentdir_handle, /* IN */ fsal_name_t * p_new_name, /* IN */ fusefsal_op_context_t * p_context, /* IN */ fsal_attrib_list_t * src_dir_attributes, /* [ IN/OUT ] */ fsal_attrib_list_t * tgt_dir_attributes /* [ IN/OUT ] */ ) { int rc = 0; char src_dir_path[FSAL_MAX_PATH_LEN]; char tgt_dir_path[FSAL_MAX_PATH_LEN]; char src_obj_path[FSAL_MAX_PATH_LEN]; char tgt_obj_path[FSAL_MAX_PATH_LEN]; /* sanity checks. * note : src/tgt_dir_attributes are optional. */ if(!old_parentdir_handle || !new_parentdir_handle || !p_old_name || !p_new_name || !p_context) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_rename); if(!p_fs_ops->rename) Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_rename); /* get full path for parent source handle */ rc = NamespacePath(old_parentdir_handle->data.inode, old_parentdir_handle->data.device, old_parentdir_handle->data.validator, src_dir_path); if(rc) Return(ERR_FSAL_STALE, rc, INDEX_FSAL_rename); /* get full path for parent target handle */ rc = NamespacePath(new_parentdir_handle->data.inode, new_parentdir_handle->data.device, new_parentdir_handle->data.validator, tgt_dir_path); if(rc) Return(ERR_FSAL_STALE, rc, INDEX_FSAL_rename); /* build full path for source entry */ FSAL_internal_append_path(src_obj_path, src_dir_path, p_old_name->name); /* build full path for target entry */ FSAL_internal_append_path(tgt_obj_path, tgt_dir_path, p_new_name->name); /* set context for the next operation, so it can be retrieved by FS thread */ fsal_set_thread_context(p_context); TakeTokenFSCall(); rc = p_fs_ops->rename(src_obj_path, tgt_obj_path); ReleaseTokenFSCall(); /* Regarding FALSE parameter of function fuse2fsal_error: * here, if error is ENOENT, we don't know weither the father handle is STALE * or if the source entry does not exist. * We choose returning ENOENT since the parent exists in the namespace, * so it it more likely to exist than the children. */ if(rc) Return(fuse2fsal_error(rc, FALSE), rc, INDEX_FSAL_rename); /* If operation succeeded, impact the namespace */ NamespaceRename(old_parentdir_handle->data.inode, old_parentdir_handle->data.device, old_parentdir_handle->data.validator, p_old_name->name, new_parentdir_handle->data.inode, new_parentdir_handle->data.device, new_parentdir_handle->data.validator, p_new_name->name); /* Last parent post op attributes if asked */ if(src_dir_attributes) { fsal_status_t st; st = FUSEFSAL_getattrs(old_parentdir_handle, p_context, src_dir_attributes); if(FSAL_IS_ERROR(st)) { FSAL_CLEAR_MASK(src_dir_attributes->asked_attributes); FSAL_SET_MASK(src_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } /* New parent post op attributes if asked */ if(tgt_dir_attributes) { fsal_status_t st; /* optimization when src=tgt : */ if(!FUSEFSAL_handlecmp(old_parentdir_handle, new_parentdir_handle, &st) && src_dir_attributes) { /* If source dir = target dir, we just copy the attributes. * to avoid doing another getattr. */ (*tgt_dir_attributes) = (*src_dir_attributes); } else { /* get attributes */ st = FUSEFSAL_getattrs(new_parentdir_handle, p_context, tgt_dir_attributes); if(FSAL_IS_ERROR(st)) { FSAL_CLEAR_MASK(tgt_dir_attributes->asked_attributes); FSAL_SET_MASK(tgt_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } } /* OK */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_rename); }