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