nfs-ganesha 1.4
|
00001 /* 00002 * vim:expandtab:shiftwidth=8:tabstop=8: 00003 * 00004 * Copyright CEA/DAM/DIF (2008) 00005 * contributeur : Philippe DENIEL philippe.deniel@cea.fr 00006 * Thomas LEIBOVICI thomas.leibovici@cea.fr 00007 * 00008 * 00009 * This program is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 3 of the License, or (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * Lesser General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU Lesser General Public 00020 * License along with this library; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00022 * 00023 * ------------- 00024 */ 00025 00035 #ifdef HAVE_CONFIG_H 00036 #include "config.h" 00037 #endif 00038 00039 #include "fsal.h" 00040 #include "fsal_internal.h" 00041 #include "fsal_convert.h" 00042 00077 fsal_status_t GPFSFSAL_rename(fsal_handle_t * p_old_parentdir_handle, /* IN */ 00078 fsal_name_t * p_old_name, /* IN */ 00079 fsal_handle_t * p_new_parentdir_handle, /* IN */ 00080 fsal_name_t * p_new_name, /* IN */ 00081 fsal_op_context_t * p_context, /* IN */ 00082 fsal_attrib_list_t * p_src_dir_attributes, /* [ IN/OUT ] */ 00083 fsal_attrib_list_t * p_tgt_dir_attributes /* [ IN/OUT ] */ 00084 ) 00085 { 00086 00087 fsal_status_t status; 00088 struct stat buffstat; 00089 int src_equal_tgt = FALSE; 00090 fsal_accessflags_t access_mask = 0; 00091 fsal_attrib_list_t src_dir_attrs, tgt_dir_attrs; 00092 00093 /* sanity checks. 00094 * note : src/tgt_dir_attributes are optional. 00095 */ 00096 if(!p_old_parentdir_handle || !p_new_parentdir_handle 00097 || !p_old_name || !p_new_name || !p_context) 00098 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_rename); 00099 00100 /* retrieve directory metadata for checking access rights */ 00101 00102 src_dir_attrs.asked_attributes = GPFS_SUPPORTED_ATTRIBUTES; 00103 status = GPFSFSAL_getattrs(p_old_parentdir_handle, p_context, &src_dir_attrs); 00104 if(FSAL_IS_ERROR(status)) 00105 { 00106 ReturnStatus(status, INDEX_FSAL_rename); 00107 } 00108 00109 /* optimisation : don't do the job twice if source dir = dest dir */ 00110 if(!FSAL_handlecmp(p_old_parentdir_handle, p_new_parentdir_handle, &status)) 00111 { 00112 src_equal_tgt = TRUE; 00113 tgt_dir_attrs = src_dir_attrs; 00114 } 00115 else 00116 { 00117 /* retrieve destination attrs */ 00118 tgt_dir_attrs.asked_attributes = GPFS_SUPPORTED_ATTRIBUTES; 00119 status = GPFSFSAL_getattrs(p_new_parentdir_handle, p_context, &tgt_dir_attrs); 00120 if(FSAL_IS_ERROR(status)) 00121 { 00122 ReturnStatus(status, INDEX_FSAL_rename); 00123 } 00124 } 00125 00126 /* check access rights */ 00127 00128 /* Set both mode and ace4 mask */ 00129 access_mask = FSAL_MODE_MASK_SET(FSAL_W_OK | FSAL_X_OK) | 00130 FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_DELETE_CHILD); 00131 00132 if(!p_context->export_context->fe_static_fs_info->accesscheck_support) 00133 status = fsal_internal_testAccess(p_context, access_mask, NULL, &src_dir_attrs); 00134 else 00135 status = fsal_internal_access(p_context, p_old_parentdir_handle, access_mask, 00136 &src_dir_attrs); 00137 if(FSAL_IS_ERROR(status)) { 00138 ReturnStatus(status, INDEX_FSAL_rename); 00139 } 00140 00141 if(!src_equal_tgt) 00142 { 00143 access_mask = FSAL_MODE_MASK_SET(FSAL_W_OK | FSAL_X_OK) | 00144 FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_ADD_FILE | 00145 FSAL_ACE_PERM_ADD_SUBDIRECTORY); 00146 00147 if(!p_context->export_context->fe_static_fs_info->accesscheck_support) 00148 status = fsal_internal_testAccess(p_context, access_mask, NULL, &tgt_dir_attrs); 00149 else 00150 status = fsal_internal_access(p_context, p_new_parentdir_handle, access_mask, 00151 &tgt_dir_attrs); 00152 if(FSAL_IS_ERROR(status)) { 00153 ReturnStatus(status, INDEX_FSAL_rename); 00154 } 00155 } 00156 00157 /* build file paths */ 00158 TakeTokenFSCall(); 00159 status = fsal_internal_stat_name(p_context, p_old_parentdir_handle, p_old_name, &buffstat); 00160 ReleaseTokenFSCall(); 00161 if(FSAL_IS_ERROR(status)) 00162 ReturnStatus(status, INDEX_FSAL_rename); 00163 00164 /* Check sticky bits */ 00165 00166 /* Sticky bit on the source directory => the user who wants to delete the file must own it or its parent dir */ 00167 if((fsal2unix_mode(src_dir_attrs.mode) & S_ISVTX) && 00168 src_dir_attrs.owner != p_context->credential.user && 00169 buffstat.st_uid != p_context->credential.user && p_context->credential.user != 0) { 00170 Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_rename); 00171 } 00172 00173 /* Sticky bit on the target directory => the user who wants to create the file must own it or its parent dir */ 00174 if(fsal2unix_mode(tgt_dir_attrs.mode) & S_ISVTX) 00175 { 00176 TakeTokenFSCall(); 00177 status = fsal_internal_stat_name(p_context, p_new_parentdir_handle, p_new_name, &buffstat); 00178 ReleaseTokenFSCall(); 00179 00180 if(FSAL_IS_ERROR(status)) 00181 { 00182 if(status.major != ERR_FSAL_NOENT) 00183 { 00184 ReturnStatus(status, INDEX_FSAL_rename); 00185 } 00186 } 00187 else 00188 { 00189 00190 if(tgt_dir_attrs.owner != p_context->credential.user 00191 && buffstat.st_uid != p_context->credential.user 00192 && p_context->credential.user != 0) 00193 { 00194 Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_rename); 00195 } 00196 } 00197 } 00198 00199 /************************************* 00200 * Rename the file on the filesystem * 00201 *************************************/ 00202 TakeTokenFSCall(); 00203 status = fsal_internal_rename_fh(p_context, p_old_parentdir_handle, 00204 p_new_parentdir_handle, p_old_name, 00205 p_new_name); 00206 ReleaseTokenFSCall(); 00207 00208 if(FSAL_IS_ERROR(status)) 00209 ReturnStatus(status, INDEX_FSAL_rename); 00210 00211 /*********************** 00212 * Fill the attributes * 00213 ***********************/ 00214 00215 if(p_src_dir_attributes) 00216 { 00217 00218 status = GPFSFSAL_getattrs(p_old_parentdir_handle, p_context, p_src_dir_attributes); 00219 00220 if(FSAL_IS_ERROR(status)) 00221 { 00222 FSAL_CLEAR_MASK(p_src_dir_attributes->asked_attributes); 00223 FSAL_SET_MASK(p_src_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00224 } 00225 00226 } 00227 00228 if(p_tgt_dir_attributes) 00229 { 00230 00231 status = GPFSFSAL_getattrs(p_new_parentdir_handle, p_context, p_tgt_dir_attributes); 00232 00233 if(FSAL_IS_ERROR(status)) 00234 { 00235 FSAL_CLEAR_MASK(p_tgt_dir_attributes->asked_attributes); 00236 FSAL_SET_MASK(p_tgt_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00237 } 00238 00239 } 00240 00241 /* OK */ 00242 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_rename); 00243 00244 }