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 00032 #ifdef HAVE_CONFIG_H 00033 #include "config.h" 00034 #endif 00035 00036 #include "fsal.h" 00037 #include "fsal_internal.h" 00038 #include "FSAL/access_check.h" 00039 #include "fsal_convert.h" 00040 #include <sys/types.h> 00041 #include <unistd.h> 00042 #include <utime.h> 00043 #include <sys/time.h> 00044 00045 extern fsal_status_t posixstat64_2_fsal_attributes(struct stat64 *p_buffstat, 00046 fsal_attrib_list_t * p_fsalattr_out); 00047 00067 fsal_status_t VFSFSAL_getattrs(fsal_handle_t * p_filehandle, /* IN */ 00068 fsal_op_context_t * p_context, /* IN */ 00069 fsal_attrib_list_t * p_object_attributes /* IN/OUT */ 00070 ) 00071 { 00072 fsal_status_t st; 00073 int rc = 0 ; 00074 int errsv; 00075 struct stat buffstat; 00076 00077 /* sanity checks. 00078 * note : object_attributes is mandatory in VFSFSAL_getattrs. 00079 */ 00080 if(!p_filehandle || !p_context || !p_object_attributes) 00081 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_getattrs); 00082 00083 TakeTokenFSCall(); 00084 rc = vfs_stat_by_handle( ((vfsfsal_op_context_t *)p_context)->export_context->mount_root_fd, 00085 &((vfsfsal_handle_t *)p_filehandle)->data.vfs_handle, 00086 &buffstat ) ; 00087 errsv = errno; 00088 ReleaseTokenFSCall(); 00089 00090 if( rc == -1 ) 00091 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_getattrs); 00092 00093 /* convert attributes */ 00094 st = posix2fsal_attributes(&buffstat, p_object_attributes); 00095 if(FSAL_IS_ERROR(st)) 00096 { 00097 FSAL_CLEAR_MASK(p_object_attributes->asked_attributes); 00098 FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00099 ReturnStatus(st, INDEX_FSAL_getattrs); 00100 } 00101 00102 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_getattrs); 00103 00104 } 00105 00127 fsal_status_t VFSFSAL_getattrs_descriptor(fsal_file_t * p_file_descriptor, /* IN */ 00128 fsal_handle_t * p_filehandle, /* IN */ 00129 fsal_op_context_t * p_context, /* IN */ 00130 fsal_attrib_list_t * p_object_attributes /* IN/OUT */ 00131 ) 00132 { 00133 fsal_status_t st; 00134 struct stat64 buffstat; 00135 int rc, errsv; 00136 00137 /* sanity checks. 00138 * note : object_attributes is mandatory in VFSFSAL_getattrs. 00139 */ 00140 if(!p_file_descriptor || !p_filehandle || !p_context || !p_object_attributes) 00141 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_getattrs_descriptor); 00142 00143 TakeTokenFSCall(); 00144 rc = fstat64(((vfsfsal_file_t *)p_file_descriptor)->fd, &buffstat); 00145 errsv = errno; 00146 ReleaseTokenFSCall(); 00147 00148 if(rc == -1) 00149 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_getattrs_descriptor); 00150 00151 /* convert attributes */ 00152 st = posixstat64_2_fsal_attributes(&buffstat, p_object_attributes); 00153 if(FSAL_IS_ERROR(st)) 00154 { 00155 FSAL_CLEAR_MASK(p_object_attributes->asked_attributes); 00156 FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00157 ReturnStatus(st, INDEX_FSAL_getattrs_descriptor); 00158 } 00159 00160 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_getattrs_descriptor); 00161 00162 } 00163 00188 fsal_status_t VFSFSAL_setattrs(fsal_handle_t * p_filehandle, /* IN */ 00189 fsal_op_context_t * p_context, /* IN */ 00190 fsal_attrib_list_t * p_attrib_set, /* IN */ 00191 fsal_attrib_list_t * p_object_attributes /* [ IN/OUT ] */ 00192 ) 00193 { 00194 vfsfsal_op_context_t * vfs_context = (vfsfsal_op_context_t *) p_context; 00195 int rc, errsv; 00196 unsigned int i; 00197 fsal_status_t status; 00198 fsal_attrib_list_t attrs; 00199 00200 int fd; 00201 struct stat buffstat; 00202 00203 /* sanity checks. 00204 * note : object_attributes is optional. 00205 */ 00206 if(!p_filehandle || !p_context || !p_attrib_set) 00207 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_setattrs); 00208 00209 /* local copy of attributes */ 00210 attrs = *p_attrib_set; 00211 00212 /* It does not make sense to setattr on a symlink */ 00213 /* if(p_filehandle->type == DT_LNK) 00214 return fsal_internal_setattrs_symlink(p_filehandle, p_context, p_attrib_set, 00215 p_object_attributes); 00216 */ 00217 /* First, check that FSAL attributes changes are allowed. */ 00218 00219 /* Is it allowed to change times ? */ 00220 00221 if(!global_fs_info.cansettime) 00222 { 00223 00224 if(attrs.asked_attributes 00225 & (FSAL_ATTR_ATIME | FSAL_ATTR_CREATION | FSAL_ATTR_CTIME | FSAL_ATTR_MTIME)) 00226 { 00227 /* handled as an unsettable attribute. */ 00228 Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_setattrs); 00229 } 00230 } 00231 00232 /* apply umask, if mode attribute is to be changed */ 00233 if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MODE)) 00234 { 00235 attrs.mode &= (~global_fs_info.umask); 00236 } 00237 00238 TakeTokenFSCall(); 00239 status = fsal_internal_handle2fd(p_context, p_filehandle, &fd, O_RDONLY); 00240 ReleaseTokenFSCall(); 00241 if(FSAL_IS_ERROR(status)) 00242 { 00243 /* Symbolic link are handled here, they are to be opened as O_PATH */ 00244 if( status.minor == ELOOP ) 00245 { 00246 if(p_object_attributes) 00247 { 00248 status = VFSFSAL_getattrs(p_filehandle, p_context, p_object_attributes); 00249 00250 /* on error, we set a special bit in the mask. */ 00251 if(FSAL_IS_ERROR(status)) 00252 { 00253 FSAL_CLEAR_MASK(p_object_attributes->asked_attributes); 00254 FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00255 } 00256 } 00257 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_setattrs); 00258 } 00259 00260 ReturnStatus( status, INDEX_FSAL_setattrs); 00261 } 00262 00263 /* get current attributes */ 00264 TakeTokenFSCall(); 00265 rc = fstat(fd, &buffstat); 00266 errsv = errno; 00267 ReleaseTokenFSCall(); 00268 00269 if(rc != 0) 00270 { 00271 close(fd); 00272 00273 if(errsv == ENOENT) 00274 Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_setattrs); 00275 else 00276 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_setattrs); 00277 } 00278 00279 /*********** 00280 * CHMOD * 00281 ***********/ 00282 if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MODE)) 00283 { 00284 00285 /* The POSIX chmod call don't affect the symlink object, but 00286 * the entry it points to. So we must ignore it. 00287 */ 00288 if(!S_ISLNK(buffstat.st_mode)) 00289 { 00290 00291 /* For modifying mode, user must be root or the owner */ 00292 if((vfs_context->credential.user != 0) 00293 && (vfs_context->credential.user != buffstat.st_uid)) 00294 { 00295 LogFullDebug(COMPONENT_FSAL, 00296 "Permission denied for CHMOD opeartion: current owner=%d, credential=%d", 00297 buffstat.st_uid, vfs_context->credential.user); 00298 close(fd); 00299 Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs); 00300 } 00301 00302 TakeTokenFSCall(); 00303 rc = fchmod(fd, fsal2unix_mode(attrs.mode)); 00304 errsv = errno; 00305 ReleaseTokenFSCall(); 00306 00307 if(rc) 00308 { 00309 close(fd); 00310 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_setattrs); 00311 } 00312 00313 } 00314 00315 } 00316 00317 /*********** 00318 * CHOWN * 00319 ***********/ 00320 /* Only root can change uid and A normal user must be in the group he wants to set */ 00321 if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_OWNER)) 00322 { 00323 00324 /* For modifying owner, user must be root or current owner==wanted==client */ 00325 if((vfs_context->credential.user != 0) && 00326 ((vfs_context->credential.user != buffstat.st_uid) || 00327 (vfs_context->credential.user != attrs.owner))) 00328 { 00329 LogFullDebug(COMPONENT_FSAL, 00330 "Permission denied for CHOWN opeartion: current owner=%d, credential=%d, new owner=%d", 00331 buffstat.st_uid, vfs_context->credential.user, attrs.owner); 00332 close(fd); 00333 Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs); 00334 } 00335 } 00336 00337 if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_GROUP)) 00338 { 00339 00340 /* For modifying group, user must be root or current owner */ 00341 if((vfs_context->credential.user != 0) 00342 && (vfs_context->credential.user != buffstat.st_uid)) 00343 { 00344 close(fd); 00345 Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs); 00346 } 00347 00348 int in_grp = 0; 00349 /* set in_grp */ 00350 if(vfs_context->credential.group == attrs.group) 00351 in_grp = 1; 00352 else 00353 for(i = 0; i < vfs_context->credential.nbgroups; i++) 00354 { 00355 if((in_grp = (attrs.group == vfs_context->credential.alt_groups[i]))) 00356 break; 00357 } 00358 00359 /* it must also be in target group */ 00360 if(vfs_context->credential.user != 0 && !in_grp) 00361 { 00362 LogFullDebug(COMPONENT_FSAL, 00363 "Permission denied for CHOWN operation: current group=%d, credential=%d, new group=%d", 00364 buffstat.st_gid, vfs_context->credential.group, attrs.group); 00365 close(fd); 00366 Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs); 00367 } 00368 } 00369 00370 if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_OWNER | FSAL_ATTR_GROUP)) 00371 { 00372 /* LogFullDebug(COMPONENT_FSAL, "Performing chown(%s, %d,%d)", 00373 fsalpath.path, FSAL_TEST_MASK(attrs.asked_attributes, 00374 FSAL_ATTR_OWNER) ? (int)attrs.owner 00375 : -1, FSAL_TEST_MASK(attrs.asked_attributes, 00376 FSAL_ATTR_GROUP) ? (int)attrs.group : -1);*/ 00377 00378 TakeTokenFSCall(); 00379 rc = fchown(fd, 00380 FSAL_TEST_MASK(attrs.asked_attributes, 00381 FSAL_ATTR_OWNER) ? (int)attrs.owner : -1, 00382 FSAL_TEST_MASK(attrs.asked_attributes, 00383 FSAL_ATTR_GROUP) ? (int)attrs.group : -1); 00384 ReleaseTokenFSCall(); 00385 if(rc) 00386 { 00387 close(fd); 00388 Return(posix2fsal_error(errno), errno, INDEX_FSAL_setattrs); 00389 } 00390 } 00391 00392 /*********** 00393 * UTIME * 00394 ***********/ 00395 00396 /* user must be the owner or have read access to modify 'atime' */ 00397 if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME) 00398 && (vfs_context->credential.user != 0) 00399 && (vfs_context->credential.user != buffstat.st_uid) 00400 && ((status = fsal_check_access(p_context, FSAL_R_OK, &buffstat, NULL)).major 00401 != ERR_FSAL_NO_ERROR)) 00402 { 00403 close(fd); 00404 ReturnStatus(status, INDEX_FSAL_setattrs); 00405 } 00406 /* user must be the owner or have write access to modify 'mtime' */ 00407 if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MTIME) 00408 && (vfs_context->credential.user != 0) 00409 && (vfs_context->credential.user != buffstat.st_uid) 00410 && ((status = fsal_check_access(p_context, FSAL_W_OK, &buffstat, NULL)).major 00411 != ERR_FSAL_NO_ERROR)) 00412 { 00413 close(fd); 00414 ReturnStatus(status, INDEX_FSAL_setattrs); 00415 } 00416 00417 if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME | FSAL_ATTR_MTIME)) 00418 { 00419 00420 struct timeval timebuf[2]; 00421 00422 /* Atime */ 00423 timebuf[0].tv_sec = 00424 (FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME) ? (time_t) attrs. 00425 atime.seconds : buffstat.st_atime); 00426 timebuf[0].tv_usec = 0; 00427 00428 /* Mtime */ 00429 timebuf[1].tv_sec = 00430 (FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MTIME) ? (time_t) attrs. 00431 mtime.seconds : buffstat.st_mtime); 00432 timebuf[1].tv_usec = 0; 00433 00434 TakeTokenFSCall(); 00435 rc = futimes(fd, timebuf); 00436 errsv = errno; 00437 ReleaseTokenFSCall(); 00438 if(rc) 00439 { 00440 close(fd); 00441 Return(posix2fsal_error(errno), errno, INDEX_FSAL_setattrs); 00442 } 00443 } 00444 00445 /* Optionaly fills output attributes. */ 00446 00447 if(p_object_attributes) 00448 { 00449 status = VFSFSAL_getattrs(p_filehandle, p_context, p_object_attributes); 00450 00451 /* on error, we set a special bit in the mask. */ 00452 if(FSAL_IS_ERROR(status)) 00453 { 00454 FSAL_CLEAR_MASK(p_object_attributes->asked_attributes); 00455 FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00456 } 00457 00458 } 00459 00460 close(fd); 00461 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_setattrs); 00462 00463 }