nfs-ganesha 1.4

fsal_symlinks.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=4:tabstop=4:
00003  */
00004 
00013 #ifdef HAVE_CONFIG_H
00014 #include "config.h"
00015 #endif
00016 
00017 #include "fsal.h"
00018 #include "fsal_internal.h"
00019 #include "fsal_convert.h"
00020 #include <string.h>
00021 #include <unistd.h>
00022 
00046 fsal_status_t LUSTREFSAL_readlink(fsal_handle_t * p_linkhandle,   /* IN */
00047                                   fsal_op_context_t * p_context,  /* IN */
00048                                   fsal_path_t * p_link_content, /* OUT */
00049                                   fsal_attrib_list_t * p_link_attributes        /* [ IN/OUT ] */
00050     )
00051 {
00052 
00053   int rc, errsv;
00054   fsal_status_t status;
00055   char link_content_out[FSAL_MAX_PATH_LEN];
00056   fsal_path_t fsalpath;
00057 
00058   /* sanity checks.
00059    * note : link_attributes is optional.
00060    */
00061   if(!p_linkhandle || !p_context || !p_link_content)
00062     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readlink);
00063 
00064   status = fsal_internal_Handle2FidPath(p_context, p_linkhandle, &fsalpath);
00065   if(FSAL_IS_ERROR(status))
00066     ReturnStatus(status, INDEX_FSAL_readlink);
00067 
00068   memset(link_content_out, 0, FSAL_MAX_PATH_LEN);
00069 
00070   /* Read the link on the filesystem */
00071 
00072   TakeTokenFSCall();
00073   rc = readlink(fsalpath.path, link_content_out, FSAL_MAX_PATH_LEN);
00074   errsv = errno;
00075   ReleaseTokenFSCall();
00076 
00077   /* rc is the length for the symlink content or -1 on error !!! */
00078   if(rc < 0)
00079     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_readlink);
00080 
00081   /* convert char * to fsal_path_t */
00082   status = FSAL_str2path(link_content_out, FSAL_MAX_PATH_LEN, p_link_content);
00083 
00084   if(FSAL_IS_ERROR(status))
00085     ReturnStatus(status, INDEX_FSAL_readlink);
00086 
00087   /* retrieves object attributes, if asked */
00088 
00089   if(p_link_attributes)
00090     {
00091 
00092       status = LUSTREFSAL_getattrs(p_linkhandle, p_context, p_link_attributes);
00093 
00094       /* On error, we set a flag in the returned attributes */
00095 
00096       if(FSAL_IS_ERROR(status))
00097         {
00098           FSAL_CLEAR_MASK(p_link_attributes->asked_attributes);
00099           FSAL_SET_MASK(p_link_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00100         }
00101 
00102     }
00103 
00104   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readlink);
00105 
00106 }
00107 
00137 fsal_status_t LUSTREFSAL_symlink(fsal_handle_t * p_parent_directory_handle,       /* IN */
00138                                  fsal_name_t * p_linkname,      /* IN */
00139                                  fsal_path_t * p_linkcontent,   /* IN */
00140                                  fsal_op_context_t * p_context,   /* IN */
00141                                  fsal_accessmode_t accessmode,  /* IN (ignored) */
00142                                  fsal_handle_t * p_link_handle,   /* OUT */
00143                                  fsal_attrib_list_t * p_link_attributes /* [ IN/OUT ] */
00144     )
00145 {
00146 
00147   int rc, errsv;
00148   fsal_status_t status;
00149   fsal_path_t fsalpath;
00150   struct stat buffstat;
00151   int setgid_bit = FALSE;
00152 
00153   /* sanity checks.
00154    * note : link_attributes is optional.
00155    */
00156   if(!p_parent_directory_handle || !p_context ||
00157      !p_link_handle || !p_linkname || !p_linkcontent)
00158     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_symlink);
00159 
00160   /* Tests if symlinking is allowed by configuration. */
00161 
00162   if(!global_fs_info.symlink_support)
00163     Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_symlink);
00164 
00165   /* build the new path and check the permissions on the parent directory */
00166   status = fsal_internal_Handle2FidPath(p_context, p_parent_directory_handle, &fsalpath);
00167   if(FSAL_IS_ERROR(status))
00168     ReturnStatus(status, INDEX_FSAL_symlink);
00169 
00170   /* retrieve directory metadata, for checking access */
00171   TakeTokenFSCall();
00172   rc = lstat(fsalpath.path, &buffstat);
00173   errsv = errno;
00174   ReleaseTokenFSCall();
00175 
00176   if(rc)
00177     {
00178       if(errsv == ENOENT)
00179         Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_symlink);
00180       else
00181         Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_symlink);
00182     }
00183 
00184   if(buffstat.st_mode & S_ISGID)
00185     setgid_bit = TRUE;
00186 
00187   status = fsal_internal_testAccess(p_context, FSAL_W_OK, &buffstat, NULL);
00188   if(FSAL_IS_ERROR(status))
00189     ReturnStatus(status, INDEX_FSAL_symlink);
00190 
00191   /* build symlink path */
00192 
00193   status = fsal_internal_appendNameToPath(&fsalpath, p_linkname);
00194   if(FSAL_IS_ERROR(status))
00195     ReturnStatus(status, INDEX_FSAL_symlink);
00196 
00197   /* create the symlink on the filesystem. */
00198 
00199   TakeTokenFSCall();
00200   rc = symlink(p_linkcontent->path, fsalpath.path);
00201   errsv = errno;
00202   ReleaseTokenFSCall();
00203 
00204   if(rc)
00205     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_symlink);
00206 
00207   /* Get symlink handle */
00208   TakeTokenFSCall();
00209   status = fsal_internal_Path2Handle(p_context, &fsalpath, p_link_handle);
00210   ReleaseTokenFSCall();
00211   if(FSAL_IS_ERROR(status))
00212     ReturnStatus(status, INDEX_FSAL_lookup);
00213 
00214   /* chown the symlink to the current user/group */
00215 
00216   TakeTokenFSCall();
00217   rc = lchown(fsalpath.path, p_context->credential.user,
00218               setgid_bit ? -1 : p_context->credential.group);
00219   errsv = errno;
00220   ReleaseTokenFSCall();
00221 
00222   if(rc)
00223     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_symlink);
00224 
00225   /* get attributes if asked */
00226 
00227   if(p_link_attributes)
00228     {
00229 
00230       status = LUSTREFSAL_getattrs(p_link_handle, p_context, p_link_attributes);
00231 
00232       /* On error, we set a flag in the returned attributes */
00233 
00234       if(FSAL_IS_ERROR(status))
00235         {
00236           FSAL_CLEAR_MASK(p_link_attributes->asked_attributes);
00237           FSAL_SET_MASK(p_link_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00238         }
00239 
00240     }
00241 
00242   /* OK */
00243   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_symlink);
00244 }