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 #include <sys/fsuid.h>
00024 
00053 fsal_status_t GPFSFSAL_create(fsal_handle_t * p_parent_directory_handle,    /* IN */
00054                           fsal_name_t * p_filename,     /* IN */
00055                           fsal_op_context_t * p_context,        /* IN */
00056                           fsal_accessmode_t accessmode, /* IN */
00057                           fsal_handle_t * p_object_handle,      /* OUT */
00058                           fsal_attrib_list_t * p_object_attributes      /* [ IN/OUT ] */
00059     )
00060 {
00061 
00062   int fsuid, fsgid;
00063   fsal_status_t status;
00064 
00065   mode_t unix_mode;
00066   fsal_accessflags_t access_mask = 0;
00067   fsal_attrib_list_t parent_dir_attrs;
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   /* retrieve directory metadata */
00084   parent_dir_attrs.asked_attributes = GPFS_SUPPORTED_ATTRIBUTES;
00085   status = GPFSFSAL_getattrs(p_parent_directory_handle, p_context, &parent_dir_attrs);
00086   if(FSAL_IS_ERROR(status))
00087     ReturnStatus(status, INDEX_FSAL_create);
00088 
00089   /* Check the user can write in the directory */
00090 
00091   /* Set both mode and ace4 mask */
00092   access_mask = FSAL_MODE_MASK_SET(FSAL_W_OK | FSAL_X_OK) |
00093                 FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_ADD_FILE);
00094 
00095   if(!p_context->export_context->fe_static_fs_info->accesscheck_support)
00096   status = fsal_internal_testAccess(p_context, access_mask, NULL, &parent_dir_attrs);
00097   else
00098     status = fsal_internal_access(p_context, p_parent_directory_handle, access_mask,
00099                                   &parent_dir_attrs);
00100   if(FSAL_IS_ERROR(status))
00101     ReturnStatus(status, INDEX_FSAL_create);
00102 
00103   /* call to filesystem */
00104 
00105   fsuid = setfsuid(p_context->credential.user);
00106   fsgid = setfsgid(p_context->credential.group);
00107   TakeTokenFSCall();
00108   status = fsal_internal_create(p_context, p_parent_directory_handle,
00109                                 p_filename, unix_mode | S_IFREG, 0,
00110                                 p_object_handle, NULL);
00111   ReleaseTokenFSCall();
00112   setfsuid(fsuid);
00113   setfsgid(fsgid);
00114   if(FSAL_IS_ERROR(status))
00115     ReturnStatus(status, INDEX_FSAL_create);
00116 
00117   /* retrieve file attributes */
00118   if(p_object_attributes)
00119     {
00120       status = GPFSFSAL_getattrs(p_object_handle, p_context, p_object_attributes);
00121 
00122       /* on error, we set a special bit in the mask. */
00123       if(FSAL_IS_ERROR(status))
00124         {
00125           FSAL_CLEAR_MASK(p_object_attributes->asked_attributes);
00126           FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00127         }
00128 
00129     }
00130 
00131   /* OK */
00132   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_create);
00133 
00134 }
00135 
00165 fsal_status_t GPFSFSAL_mkdir(fsal_handle_t * p_parent_directory_handle,     /* IN */
00166                          fsal_name_t * p_dirname,       /* IN */
00167                          fsal_op_context_t * p_context, /* IN */
00168                          fsal_accessmode_t accessmode,  /* IN */
00169                          fsal_handle_t * p_object_handle,       /* OUT */
00170                          fsal_attrib_list_t * p_object_attributes       /* [ IN/OUT ] */
00171     )
00172 {
00173 /*   int setgid_bit = 0; */
00174   mode_t unix_mode;
00175   fsal_status_t status;
00176   fsal_accessflags_t access_mask = 0;
00177   fsal_attrib_list_t parent_dir_attrs;
00178   int fsuid, fsgid;
00179 
00180   /* sanity checks.
00181    * note : object_attributes is optional.
00182    */
00183   if(!p_parent_directory_handle || !p_context || !p_object_handle || !p_dirname)
00184     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mkdir);
00185 
00186   /* convert FSAL mode to unix mode. */
00187   unix_mode = fsal2unix_mode(accessmode);
00188 
00189   /* Apply umask */
00190   unix_mode = unix_mode & ~global_fs_info.umask;
00191 
00192   /* get directory metadata */
00193   parent_dir_attrs.asked_attributes = GPFS_SUPPORTED_ATTRIBUTES;
00194   status = GPFSFSAL_getattrs(p_parent_directory_handle, p_context, &parent_dir_attrs);
00195   if(FSAL_IS_ERROR(status))
00196     ReturnStatus(status, INDEX_FSAL_mkdir);
00197 
00198   /* Check the user can write in the directory, and check the setgid bit on the directory */
00199 
00200 /*   if(fsal2unix_mode(parent_dir_attrs.mode) & S_ISGID) */
00201 /*     setgid_bit = 1; */
00202 
00203   /* Set both mode and ace4 mask */
00204   access_mask = FSAL_MODE_MASK_SET(FSAL_W_OK | FSAL_X_OK) |
00205                 FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_ADD_SUBDIRECTORY);
00206 
00207   if(!p_context->export_context->fe_static_fs_info->accesscheck_support)
00208   status = fsal_internal_testAccess(p_context, access_mask, NULL, &parent_dir_attrs);
00209   else
00210     status = fsal_internal_access(p_context, p_parent_directory_handle, access_mask,
00211                                   &parent_dir_attrs);
00212   if(FSAL_IS_ERROR(status))
00213     ReturnStatus(status, INDEX_FSAL_mkdir);
00214 
00215   /* build new entry path */
00216 
00217   /* creates the directory and get its handle */
00218 
00219   fsuid = setfsuid(p_context->credential.user);
00220   fsgid = setfsgid(p_context->credential.group);
00221 
00222   TakeTokenFSCall();
00223   status = fsal_internal_create(p_context, p_parent_directory_handle,
00224                                 p_dirname, unix_mode | S_IFDIR, 0,
00225                                 p_object_handle, NULL);
00226   ReleaseTokenFSCall();
00227   setfsuid(fsuid);
00228   setfsgid(fsgid);
00229 
00230   if(FSAL_IS_ERROR(status))
00231     ReturnStatus(status, INDEX_FSAL_mkdir);
00232 
00233   /* retrieve file attributes */
00234   if(p_object_attributes)
00235     {
00236       status = GPFSFSAL_getattrs(p_object_handle, p_context, p_object_attributes);
00237 
00238       /* on error, we set a special bit in the mask. */
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         }
00244 
00245     }
00246 
00247   /* OK */
00248   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_mkdir);
00249 
00250 }
00251 
00281 fsal_status_t GPFSFSAL_link(fsal_handle_t * p_target_handle,        /* IN */
00282                         fsal_handle_t * p_dir_handle,   /* IN */
00283                         fsal_name_t * p_link_name,      /* IN */
00284                         fsal_op_context_t * p_context,  /* IN */
00285                         fsal_attrib_list_t * p_attributes       /* [ IN/OUT ] */
00286     )
00287 {
00288   fsal_status_t status;
00289   fsal_accessflags_t access_mask = 0;
00290   fsal_attrib_list_t parent_dir_attrs;
00291 
00292   /* sanity checks.
00293    * note : attributes is optional.
00294    */
00295   if(!p_target_handle || !p_dir_handle || !p_context || !p_context->export_context
00296      || !p_link_name || !p_link_name->name)
00297     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_link);
00298 
00299   /* Tests if hardlinking is allowed by configuration. */
00300 
00301   if(!global_fs_info.link_support)
00302     Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_link);
00303 
00304   /* retrieve target directory metadata */
00305   parent_dir_attrs.asked_attributes = GPFS_SUPPORTED_ATTRIBUTES;
00306   status = GPFSFSAL_getattrs(p_dir_handle, p_context, &parent_dir_attrs);
00307   if(FSAL_IS_ERROR(status))
00308       goto out_status_fsal_err;
00309 
00310   /* check permission on target directory */
00311 
00312   /* Set both mode and ace4 mask */
00313   access_mask = FSAL_MODE_MASK_SET(FSAL_W_OK | FSAL_X_OK) |
00314                 FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_ADD_FILE);
00315 
00316   if(!p_context->export_context->fe_static_fs_info->accesscheck_support)
00317   status = fsal_internal_testAccess(p_context, access_mask, NULL, &parent_dir_attrs);
00318   else
00319     status = fsal_internal_access(p_context, p_dir_handle, access_mask,
00320                                   &parent_dir_attrs);
00321   if(FSAL_IS_ERROR(status))
00322       goto out_status_fsal_err;
00323 
00324   /* Create the link on the filesystem */
00325 
00326   TakeTokenFSCall();
00327   status = fsal_internal_link_fh(p_context, p_target_handle, p_dir_handle,
00328                                  p_link_name);
00329   ReleaseTokenFSCall();
00330 
00331   if(FSAL_IS_ERROR(status))
00332       goto out_status_fsal_err;
00333 
00334   /* optionnaly get attributes */
00335 
00336   if(p_attributes)
00337     {
00338       status = GPFSFSAL_getattrs(p_target_handle, p_context, p_attributes);
00339 
00340       /* on error, we set a special bit in the mask. */
00341       if(FSAL_IS_ERROR(status))
00342         {
00343           FSAL_CLEAR_MASK(p_attributes->asked_attributes);
00344           FSAL_SET_MASK(p_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00345         }
00346     }
00347 
00348   /* OK */
00349   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_link);
00350 
00351  out_status_fsal_err:
00352 
00353   ReturnStatus(status, INDEX_FSAL_link);
00354 }
00355 
00363 fsal_status_t GPFSFSAL_mknode(fsal_handle_t * parentdir_handle,     /* IN */
00364                           fsal_name_t * p_node_name,    /* IN */
00365                           fsal_op_context_t * p_context,        /* IN */
00366                           fsal_accessmode_t accessmode, /* IN */
00367                           fsal_nodetype_t nodetype,     /* IN */
00368                           fsal_dev_t * dev,     /* IN */
00369                           fsal_handle_t * p_object_handle,      /* OUT (handle to the created node) */
00370                           fsal_attrib_list_t * node_attributes  /* [ IN/OUT ] */
00371     )
00372 {
00373   fsal_status_t status;
00374 /*   int flags=(O_RDONLY|O_NOFOLLOW); */
00375   int fsuid, fsgid;
00376 
00377   mode_t unix_mode = 0;
00378   dev_t unix_dev = 0;
00379   fsal_accessflags_t access_mask = 0;
00380   fsal_attrib_list_t parent_dir_attrs;
00381 
00382   /* sanity checks.
00383    * note : link_attributes is optional.
00384    */
00385   if(!parentdir_handle || !p_context || !p_node_name)
00386     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mknode);
00387 
00388   unix_mode = fsal2unix_mode(accessmode);
00389 
00390   /* Apply umask */
00391   unix_mode = unix_mode & ~global_fs_info.umask;
00392 
00393   switch (nodetype)
00394     {
00395     case FSAL_TYPE_BLK:
00396       if(!dev)
00397         Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mknode);
00398       unix_mode |= S_IFBLK;
00399       unix_dev = (dev->major << 8) | (dev->minor & 0xFF);
00400       break;
00401 
00402     case FSAL_TYPE_CHR:
00403       if(!dev)
00404         Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mknode);
00405       unix_mode |= S_IFCHR;
00406       unix_dev = (dev->major << 8) | (dev->minor & 0xFF);
00407       break;
00408 
00409     case FSAL_TYPE_SOCK:
00410       unix_mode |= S_IFSOCK;
00411       break;
00412 
00413     case FSAL_TYPE_FIFO:
00414       unix_mode |= S_IFIFO;
00415 /*       flags = (O_RDONLY | O_NOFOLLOW | O_NONBLOCK); */
00416       break;
00417 
00418     default:
00419       LogMajor(COMPONENT_FSAL,
00420                "Invalid node type in FSAL_mknode: %d", nodetype);
00421       Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_mknode);
00422     }
00423 
00424   /* retrieve directory attributes */
00425   parent_dir_attrs.asked_attributes = GPFS_SUPPORTED_ATTRIBUTES;
00426   status = GPFSFSAL_getattrs(parentdir_handle, p_context, &parent_dir_attrs);
00427   if(FSAL_IS_ERROR(status))
00428     ReturnStatus(status, INDEX_FSAL_mknode);
00429 
00430   /* Check the user can write in the directory */
00431 
00432   /* Set both mode and ace4 mask */
00433   access_mask = FSAL_MODE_MASK_SET(FSAL_W_OK | FSAL_X_OK) |
00434                 FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_ADD_FILE);
00435 
00436   if(!p_context->export_context->fe_static_fs_info->accesscheck_support)
00437   status = fsal_internal_testAccess(p_context, access_mask, NULL, &parent_dir_attrs);
00438   else
00439     status = fsal_internal_access(p_context, parentdir_handle, access_mask,
00440                                   &parent_dir_attrs);
00441   if(FSAL_IS_ERROR(status))
00442     ReturnStatus(status, INDEX_FSAL_mknode);
00443 
00444   fsuid = setfsuid(p_context->credential.user);
00445   fsgid = setfsgid(p_context->credential.group);
00446 
00447   TakeTokenFSCall();
00448   status = fsal_internal_create(p_context, parentdir_handle,
00449                                 p_node_name, unix_mode, unix_dev,
00450                                 p_object_handle, NULL);
00451   ReleaseTokenFSCall();
00452 
00453   setfsuid(fsuid);
00454   setfsgid(fsgid);
00455 
00456   if(FSAL_IS_ERROR(status))
00457     ReturnStatus(status, INDEX_FSAL_mknode);
00458 
00459   /* Fills the attributes if needed */
00460   if(node_attributes)
00461     {
00462 
00463       status = GPFSFSAL_getattrs(p_object_handle, p_context, node_attributes);
00464 
00465       /* on error, we set a special bit in the mask. */
00466 
00467       if(FSAL_IS_ERROR(status))
00468         {
00469           FSAL_CLEAR_MASK(node_attributes->asked_attributes);
00470           FSAL_SET_MASK(node_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00471         }
00472 
00473     }
00474 
00475   /* Finished */
00476   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_mknode);
00477 
00478 }