nfs-ganesha 1.4

fsal_symlinks.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
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 
00045 fsal_status_t POSIXFSAL_readlink(fsal_handle_t * linkhandle,     /* IN */
00046                                  fsal_op_context_t * context,    /* IN */
00047                                  fsal_path_t * p_link_content,  /* OUT */
00048                                  fsal_attrib_list_t * p_link_attributes /* [ IN/OUT ] */
00049     )
00050 {
00051   posixfsal_handle_t * p_linkhandle = (posixfsal_handle_t *) linkhandle;
00052   posixfsal_op_context_t * p_context = (posixfsal_op_context_t *) context;
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_getPathFromHandle(p_context, p_linkhandle, 0, &fsalpath, NULL);
00065   if(FSAL_IS_ERROR(status))
00066     Return(status.major, status.minor, 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 
00083   status = FSAL_str2path(link_content_out, FSAL_MAX_PATH_LEN, p_link_content);
00084 
00085   if(FSAL_IS_ERROR(status))
00086     Return(status.major, status.minor, INDEX_FSAL_readlink);
00087 
00088   /* retrieves object attributes, if asked */
00089 
00090   if(p_link_attributes)
00091     {
00092 
00093       status = POSIXFSAL_getattrs(p_linkhandle, p_context, p_link_attributes);
00094 
00095       /* On error, we set a flag in the returned attributes */
00096 
00097       if(FSAL_IS_ERROR(status))
00098         {
00099           FSAL_CLEAR_MASK(p_link_attributes->asked_attributes);
00100           FSAL_SET_MASK(p_link_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00101         }
00102 
00103     }
00104 
00105   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readlink);
00106 
00107 }
00108 
00138 fsal_status_t POSIXFSAL_symlink(fsal_handle_t * parent_directory_handle, /* IN */
00139                                 fsal_name_t * p_linkname,       /* IN */
00140                                 fsal_path_t * p_linkcontent,    /* IN */
00141                                 fsal_op_context_t * context,     /* IN */
00142                                 fsal_accessmode_t accessmode,   /* IN (ignored) */
00143                                 fsal_handle_t * link_handle,     /* OUT */
00144                                 fsal_attrib_list_t * p_link_attributes  /* [ IN/OUT ] */
00145     )
00146 {
00147   posixfsal_handle_t * p_parent_directory_handle
00148     = (posixfsal_handle_t *) parent_directory_handle;
00149   posixfsal_op_context_t * p_context = (posixfsal_op_context_t *) context;
00150   posixfsal_handle_t * p_link_handle = (posixfsal_handle_t *) link_handle;
00151   int rc, errsv;
00152   fsal_status_t status;
00153   fsal_path_t fsalpath;
00154   fsal_posixdb_fileinfo_t infofs;
00155   struct stat buffstat;
00156 
00157   /* sanity checks.
00158    * note : link_attributes is optional.
00159    */
00160   if(!p_parent_directory_handle ||
00161      !p_context || !p_link_handle || !p_linkname || !p_linkcontent)
00162     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_symlink);
00163 
00164   /* Tests if symlinking is allowed by configuration. */
00165 
00166   if(!global_fs_info.symlink_support)
00167     Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_symlink);
00168 
00169   /* build the new path and check the permissions on the parent directory */
00170   status =
00171       fsal_internal_getPathFromHandle(p_context, p_parent_directory_handle, 1, &fsalpath,
00172                                       &buffstat);
00173   if(FSAL_IS_ERROR(status))
00174     Return(status.major, status.minor, INDEX_FSAL_symlink);
00175 
00176   status = fsal_internal_testAccess(p_context, FSAL_W_OK, &buffstat, NULL);
00177   if(FSAL_IS_ERROR(status))
00178     Return(status.major, status.minor, INDEX_FSAL_symlink);
00179 
00180   status = fsal_internal_appendFSALNameToFSALPath(&fsalpath, p_linkname);
00181   if(FSAL_IS_ERROR(status))
00182     Return(status.major, status.minor, INDEX_FSAL_symlink);
00183 
00184   /* create the symlink on the filesystem. */
00185 
00186   TakeTokenFSCall();
00187   rc = symlink(p_linkcontent->path, fsalpath.path);
00188   errsv = errno;
00189   ReleaseTokenFSCall();
00190 
00191   if(rc)
00192     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_symlink);
00193 
00194   /* stat the file & add it to the database */
00195   TakeTokenFSCall();
00196   rc = lstat(fsalpath.path, &buffstat);
00197   errsv = errno;
00198   ReleaseTokenFSCall();
00199 
00200   if(rc)
00201     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_symlink);
00202 
00203   if(FSAL_IS_ERROR(status = fsal_internal_posix2posixdb_fileinfo(&buffstat, &infofs)))
00204     Return(status.major, status.minor, INDEX_FSAL_symlink);
00205   if(FSAL_IS_ERROR
00206      (status =
00207       fsal_internal_posixdb_add_entry(p_context->p_conn, p_linkname, &infofs,
00208                                       p_parent_directory_handle, p_link_handle)))
00209     Return(status.major, status.minor, INDEX_FSAL_symlink);
00210 
00211   /* chown the symlink to the current user */
00212 
00213   TakeTokenFSCall();
00214   rc = lchown(fsalpath.path, p_context->credential.user, -1);
00215   errsv = errno;
00216   ReleaseTokenFSCall();
00217 
00218   if(rc)
00219     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_symlink);
00220 
00221   /* get attributes if asked */
00222 
00223   if(p_link_attributes)
00224     {
00225 
00226       status = posix2fsal_attributes(&buffstat, p_link_attributes);
00227 
00228       if(FSAL_IS_ERROR(status))
00229         {
00230           FSAL_CLEAR_MASK(p_link_attributes->asked_attributes);
00231           FSAL_SET_MASK(p_link_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00232         }
00233 
00234     }
00235 
00236   /* OK */
00237   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_symlink);
00238 }