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_convert.h" 00039 #include <sys/types.h> 00040 #include <unistd.h> 00041 #include <utime.h> 00042 #include <sys/time.h> 00043 00044 extern fsal_status_t gpfsfsal_xstat_2_fsal_attributes(gpfsfsal_xstat_t *p_buffxstat, 00045 fsal_attrib_list_t *p_fsalattr_out); 00046 00047 #ifdef _USE_NFS4_ACL 00048 extern fsal_status_t fsal_acl_2_gpfs_acl(fsal_acl_t *p_fsalacl, gpfsfsal_xstat_t *p_buffxstat); 00049 #endif /* _USE_NFS4_ACL */ 00050 00070 fsal_status_t GPFSFSAL_getattrs(fsal_handle_t * p_filehandle, /* IN */ 00071 fsal_op_context_t * p_context, /* IN */ 00072 fsal_attrib_list_t * p_object_attributes /* IN/OUT */ 00073 ) 00074 { 00075 fsal_status_t st; 00076 gpfsfsal_xstat_t buffxstat; 00077 00078 #ifdef _USE_NFS4_ACL 00079 fsal_accessflags_t access_mask = 0; 00080 #endif 00081 00082 /* sanity checks. 00083 * note : object_attributes is mandatory in GPFSFSAL_getattrs. 00084 */ 00085 if(!p_filehandle || !p_context || !p_object_attributes) 00086 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_getattrs); 00087 00088 TakeTokenFSCall(); 00089 st = fsal_get_xstat_by_handle(p_context, 00090 p_filehandle, 00091 &buffxstat); 00092 ReleaseTokenFSCall(); 00093 00094 if(FSAL_IS_ERROR(st)) 00095 ReturnStatus(st, INDEX_FSAL_getattrs); 00096 00097 /* convert attributes */ 00098 st = gpfsfsal_xstat_2_fsal_attributes(&buffxstat, p_object_attributes); 00099 if(FSAL_IS_ERROR(st)) 00100 { 00101 FSAL_CLEAR_MASK(p_object_attributes->asked_attributes); 00102 FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00103 ReturnStatus(st, INDEX_FSAL_getattrs); 00104 } 00105 00106 #ifdef _USE_NFS4_ACL 00107 /* Check permission to get attributes and ACL. */ 00108 access_mask = FSAL_MODE_MASK_SET(0) | /* Dummy */ 00109 FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_READ_ATTR | 00110 FSAL_ACE_PERM_READ_ACL); 00111 00112 if(!p_context->export_context->fe_static_fs_info->accesscheck_support) 00113 st = fsal_internal_testAccess(p_context, access_mask, NULL, p_object_attributes); 00114 else 00115 st = fsal_internal_access(p_context, p_filehandle, access_mask, 00116 p_object_attributes); 00117 00118 if(FSAL_IS_ERROR(st)) 00119 ReturnStatus(st, INDEX_FSAL_getattrs); 00120 #endif 00121 00122 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_getattrs); 00123 00124 } 00125 00147 fsal_status_t GPFSFSAL_getattrs_descriptor(fsal_file_t * p_file_descriptor, /* IN */ 00148 fsal_handle_t * p_filehandle, /* IN */ 00149 fsal_op_context_t * p_context, /* IN */ 00150 fsal_attrib_list_t * p_object_attributes /* IN/OUT */ 00151 ) 00152 { 00153 return GPFSFSAL_getattrs(p_filehandle, p_context, p_object_attributes); 00154 } 00155 00180 fsal_status_t GPFSFSAL_setattrs(fsal_handle_t * p_filehandle, /* IN */ 00181 fsal_op_context_t * p_context, /* IN */ 00182 fsal_attrib_list_t * p_attrib_set, /* IN */ 00183 fsal_attrib_list_t * p_object_attributes /* [ IN/OUT ] */ 00184 ) 00185 { 00186 unsigned int i; 00187 fsal_status_t status; 00188 00189 /* Buffer that will be passed to gpfs_ganesha API. */ 00190 gpfsfsal_xstat_t buffxstat; 00191 00192 /* Indicate if stat or acl or both should be changed. */ 00193 int attr_valid = 0; 00194 00195 /* Indiate which attribute in stat should be changed. */ 00196 int attr_changed = 0; 00197 00198 fsal_accessflags_t access_mask = 0; 00199 fsal_attrib_list_t wanted_attrs, current_attrs; 00200 00201 /* sanity checks. 00202 * note : object_attributes is optional. 00203 */ 00204 if(!p_filehandle || !p_context || !p_attrib_set) 00205 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_setattrs); 00206 00207 /* local copy of attributes */ 00208 wanted_attrs = *p_attrib_set; 00209 00210 /* It does not make sense to setattr on a symlink */ 00211 /* if(p_filehandle->type == DT_LNK) 00212 return fsal_internal_setattrs_symlink(p_filehandle, p_context, p_attrib_set, 00213 p_object_attributes); 00214 */ 00215 /* First, check that FSAL attributes changes are allowed. */ 00216 00217 /* Is it allowed to change times ? */ 00218 00219 if(!global_fs_info.cansettime) 00220 { 00221 00222 if(wanted_attrs.asked_attributes 00223 & (FSAL_ATTR_ATIME | FSAL_ATTR_CREATION | FSAL_ATTR_CTIME | FSAL_ATTR_MTIME)) 00224 { 00225 /* handled as an unsettable attribute. */ 00226 Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_setattrs); 00227 } 00228 } 00229 00230 /* apply umask, if mode attribute is to be changed */ 00231 if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_MODE)) 00232 { 00233 wanted_attrs.mode &= (~global_fs_info.umask); 00234 } 00235 00236 /* get current attributes */ 00237 current_attrs.asked_attributes = GPFS_SUPPORTED_ATTRIBUTES; 00238 status = GPFSFSAL_getattrs(p_filehandle, p_context, ¤t_attrs); 00239 if(FSAL_IS_ERROR(status)) 00240 { 00241 FSAL_CLEAR_MASK(p_object_attributes->asked_attributes); 00242 FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00243 ReturnStatus(status, INDEX_FSAL_setattrs); 00244 } 00245 00246 /*********** 00247 * CHMOD * 00248 ***********/ 00249 if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_MODE)) 00250 { 00251 00252 /* The POSIX chmod call don't affect the symlink object, but 00253 * the entry it points to. So we must ignore it. 00254 */ 00255 if(current_attrs.type != FSAL_TYPE_LNK) 00256 { 00257 00258 /* For modifying mode, user must be root or the owner */ 00259 if((p_context->credential.user != 0) 00260 && (p_context->credential.user != current_attrs.owner)) 00261 { 00262 LogFullDebug(COMPONENT_FSAL, 00263 "Permission denied for CHMOD opeartion: current owner=%d, credential=%d", 00264 current_attrs.owner, p_context->credential.user); 00265 Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs); 00266 } 00267 00268 #ifdef _USE_NFS4_ACL 00269 /* Check permission using ACL. */ 00270 access_mask = FSAL_MODE_MASK_SET(0) | /* Dummy. */ 00271 FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_WRITE_ATTR); 00272 00273 if(!p_context->export_context->fe_static_fs_info->accesscheck_support) 00274 status = fsal_internal_testAccess(p_context, access_mask, NULL, ¤t_attrs); 00275 else 00276 status = fsal_internal_access(p_context, p_filehandle, access_mask, 00277 ¤t_attrs); 00278 00279 if(FSAL_IS_ERROR(status)) 00280 ReturnStatus(status, INDEX_FSAL_setattrs); 00281 #endif 00282 00283 attr_valid |= XATTR_STAT; 00284 attr_changed |= XATTR_MODE; 00285 00286 /* Fill wanted mode. */ 00287 buffxstat.buffstat.st_mode = fsal2unix_mode(wanted_attrs.mode); 00288 LogDebug(COMPONENT_FSAL, 00289 "current mode = %o, new mode = %o", 00290 fsal2unix_mode(current_attrs.mode), buffxstat.buffstat.st_mode); 00291 00292 } 00293 00294 } 00295 00296 /*********** 00297 * CHOWN * 00298 ***********/ 00299 /* Only root can change uid and A normal user must be in the group he wants to set */ 00300 if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_OWNER)) 00301 { 00302 00303 /* For modifying owner, user must be root or current owner==wanted==client */ 00304 if((p_context->credential.user != 0) && 00305 ((p_context->credential.user != current_attrs.owner) || 00306 (p_context->credential.user != wanted_attrs.owner))) 00307 { 00308 LogFullDebug(COMPONENT_FSAL, 00309 "Permission denied for CHOWN opeartion: current owner=%d, credential=%d, new owner=%d", 00310 current_attrs.owner, p_context->credential.user, wanted_attrs.owner); 00311 Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs); 00312 } 00313 00314 #ifdef _USE_NFS4_ACL 00315 /* Check permission using ACL. */ 00316 access_mask = FSAL_MODE_MASK_SET(0) | /* Dummy. */ 00317 FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_WRITE_OWNER); 00318 00319 if(!p_context->export_context->fe_static_fs_info->accesscheck_support) 00320 status = fsal_internal_testAccess(p_context, access_mask, NULL, ¤t_attrs); 00321 else 00322 status = fsal_internal_access(p_context, p_filehandle, access_mask, 00323 ¤t_attrs); 00324 00325 if(FSAL_IS_ERROR(status)) 00326 ReturnStatus(status, INDEX_FSAL_setattrs); 00327 #endif 00328 00329 } 00330 00331 if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_GROUP)) 00332 { 00333 00334 /* For modifying group, user must be root or current owner */ 00335 if((p_context->credential.user != 0) 00336 && (p_context->credential.user != current_attrs.owner)) 00337 { 00338 Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs); 00339 } 00340 00341 int in_grp = 0; 00342 /* set in_grp */ 00343 if(p_context->credential.group == wanted_attrs.group) 00344 in_grp = 1; 00345 else 00346 for(i = 0; i < p_context->credential.nbgroups; i++) 00347 { 00348 if((in_grp = (wanted_attrs.group == p_context->credential.alt_groups[i]))) 00349 break; 00350 } 00351 00352 /* it must also be in target group */ 00353 if(p_context->credential.user != 0 && !in_grp) 00354 { 00355 LogFullDebug(COMPONENT_FSAL, 00356 "Permission denied for CHOWN operation: current group=%d, credential=%d, new group=%d", 00357 current_attrs.group, p_context->credential.group, wanted_attrs.group); 00358 Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs); 00359 } 00360 00361 #ifdef _USE_NFS4_ACL 00362 /* Check permission using ACL. */ 00363 access_mask = FSAL_MODE_MASK_SET(0) | /* Dummy. */ 00364 FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_WRITE_OWNER); 00365 00366 if(!p_context->export_context->fe_static_fs_info->accesscheck_support) 00367 status = fsal_internal_testAccess(p_context, access_mask, NULL, ¤t_attrs); 00368 else 00369 status = fsal_internal_access(p_context, p_filehandle, access_mask, 00370 ¤t_attrs); 00371 00372 if(FSAL_IS_ERROR(status)) 00373 ReturnStatus(status, INDEX_FSAL_setattrs); 00374 #endif 00375 00376 } 00377 00378 if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_OWNER | FSAL_ATTR_GROUP)) 00379 { 00380 /* LogFullDebug(COMPONENT_FSAL, "Performing chown(%s, %d,%d)", 00381 fsalpath.path, FSAL_TEST_MASK(wanted_attrs.asked_attributes, 00382 FSAL_ATTR_OWNER) ? (int)wanted_attrs.owner 00383 : -1, FSAL_TEST_MASK(wanted_attrs.asked_attributes, 00384 FSAL_ATTR_GROUP) ? (int)wanted_attrs.group : -1);*/ 00385 00386 attr_valid |= XATTR_STAT; 00387 attr_changed |= FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_OWNER) ? 00388 XATTR_UID : XATTR_GID; 00389 00390 /* Fill wanted owner. */ 00391 if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_OWNER)) 00392 { 00393 buffxstat.buffstat.st_uid = (int)wanted_attrs.owner; 00394 LogDebug(COMPONENT_FSAL, 00395 "current uid = %d, new uid = %d", 00396 current_attrs.owner, buffxstat.buffstat.st_uid); 00397 } 00398 00399 /* Fill wanted group. */ 00400 if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_GROUP)) 00401 { 00402 buffxstat.buffstat.st_gid = (int)wanted_attrs.group; 00403 LogDebug(COMPONENT_FSAL, 00404 "current gid = %d, new gid = %d", 00405 current_attrs.group, buffxstat.buffstat.st_gid); 00406 } 00407 00408 } 00409 00410 /*********** 00411 * UTIME * 00412 ***********/ 00413 00414 /* user must be the owner or have read access to modify 'atime' */ 00415 access_mask = FSAL_MODE_MASK_SET(FSAL_R_OK) | 00416 FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_WRITE_ATTR); 00417 00418 if(!p_context->export_context->fe_static_fs_info->accesscheck_support) 00419 status = fsal_internal_testAccess(p_context, access_mask, NULL, ¤t_attrs); 00420 else 00421 status = fsal_internal_access(p_context, p_filehandle, access_mask, 00422 ¤t_attrs); 00423 00424 if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_ATIME) 00425 && (p_context->credential.user != 0) 00426 && (p_context->credential.user != current_attrs.owner) 00427 && (status.major 00428 != ERR_FSAL_NO_ERROR)) 00429 { 00430 ReturnStatus(status, INDEX_FSAL_setattrs); 00431 } 00432 /* user must be the owner or have write access to modify 'mtime' */ 00433 access_mask = FSAL_MODE_MASK_SET(FSAL_W_OK) | 00434 FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_WRITE_ATTR); 00435 00436 if(!p_context->export_context->fe_static_fs_info->accesscheck_support) 00437 status = fsal_internal_testAccess(p_context, access_mask, NULL, ¤t_attrs); 00438 else 00439 status = fsal_internal_access(p_context, p_filehandle, access_mask, 00440 ¤t_attrs); 00441 00442 if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_MTIME) 00443 && (p_context->credential.user != 0) 00444 && (p_context->credential.user != current_attrs.owner) 00445 && (status.major 00446 != ERR_FSAL_NO_ERROR)) 00447 { 00448 ReturnStatus(status, INDEX_FSAL_setattrs); 00449 } 00450 00451 if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_ATIME | FSAL_ATTR_MTIME)) 00452 { 00453 attr_valid |= XATTR_STAT; 00454 00455 /* Fill wanted atime. */ 00456 if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_ATIME)) 00457 { 00458 attr_changed |= XATTR_ATIME; 00459 buffxstat.buffstat.st_atime = (time_t) wanted_attrs.atime.seconds; 00460 LogDebug(COMPONENT_FSAL, 00461 "current atime = %lu, new atime = %lu", 00462 (unsigned long)current_attrs.atime.seconds, (unsigned long)buffxstat.buffstat.st_atime); 00463 } 00464 00465 /* Fill wanted mtime. */ 00466 if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_MTIME)) 00467 { 00468 attr_changed |= XATTR_CTIME; 00469 buffxstat.buffstat.st_mtime = (time_t) wanted_attrs.mtime.seconds; 00470 LogDebug(COMPONENT_FSAL, 00471 "current mtime = %lu, new mtime = %lu", 00472 (unsigned long)current_attrs.mtime.seconds, (unsigned long)buffxstat.buffstat.st_mtime); 00473 } 00474 } 00475 00476 #ifdef _USE_NFS4_ACL 00477 /*********** 00478 * ACL * 00479 ***********/ 00480 00481 if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_ACL)) 00482 { 00483 /* Check permission to set ACL. */ 00484 access_mask = FSAL_MODE_MASK_SET(0) | /* Dummy */ 00485 FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_WRITE_ACL); 00486 00487 if(!p_context->export_context->fe_static_fs_info->accesscheck_support) 00488 status = fsal_internal_testAccess(p_context, access_mask, NULL, ¤t_attrs); 00489 else 00490 status = fsal_internal_access(p_context, p_filehandle, access_mask, 00491 ¤t_attrs); 00492 00493 if(FSAL_IS_ERROR(status)) 00494 ReturnStatus(status, INDEX_FSAL_setattrs); 00495 00496 if(wanted_attrs.acl) 00497 { 00498 attr_valid |= XATTR_ACL; 00499 LogDebug(COMPONENT_FSAL, "setattr acl = %p", wanted_attrs.acl); 00500 00501 /* Convert FSAL ACL to GPFS NFS4 ACL and fill the buffer. */ 00502 status = fsal_acl_2_gpfs_acl(wanted_attrs.acl, &buffxstat); 00503 00504 if(FSAL_IS_ERROR(status)) 00505 ReturnStatus(status, INDEX_FSAL_setattrs); 00506 } 00507 else 00508 { 00509 LogCrit(COMPONENT_FSAL, "setattr acl is NULL"); 00510 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_setattrs); 00511 } 00512 } 00513 #endif /* _USE_NFS4_ACL */ 00514 00515 /* If there is any change in stat or acl or both, send it down to file system. */ 00516 if((attr_valid == XATTR_STAT && attr_changed !=0) || attr_valid == XATTR_ACL) 00517 { 00518 status = fsal_set_xstat_by_handle(p_context, 00519 p_filehandle, 00520 attr_valid, 00521 attr_changed, 00522 &buffxstat); 00523 00524 if(FSAL_IS_ERROR(status)) 00525 ReturnStatus(status, INDEX_FSAL_setattrs); 00526 } 00527 00528 /* Optionaly fills output attributes. */ 00529 00530 if(p_object_attributes) 00531 { 00532 status = GPFSFSAL_getattrs(p_filehandle, p_context, p_object_attributes); 00533 00534 /* on error, we set a special bit in the mask. */ 00535 if(FSAL_IS_ERROR(status)) 00536 { 00537 FSAL_CLEAR_MASK(p_object_attributes->asked_attributes); 00538 FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00539 } 00540 00541 } 00542 00543 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_setattrs); 00544 00545 }