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 #include <unistd.h> 00022 #include <fcntl.h> 00023 00052 fsal_status_t LUSTREFSAL_create(fsal_handle_t * p_parent_directory_handle, /* IN */ 00053 fsal_name_t * p_filename, /* IN */ 00054 fsal_op_context_t * p_context, /* IN */ 00055 fsal_accessmode_t accessmode, /* IN */ 00056 fsal_handle_t * p_object_handle, /* OUT */ 00057 fsal_attrib_list_t * p_object_attributes /* [ IN/OUT ] */ 00058 ) 00059 { 00060 00061 int rc, fd, errsv; 00062 int setgid_bit = 0; 00063 fsal_status_t status; 00064 00065 fsal_path_t fsalpath; 00066 struct stat buffstat; 00067 mode_t unix_mode; 00068 00069 /* sanity checks. 00070 * note : object_attributes is optional. 00071 */ 00072 if(!p_parent_directory_handle || !p_context || !p_object_handle || !p_filename) 00073 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_create); 00074 00075 /* convert fsal mode to unix mode. */ 00076 unix_mode = fsal2unix_mode(accessmode); 00077 00078 /* Apply umask */ 00079 unix_mode = unix_mode & ~global_fs_info.umask; 00080 00081 LogFullDebug(COMPONENT_FSAL, "Creation mode: 0%o", accessmode); 00082 00083 /* build the destination path */ 00084 status = fsal_internal_Handle2FidPath(p_context, p_parent_directory_handle, &fsalpath); 00085 if(FSAL_IS_ERROR(status)) 00086 ReturnStatus(status, INDEX_FSAL_create); 00087 00088 /* retrieve directory metadata */ 00089 TakeTokenFSCall(); 00090 rc = lstat(fsalpath.path, &buffstat); 00091 errsv = errno; 00092 ReleaseTokenFSCall(); 00093 if(rc) 00094 { 00095 if(errsv == ENOENT) 00096 Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_create); 00097 else 00098 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_create); 00099 } 00100 00101 /* Check the user can write in the directory, and check the setgid bit on the directory */ 00102 00103 if(buffstat.st_mode & S_ISGID) 00104 setgid_bit = 1; 00105 00106 status = fsal_internal_testAccess(p_context, FSAL_W_OK | FSAL_X_OK, &buffstat, NULL); 00107 if(FSAL_IS_ERROR(status)) 00108 ReturnStatus(status, INDEX_FSAL_create); 00109 00110 /* build new entry path */ 00111 status = fsal_internal_appendNameToPath(&fsalpath, p_filename); 00112 if(FSAL_IS_ERROR(status)) 00113 ReturnStatus(status, INDEX_FSAL_create); 00114 00115 /* call to filesystem */ 00116 00117 TakeTokenFSCall(); 00118 /* create the file. 00119 * O_EXCL=> error if the file already exists */ 00120 fd = open(fsalpath.path, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, unix_mode); 00121 errsv = errno; 00122 00123 if(fd == -1) 00124 { 00125 ReleaseTokenFSCall(); 00126 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_create); 00127 } 00128 00129 /* close the file descriptor */ 00130 rc = close(fd); 00131 errsv = errno; 00132 if(rc) 00133 { 00134 ReleaseTokenFSCall(); 00135 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_create); 00136 } 00137 00138 /* get the new file handle */ 00139 status = fsal_internal_Path2Handle(p_context, &fsalpath, p_object_handle); 00140 ReleaseTokenFSCall(); 00141 00142 if(FSAL_IS_ERROR(status)) 00143 ReturnStatus(status, INDEX_FSAL_create); 00144 00145 /* the file has been created */ 00146 /* chown the file to the current user */ 00147 00148 if(p_context->credential.user != geteuid()) 00149 { 00150 TakeTokenFSCall(); 00151 /* if the setgid_bit was set on the parent directory, do not change the group of the created file, because it's already the parentdir's group */ 00152 rc = lchown(fsalpath.path, p_context->credential.user, 00153 setgid_bit ? -1 : (int)p_context->credential.group); 00154 errsv = errno; 00155 ReleaseTokenFSCall(); 00156 if(rc) 00157 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_create); 00158 } 00159 00160 /* retrieve file attributes */ 00161 if(p_object_attributes) 00162 { 00163 status = LUSTREFSAL_getattrs(p_object_handle, p_context, p_object_attributes); 00164 00165 /* on error, we set a special bit in the mask. */ 00166 if(FSAL_IS_ERROR(status)) 00167 { 00168 FSAL_CLEAR_MASK(p_object_attributes->asked_attributes); 00169 FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00170 } 00171 00172 } 00173 00174 /* OK */ 00175 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_create); 00176 00177 } 00178 00208 fsal_status_t LUSTREFSAL_mkdir(fsal_handle_t * p_parent_directory_handle, /* IN */ 00209 fsal_name_t * p_dirname, /* IN */ 00210 fsal_op_context_t * p_context, /* IN */ 00211 fsal_accessmode_t accessmode, /* IN */ 00212 fsal_handle_t * p_object_handle, /* OUT */ 00213 fsal_attrib_list_t * p_object_attributes /* [ IN/OUT ] */ 00214 ) 00215 { 00216 00217 int rc, errsv; 00218 int setgid_bit = 0; 00219 struct stat buffstat; 00220 mode_t unix_mode; 00221 fsal_status_t status; 00222 fsal_path_t fsalpath; 00223 00224 /* sanity checks. 00225 * note : object_attributes is optional. 00226 */ 00227 if(!p_parent_directory_handle || !p_context || !p_object_handle || !p_dirname) 00228 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mkdir); 00229 00230 /* convert FSAL mode to HPSS mode. */ 00231 unix_mode = fsal2unix_mode(accessmode); 00232 00233 /* Apply umask */ 00234 unix_mode = unix_mode & ~global_fs_info.umask; 00235 00236 /* build the destination path */ 00237 status = fsal_internal_Handle2FidPath(p_context, p_parent_directory_handle, &fsalpath); 00238 if(FSAL_IS_ERROR(status)) 00239 ReturnStatus(status, INDEX_FSAL_mkdir); 00240 00241 /* get directory metadata */ 00242 TakeTokenFSCall(); 00243 rc = lstat(fsalpath.path, &buffstat); 00244 errsv = errno; 00245 ReleaseTokenFSCall(); 00246 if(rc) 00247 { 00248 if(errsv == ENOENT) 00249 Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_create); 00250 else 00251 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_create); 00252 } 00253 00254 /* Check the user can write in the directory, and check the setgid bit on the directory */ 00255 00256 if(buffstat.st_mode & S_ISGID) 00257 setgid_bit = 1; 00258 00259 status = fsal_internal_testAccess(p_context, FSAL_W_OK | FSAL_X_OK, &buffstat, NULL); 00260 if(FSAL_IS_ERROR(status)) 00261 ReturnStatus(status, INDEX_FSAL_mkdir); 00262 00263 /* build new entry path */ 00264 00265 status = fsal_internal_appendNameToPath(&fsalpath, p_dirname); 00266 if(FSAL_IS_ERROR(status)) 00267 ReturnStatus(status, INDEX_FSAL_mkdir); 00268 00269 /* creates the directory and get its handle */ 00270 00271 TakeTokenFSCall(); 00272 rc = mkdir(fsalpath.path, unix_mode); 00273 errsv = errno; 00274 if(rc) 00275 { 00276 ReleaseTokenFSCall(); 00277 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_mkdir); 00278 } 00279 00280 /* get the new handle */ 00281 status = fsal_internal_Path2Handle(p_context, &fsalpath, p_object_handle); 00282 ReleaseTokenFSCall(); 00283 00284 if(FSAL_IS_ERROR(status)) 00285 ReturnStatus(status, INDEX_FSAL_mkdir); 00286 00287 /* the directory has been created */ 00288 /* chown the file to the current user/group */ 00289 00290 if(p_context->credential.user != geteuid()) 00291 { 00292 TakeTokenFSCall(); 00293 /* if the setgid_bit was set on the parent directory, do not change the group of the created file, because it's already the parentdir's group */ 00294 rc = lchown(fsalpath.path, p_context->credential.user, 00295 setgid_bit ? -1 : (int)p_context->credential.group); 00296 errsv = errno; 00297 ReleaseTokenFSCall(); 00298 if(rc) 00299 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_mkdir); 00300 } 00301 00302 /* retrieve file attributes */ 00303 if(p_object_attributes) 00304 { 00305 status = LUSTREFSAL_getattrs(p_object_handle, p_context, p_object_attributes); 00306 00307 /* on error, we set a special bit in the mask. */ 00308 if(FSAL_IS_ERROR(status)) 00309 { 00310 FSAL_CLEAR_MASK(p_object_attributes->asked_attributes); 00311 FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00312 } 00313 00314 } 00315 00316 /* OK */ 00317 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_mkdir); 00318 00319 } 00320 00350 fsal_status_t LUSTREFSAL_link(fsal_handle_t * p_target_handle, /* IN */ 00351 fsal_handle_t * p_dir_handle, /* IN */ 00352 fsal_name_t * p_link_name, /* IN */ 00353 fsal_op_context_t * p_context, /* IN */ 00354 fsal_attrib_list_t * p_attributes /* [ IN/OUT ] */ 00355 ) 00356 { 00357 00358 int rc, errsv; 00359 fsal_status_t status; 00360 fsal_path_t fsalpath_old, fsalpath_new; 00361 struct stat buffstat_dir; 00362 00363 /* sanity checks. 00364 * note : attributes is optional. 00365 */ 00366 if(!p_target_handle || !p_dir_handle || !p_context || !p_link_name) 00367 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_link); 00368 00369 /* Tests if hardlinking is allowed by configuration. */ 00370 00371 if(!global_fs_info.link_support) 00372 Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_link); 00373 00374 /* LogFullDebug(COMPONENT_FSAL, "linking %#llx:%#x:%#x to %#llx:%#x:%#x/%s \n", */ 00375 00376 /* get the target handle access by fid */ 00377 status = fsal_internal_Handle2FidPath(p_context, p_target_handle, &fsalpath_old); 00378 if(FSAL_IS_ERROR(status)) 00379 ReturnStatus(status, INDEX_FSAL_link); 00380 00381 /* build the destination path and check permissions on the directory */ 00382 status = fsal_internal_Handle2FidPath(p_context, p_dir_handle, &fsalpath_new); 00383 if(FSAL_IS_ERROR(status)) 00384 ReturnStatus(status, INDEX_FSAL_link); 00385 00386 /* retrieve target directory metadata */ 00387 00388 TakeTokenFSCall(); 00389 rc = lstat(fsalpath_new.path, &buffstat_dir); 00390 errsv = errno; 00391 ReleaseTokenFSCall(); 00392 00393 if(rc) 00394 { 00395 if(errsv == ENOENT) 00396 Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_link); 00397 else 00398 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_link); 00399 } 00400 00401 /* check permission on target directory */ 00402 status = 00403 fsal_internal_testAccess(p_context, FSAL_W_OK | FSAL_X_OK, &buffstat_dir, NULL); 00404 if(FSAL_IS_ERROR(status)) 00405 ReturnStatus(status, INDEX_FSAL_link); 00406 00407 /* build the new entry path */ 00408 status = fsal_internal_appendNameToPath(&fsalpath_new, p_link_name); 00409 if(FSAL_IS_ERROR(status)) 00410 ReturnStatus(status, INDEX_FSAL_link); 00411 00412 /* Create the link on the filesystem */ 00413 00414 TakeTokenFSCall(); 00415 rc = link(fsalpath_old.path, fsalpath_new.path); 00416 errsv = errno; 00417 ReleaseTokenFSCall(); 00418 if(rc) 00419 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_link); 00420 00421 /* optionnaly get attributes */ 00422 00423 if(p_attributes) 00424 { 00425 status = LUSTREFSAL_getattrs(p_target_handle, p_context, p_attributes); 00426 00427 /* on error, we set a special bit in the mask. */ 00428 if(FSAL_IS_ERROR(status)) 00429 { 00430 FSAL_CLEAR_MASK(p_attributes->asked_attributes); 00431 FSAL_SET_MASK(p_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00432 } 00433 } 00434 00435 /* OK */ 00436 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_link); 00437 00438 } 00439 00447 fsal_status_t LUSTREFSAL_mknode(fsal_handle_t * parentdir_handle, /* IN */ 00448 fsal_name_t * p_node_name, /* IN */ 00449 fsal_op_context_t * p_context, /* IN */ 00450 fsal_accessmode_t accessmode, /* IN */ 00451 fsal_nodetype_t nodetype, /* IN */ 00452 fsal_dev_t * dev, /* IN */ 00453 fsal_handle_t * p_object_handle, /* OUT (handle to the created node) */ 00454 fsal_attrib_list_t * node_attributes /* [ IN/OUT ] */ 00455 ) 00456 { 00457 int rc, errsv; 00458 int setgid_bit = 0; 00459 struct stat buffstat; 00460 fsal_status_t status; 00461 fsal_path_t fsalpath; 00462 00463 mode_t unix_mode = 0; 00464 dev_t unix_dev = 0; 00465 00466 /* sanity checks. 00467 * note : link_attributes is optional. 00468 */ 00469 if(!parentdir_handle || !p_context || !p_node_name) 00470 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mknode); 00471 00472 unix_mode = fsal2unix_mode(accessmode); 00473 00474 /* Apply umask */ 00475 unix_mode = unix_mode & ~global_fs_info.umask; 00476 00477 switch (nodetype) 00478 { 00479 case FSAL_TYPE_BLK: 00480 if(!dev) 00481 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mknode); 00482 unix_mode |= S_IFBLK; 00483 unix_dev = (dev->major << 8) | (dev->minor & 0xFF); 00484 break; 00485 00486 case FSAL_TYPE_CHR: 00487 if(!dev) 00488 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mknode); 00489 unix_mode |= S_IFCHR; 00490 unix_dev = (dev->major << 8) | (dev->minor & 0xFF); 00491 break; 00492 00493 case FSAL_TYPE_SOCK: 00494 unix_mode |= S_IFSOCK; 00495 break; 00496 00497 case FSAL_TYPE_FIFO: 00498 unix_mode |= S_IFIFO; 00499 break; 00500 00501 default: 00502 LogMajor(COMPONENT_FSAL, "Invalid node type in FSAL_mknode: %d", 00503 nodetype); 00504 Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_mknode); 00505 } 00506 00507 /* build the directory path */ 00508 status = fsal_internal_Handle2FidPath(p_context, parentdir_handle, &fsalpath); 00509 if(FSAL_IS_ERROR(status)) 00510 ReturnStatus(status, INDEX_FSAL_mknode); 00511 00512 /* retrieve directory attributes */ 00513 TakeTokenFSCall(); 00514 rc = lstat(fsalpath.path, &buffstat); 00515 errsv = errno; 00516 ReleaseTokenFSCall(); 00517 00518 if(rc) 00519 { 00520 if(errsv == ENOENT) 00521 Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_mknode); 00522 else 00523 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_mknode); 00524 } 00525 00526 /* Check the user can write in the directory, and check weither the setgid bit on the directory */ 00527 if(buffstat.st_mode & S_ISGID) 00528 setgid_bit = 1; 00529 00530 status = fsal_internal_testAccess(p_context, FSAL_W_OK | FSAL_X_OK, &buffstat, NULL); 00531 if(FSAL_IS_ERROR(status)) 00532 ReturnStatus(status, INDEX_FSAL_mknode); 00533 00534 status = fsal_internal_appendNameToPath(&fsalpath, p_node_name); 00535 if(FSAL_IS_ERROR(status)) 00536 ReturnStatus(status, INDEX_FSAL_mknode); 00537 00538 /* creates the node, then stats it */ 00539 TakeTokenFSCall(); 00540 rc = mknod(fsalpath.path, unix_mode, unix_dev); 00541 errsv = errno; 00542 00543 if(rc) 00544 { 00545 ReleaseTokenFSCall(); 00546 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_mknode); 00547 } 00548 00549 /* get the new object handle */ 00550 status = fsal_internal_Path2Handle(p_context, &fsalpath, p_object_handle); 00551 ReleaseTokenFSCall(); 00552 00553 if(FSAL_IS_ERROR(status)) 00554 ReturnStatus(status, INDEX_FSAL_mknode); 00555 00556 /* the node has been created */ 00557 /* chown the file to the current user/group */ 00558 00559 if(p_context->credential.user != geteuid()) 00560 { 00561 TakeTokenFSCall(); 00562 00563 /* if the setgid_bit was set on the parent directory, do not change the group of the created file, because it's already the parentdir's group */ 00564 rc = lchown(fsalpath.path, p_context->credential.user, 00565 setgid_bit ? -1 : (int)p_context->credential.group); 00566 errsv = errno; 00567 00568 ReleaseTokenFSCall(); 00569 00570 if(rc) 00571 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_mknode); 00572 } 00573 00574 /* Fills the attributes if needed */ 00575 if(node_attributes) 00576 { 00577 00578 status = LUSTREFSAL_getattrs(p_object_handle, p_context, node_attributes); 00579 00580 /* on error, we set a special bit in the mask. */ 00581 00582 if(FSAL_IS_ERROR(status)) 00583 { 00584 FSAL_CLEAR_MASK(node_attributes->asked_attributes); 00585 FSAL_SET_MASK(node_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00586 } 00587 00588 } 00589 00590 /* Finished */ 00591 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_mknode); 00592 00593 }