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 00056 fsal_status_t POSIXFSAL_rename(fsal_handle_t * old_parentdir_handle, /* IN */ 00057 fsal_name_t * p_old_name, /* IN */ 00058 fsal_handle_t * new_parentdir_handle, /* IN */ 00059 fsal_name_t * p_new_name, /* IN */ 00060 fsal_op_context_t * 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 posixfsal_handle_t * p_old_parentdir_handle 00066 = (posixfsal_handle_t *) old_parentdir_handle; 00067 posixfsal_handle_t * p_new_parentdir_handle 00068 = (posixfsal_handle_t *) new_parentdir_handle; 00069 posixfsal_op_context_t * p_context = (posixfsal_op_context_t *) context; 00070 int rc, errsv; 00071 fsal_status_t status; 00072 fsal_posixdb_status_t statusdb; 00073 struct stat old_parent_buffstat, new_parent_buffstat, buffstat; 00074 fsal_path_t old_fsalpath, new_fsalpath; 00075 fsal_posixdb_fileinfo_t info; 00076 00077 /* sanity checks. 00078 * note : src/tgt_dir_attributes are optional. 00079 */ 00080 if(!p_old_parentdir_handle || 00081 !p_new_parentdir_handle || !p_old_name || !p_new_name || !p_context) 00082 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_rename); 00083 00084 /************************************** 00085 * Build the old path and the new one * 00086 **************************************/ 00087 status = 00088 fsal_internal_getPathFromHandle(p_context, p_old_parentdir_handle, 1, &old_fsalpath, 00089 &old_parent_buffstat); 00090 if(FSAL_IS_ERROR(status)) 00091 Return(status.major, status.minor, INDEX_FSAL_rename); 00092 00093 /* optimisation : don't do the work two times if source dir = dest dir */ 00094 if(!POSIXFSAL_handlecmp(p_old_parentdir_handle, p_new_parentdir_handle, &status)) 00095 { 00096 FSAL_pathcpy(&new_fsalpath, &old_fsalpath); 00097 new_parent_buffstat = old_parent_buffstat; 00098 } 00099 else 00100 { 00101 status = 00102 fsal_internal_getPathFromHandle(p_context, p_new_parentdir_handle, 1, 00103 &new_fsalpath, &new_parent_buffstat); 00104 if(FSAL_IS_ERROR(status)) 00105 Return(status.major, status.minor, INDEX_FSAL_rename); 00106 } 00107 00108 status = fsal_internal_appendFSALNameToFSALPath(&old_fsalpath, p_old_name); 00109 if(FSAL_IS_ERROR(status)) 00110 Return(status.major, status.minor, INDEX_FSAL_mkdir); 00111 status = fsal_internal_appendFSALNameToFSALPath(&new_fsalpath, p_new_name); 00112 if(FSAL_IS_ERROR(status)) 00113 Return(status.major, status.minor, INDEX_FSAL_mkdir); 00114 00115 TakeTokenFSCall(); 00116 rc = lstat(old_fsalpath.path, &buffstat); 00117 errsv = errno; 00118 ReleaseTokenFSCall(); 00119 if(rc) 00120 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rename); 00121 00122 if(FSAL_IS_ERROR(status = fsal_internal_posix2posixdb_fileinfo(&buffstat, &info))) 00123 Return(status.major, status.minor, INDEX_FSAL_rename); 00124 00125 /******************** 00126 * Check credential * 00127 ********************/ 00128 00129 if(FSAL_IS_ERROR 00130 (status = 00131 fsal_internal_testAccess(p_context, FSAL_W_OK | FSAL_X_OK, &old_parent_buffstat, 00132 NULL))) 00133 Return(status.major, status.minor, INDEX_FSAL_rename); 00134 00135 if(FSAL_IS_ERROR 00136 (status = 00137 fsal_internal_testAccess(p_context, FSAL_W_OK | FSAL_X_OK, &new_parent_buffstat, 00138 NULL))) 00139 Return(status.major, status.minor, INDEX_FSAL_rename); 00140 00141 /* Check sticky bit on directories */ 00142 00143 if((old_parent_buffstat.st_mode & S_ISVTX) /* Sticky bit on the directory => the user who wants to delete the file must own it or its parent dir */ 00144 && old_parent_buffstat.st_uid != p_context->credential.user 00145 && buffstat.st_uid != p_context->credential.user && p_context->credential.user != 0) 00146 Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_rename); 00147 00148 if(new_parent_buffstat.st_mode & S_ISVTX) 00149 { /* Sticky bit on the directory => the user who wants to delete the file must own it or its parent dir */ 00150 TakeTokenFSCall(); 00151 rc = lstat(new_fsalpath.path, &buffstat); 00152 errsv = errno; 00153 ReleaseTokenFSCall(); 00154 if(rc) 00155 { 00156 if(errsv != ENOENT) 00157 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rename); 00158 } 00159 else if(new_parent_buffstat.st_uid != p_context->credential.user 00160 && buffstat.st_uid != p_context->credential.user 00161 && p_context->credential.user != 0) 00162 Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_rename); 00163 } 00164 /************************************* 00165 * Rename the file on the filesystem * 00166 *************************************/ 00167 TakeTokenFSCall(); 00168 rc = rename(old_fsalpath.path, new_fsalpath.path); 00169 errsv = errno; 00170 ReleaseTokenFSCall(); 00171 00172 if(rc) 00173 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rename); 00174 00175 /*********************************** 00176 * Rename the file in the database * 00177 ***********************************/ 00178 statusdb = fsal_posixdb_replace(p_context->p_conn, 00179 &info, 00180 p_old_parentdir_handle, 00181 p_old_name, p_new_parentdir_handle, p_new_name); 00182 00183 switch (statusdb.major) 00184 { 00185 case ERR_FSAL_POSIXDB_NOENT: 00186 case ERR_FSAL_POSIXDB_NOERR: 00187 break; 00188 default: 00189 if(FSAL_IS_ERROR(status = posixdb2fsal_error(statusdb))) 00190 Return(status.major, status.minor, INDEX_FSAL_rename); 00191 } 00192 00193 /*********************** 00194 * Fill the attributes * 00195 ***********************/ 00196 00197 if(p_src_dir_attributes) 00198 { 00199 00200 status = 00201 POSIXFSAL_getattrs(p_old_parentdir_handle, p_context, p_src_dir_attributes); 00202 00203 if(FSAL_IS_ERROR(status)) 00204 { 00205 FSAL_CLEAR_MASK(p_src_dir_attributes->asked_attributes); 00206 FSAL_SET_MASK(p_src_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00207 } 00208 00209 } 00210 00211 if(p_tgt_dir_attributes) 00212 { 00213 00214 status = 00215 POSIXFSAL_getattrs(p_new_parentdir_handle, p_context, p_tgt_dir_attributes); 00216 00217 if(FSAL_IS_ERROR(status)) 00218 { 00219 FSAL_CLEAR_MASK(p_tgt_dir_attributes->asked_attributes); 00220 FSAL_SET_MASK(p_tgt_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00221 } 00222 00223 } 00224 00225 /* OK */ 00226 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_rename); 00227 00228 }