nfs-ganesha 1.4
|
00001 /* 00002 * vim:expandtab:shiftwidth=4:tabstop=4: 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 00056 fsal_status_t LUSTREFSAL_rename(fsal_handle_t * p_old_parentdir_handle, /* IN */ 00057 fsal_name_t * p_old_name, /* IN */ 00058 fsal_handle_t * p_new_parentdir_handle, /* IN */ 00059 fsal_name_t * p_new_name, /* IN */ 00060 fsal_op_context_t * p_context, /* IN */ 00061 fsal_attrib_list_t * p_src_dir_attributes, /* [ IN/OUT ] */ 00062 fsal_attrib_list_t * p_tgt_dir_attributes /* [ IN/OUT ] */ 00063 ) 00064 { 00065 00066 int rc, errsv; 00067 fsal_status_t status; 00068 struct stat old_parent_buffstat, new_parent_buffstat, buffstat; 00069 fsal_path_t old_fsalpath, new_fsalpath; 00070 int src_equal_tgt = FALSE; 00071 00072 /* sanity checks. 00073 * note : src/tgt_dir_attributes are optional. 00074 */ 00075 if(!p_old_parentdir_handle || !p_new_parentdir_handle 00076 || !p_old_name || !p_new_name || !p_context) 00077 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_rename); 00078 00079 /* Get directory access path by fid */ 00080 00081 status = fsal_internal_Handle2FidPath(p_context, p_old_parentdir_handle, &old_fsalpath); 00082 if(FSAL_IS_ERROR(status)) 00083 ReturnStatus(status, INDEX_FSAL_rename); 00084 00085 /* retrieve directory metadata for checking access rights */ 00086 00087 TakeTokenFSCall(); 00088 rc = lstat(old_fsalpath.path, &old_parent_buffstat); 00089 errsv = errno; 00090 ReleaseTokenFSCall(); 00091 00092 if(rc) 00093 { 00094 if(errsv == ENOENT) 00095 Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_rename); 00096 else 00097 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rename); 00098 } 00099 00100 /* optimisation : don't do the job twice if source dir = dest dir */ 00101 if(!LUSTREFSAL_handlecmp(p_old_parentdir_handle, p_new_parentdir_handle, &status)) 00102 { 00103 FSAL_pathcpy(&new_fsalpath, &old_fsalpath); 00104 src_equal_tgt = TRUE; 00105 new_parent_buffstat = old_parent_buffstat; 00106 } 00107 else 00108 { 00109 status = 00110 fsal_internal_Handle2FidPath(p_context, p_new_parentdir_handle, &new_fsalpath); 00111 if(FSAL_IS_ERROR(status)) 00112 ReturnStatus(status, INDEX_FSAL_rename); 00113 00114 /* retrieve destination attrs */ 00115 TakeTokenFSCall(); 00116 rc = lstat(new_fsalpath.path, &new_parent_buffstat); 00117 errsv = errno; 00118 ReleaseTokenFSCall(); 00119 00120 if(rc) 00121 { 00122 if(errsv == ENOENT) 00123 Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_rename); 00124 else 00125 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rename); 00126 } 00127 00128 } 00129 00130 /* check access rights */ 00131 00132 status = 00133 fsal_internal_testAccess(p_context, FSAL_W_OK | FSAL_X_OK, &old_parent_buffstat, 00134 NULL); 00135 if(FSAL_IS_ERROR(status)) 00136 ReturnStatus(status, INDEX_FSAL_rename); 00137 00138 if(!src_equal_tgt) 00139 { 00140 status = 00141 fsal_internal_testAccess(p_context, FSAL_W_OK | FSAL_X_OK, &new_parent_buffstat, 00142 NULL); 00143 if(FSAL_IS_ERROR(status)) 00144 ReturnStatus(status, INDEX_FSAL_rename); 00145 } 00146 00147 /* build file paths */ 00148 00149 status = fsal_internal_appendNameToPath(&old_fsalpath, p_old_name); 00150 if(FSAL_IS_ERROR(status)) 00151 Return(status.major, status.minor, INDEX_FSAL_rename); 00152 status = fsal_internal_appendNameToPath(&new_fsalpath, p_new_name); 00153 if(FSAL_IS_ERROR(status)) 00154 Return(status.major, status.minor, INDEX_FSAL_rename); 00155 00156 TakeTokenFSCall(); 00157 rc = lstat(old_fsalpath.path, &buffstat); 00158 errsv = errno; 00159 ReleaseTokenFSCall(); 00160 if(rc) 00161 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rename); 00162 00163 /* Check sticky bits */ 00164 00165 /* Sticky bit on the source directory => the user who wants to delete the file must own it or its parent dir */ 00166 if((old_parent_buffstat.st_mode & S_ISVTX) 00167 && old_parent_buffstat.st_uid != p_context->credential.user 00168 && buffstat.st_uid != p_context->credential.user && p_context->credential.user != 0) 00169 Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_rename); 00170 00171 /* Sticky bit on the target directory => the user who wants to create the file must own it or its parent dir */ 00172 if(new_parent_buffstat.st_mode & S_ISVTX) 00173 { 00174 TakeTokenFSCall(); 00175 rc = lstat(new_fsalpath.path, &buffstat); 00176 errsv = errno; 00177 ReleaseTokenFSCall(); 00178 if(rc) 00179 { 00180 if(errsv != ENOENT) 00181 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rename); 00182 } 00183 else if(new_parent_buffstat.st_uid != p_context->credential.user 00184 && buffstat.st_uid != p_context->credential.user 00185 && p_context->credential.user != 0) 00186 Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_rename); 00187 } 00188 00189 /************************************* 00190 * Rename the file on the filesystem * 00191 *************************************/ 00192 TakeTokenFSCall(); 00193 rc = rename(old_fsalpath.path, new_fsalpath.path); 00194 errsv = errno; 00195 ReleaseTokenFSCall(); 00196 00197 if(rc) 00198 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rename); 00199 00200 /*********************** 00201 * Fill the attributes * 00202 ***********************/ 00203 00204 if(p_src_dir_attributes) 00205 { 00206 00207 status = 00208 LUSTREFSAL_getattrs(p_old_parentdir_handle, p_context, p_src_dir_attributes); 00209 00210 if(FSAL_IS_ERROR(status)) 00211 { 00212 FSAL_CLEAR_MASK(p_src_dir_attributes->asked_attributes); 00213 FSAL_SET_MASK(p_src_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00214 } 00215 00216 } 00217 00218 if(p_tgt_dir_attributes) 00219 { 00220 00221 status = 00222 LUSTREFSAL_getattrs(p_new_parentdir_handle, p_context, p_tgt_dir_attributes); 00223 00224 if(FSAL_IS_ERROR(status)) 00225 { 00226 FSAL_CLEAR_MASK(p_tgt_dir_attributes->asked_attributes); 00227 FSAL_SET_MASK(p_tgt_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00228 } 00229 00230 } 00231 00232 /* OK */ 00233 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_rename); 00234 00235 }