nfs-ganesha 1.4
|
00001 /* 00002 * vim:expandtab:shiftwidth=8:tabstop=8: 00003 */ 00004 00014 #ifdef HAVE_CONFIG_H 00015 #include "config.h" 00016 #endif 00017 00018 #include "fsal.h" 00019 #include "fsal_internal.h" 00020 #include "fsal_convert.h" 00021 #include "namespace.h" 00022 #include "fsal_common.h" 00023 00053 fsal_status_t FUSEFSAL_unlink(fsal_handle_t * parent, /* IN */ 00054 fsal_name_t * p_object_name, /* IN */ 00055 fsal_op_context_t * p_context, /* IN */ 00056 fsal_attrib_list_t * parentdir_attributes /* [IN/OUT ] */ 00057 ) 00058 { 00059 00060 int rc; 00061 fsal_status_t st; 00062 char parent_path[FSAL_MAX_PATH_LEN]; 00063 char child_path[FSAL_MAX_PATH_LEN]; 00064 struct stat stbuff; 00065 fusefsal_handle_t * parentdir_handle = (fusefsal_handle_t *)parent; 00066 00067 /* sanity checks. 00068 * note : parentdir_attributes are optional. 00069 * parentdir_handle is mandatory, 00070 * because, we do not allow to delete FS root ! 00071 */ 00072 if(!parentdir_handle || !p_context || !p_object_name) 00073 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_unlink); 00074 00075 /* set current FS context */ 00076 fsal_set_thread_context(p_context); 00077 00078 /* get parent directory path */ 00079 00080 rc = NamespacePath(parentdir_handle->data.inode, 00081 parentdir_handle->data.device, parentdir_handle->data.validator, parent_path); 00082 if(rc) 00083 Return(ERR_FSAL_STALE, rc, INDEX_FSAL_unlink); 00084 00085 /* We have to know what type of entry it is, 00086 * to switch between "unlink" and "rmdir". 00087 * 00088 * To do this, do a getattr. 00089 */ 00090 FSAL_internal_append_path(child_path, parent_path, p_object_name->name); 00091 00092 TakeTokenFSCall(); 00093 rc = p_fs_ops->getattr(child_path, &stbuff); 00094 ReleaseTokenFSCall(); 00095 00096 if(rc) 00097 Return(fuse2fsal_error(rc, FALSE), rc, INDEX_FSAL_unlink); 00098 00099 /* check type */ 00100 00101 if(posix2fsal_type(stbuff.st_mode) == FSAL_TYPE_DIR) 00102 { 00103 /* proceed rmdir call */ 00104 00105 /* operation not provided by filesystem */ 00106 if(!p_fs_ops->rmdir) 00107 Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_unlink); 00108 00109 TakeTokenFSCall(); 00110 rc = p_fs_ops->rmdir(child_path); 00111 ReleaseTokenFSCall(); 00112 00113 } 00114 else 00115 { 00116 /* proceed unlink call */ 00117 00118 /* operation not provided by filesystem */ 00119 if(!p_fs_ops->unlink) 00120 Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_unlink); 00121 00122 TakeTokenFSCall(); 00123 rc = p_fs_ops->unlink(child_path); 00124 ReleaseTokenFSCall(); 00125 00126 } 00127 00128 if(rc == 0 || rc == -ENOENT) 00129 { 00130 /* remove the entry from namespace */ 00131 NamespaceRemove(parentdir_handle->data.inode, parentdir_handle->data.device, 00132 parentdir_handle->data.validator, p_object_name->name); 00133 } 00134 00135 if(rc) 00136 Return(fuse2fsal_error(rc, FALSE), rc, INDEX_FSAL_unlink); 00137 00138 if(parentdir_attributes) 00139 { 00140 st = FUSEFSAL_getattrs(parentdir_handle, p_context, parentdir_attributes); 00141 00142 /* On error, we set a flag in the returned attributes */ 00143 00144 if(FSAL_IS_ERROR(st)) 00145 { 00146 FSAL_CLEAR_MASK(parentdir_attributes->asked_attributes); 00147 FSAL_SET_MASK(parentdir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00148 } 00149 } 00150 00151 /* OK */ 00152 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_unlink); 00153 00154 }