nfs-ganesha 1.4

fsal_create.c

Go to the documentation of this file.
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 }