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 "fsal_common.h"
00021 #include "namespace.h"
00022 #include <string.h>
00023 
00052 fsal_status_t FUSEFSAL_readlink(fsal_handle_t * link_hdl, /* IN */
00053                                 fsal_op_context_t * p_context,      /* IN */
00054                                 fsal_path_t * p_link_content,   /* OUT */
00055                                 fsal_attrib_list_t * link_attributes    /* [ IN/OUT ] */
00056     )
00057 {
00058   fusefsal_handle_t * linkhandle = (fusefsal_handle_t *)link_hdl;
00059   int rc;
00060   fsal_status_t st;
00061   char link_content_out[FSAL_MAX_PATH_LEN];
00062   char object_path[FSAL_MAX_PATH_LEN];
00063 
00064   /* sanity checks.
00065    * note : link_attributes is optional.
00066    */
00067   if(!linkhandle || !p_context || !p_link_content)
00068     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readlink);
00069 
00070   /* get the full path for this inode */
00071   rc = NamespacePath(linkhandle->data.inode, linkhandle->data.device, linkhandle->data.validator,
00072                      object_path);
00073   if(rc)
00074     Return(ERR_FSAL_STALE, rc, INDEX_FSAL_readlink);
00075 
00076   /* set context for the next operation, so it can be retrieved by FS thread */
00077   fsal_set_thread_context(p_context);
00078 
00079   if(p_fs_ops->readlink)
00080     {
00081       TakeTokenFSCall();
00082 
00083       rc = p_fs_ops->readlink(object_path, link_content_out, FSAL_MAX_PATH_LEN);
00084 
00085       ReleaseTokenFSCall();
00086 
00087       if(rc)
00088         Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_readlink);
00089 
00090     }
00091   else
00092     /* return empty link */
00093     link_content_out[0] = '\0';
00094 
00095   /* convert string to fsal_path_t */
00096 
00097   st = FSAL_str2path(link_content_out, FSAL_MAX_PATH_LEN, p_link_content);
00098 
00099   if(FSAL_IS_ERROR(st))
00100     Return(st.major, st.minor, INDEX_FSAL_readlink);
00101 
00102   /* retrieves object attributes, if asked */
00103 
00104   if(link_attributes)
00105     {
00106 
00107       fsal_status_t status;
00108 
00109       status = FUSEFSAL_getattrs(link_hdl, p_context, link_attributes);
00110 
00111       /* On error, we set a flag in the returned attributes */
00112 
00113       if(FSAL_IS_ERROR(status))
00114         {
00115           FSAL_CLEAR_MASK(link_attributes->asked_attributes);
00116           FSAL_SET_MASK(link_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00117         }
00118 
00119     }
00120 
00121   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readlink);
00122 
00123 }
00124 
00159 fsal_status_t FUSEFSAL_symlink(fsal_handle_t * parent,     /* IN */
00160                                fsal_name_t * p_linkname,        /* IN */
00161                                fsal_path_t * p_linkcontent,     /* IN */
00162                                fsal_op_context_t * p_context,       /* IN */
00163                                fsal_accessmode_t accessmode,    /* IN (ignored) */
00164                                fsal_handle_t * link_hdl, /* OUT */
00165                                fsal_attrib_list_t * link_attributes     /* [ IN/OUT ] */
00166     )
00167 {
00168 
00169   int rc;
00170   char parent_path[FSAL_MAX_PATH_LEN];
00171   char child_path[FSAL_MAX_PATH_LEN];
00172   struct stat buffstat;
00173   fusefsal_handle_t * parent_directory_handle = (fusefsal_handle_t *)parent;
00174   fusefsal_handle_t * link_handle = (fusefsal_handle_t *)link_hdl;
00175 
00176   /* sanity checks.
00177    * note : link_attributes is optional.
00178    */
00179   if(!parent_directory_handle ||
00180      !p_context || !link_handle || !p_linkname || !p_linkcontent)
00181     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_symlink);
00182 
00183   /* Tests if symlinking is allowed by configuration and filesystem. */
00184 
00185   if(!global_fs_info.symlink_support || !p_fs_ops->symlink)
00186     Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_symlink);
00187 
00188   /* get the full path for parent inode */
00189   rc = NamespacePath(parent_directory_handle->data.inode,
00190                      parent_directory_handle->data.device,
00191                      parent_directory_handle->data.validator, parent_path);
00192   if(rc)
00193     Return(ERR_FSAL_STALE, rc, INDEX_FSAL_symlink);
00194 
00195   /* append child name to parent path */
00196   FSAL_internal_append_path(child_path, parent_path, p_linkname->name);
00197 
00198   /* set context for the next operation, so it can be retrieved by FS thread */
00199   fsal_set_thread_context(p_context);
00200 
00201   TakeTokenFSCall();
00202 
00203   rc = p_fs_ops->symlink(p_linkcontent->path, child_path);
00204 
00205   ReleaseTokenFSCall();
00206 
00207   if(rc)
00208     Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_symlink);
00209 
00210   /* set the owner for the newly created entry */
00211 
00212   if(p_fs_ops->chown)
00213     {
00214       TakeTokenFSCall();
00215       rc = p_fs_ops->chown(child_path, p_context->credential.user,
00216                            p_context->credential.group);
00217       ReleaseTokenFSCall();
00218 
00219       LogFullDebug(COMPONENT_FSAL, "chown: status = %d", rc);
00220 
00221       if(rc)
00222         Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_symlink);
00223     }
00224 
00225   /* get info about this symlink */
00226 
00227   TakeTokenFSCall();
00228   rc = p_fs_ops->getattr(child_path, &buffstat);
00229   ReleaseTokenFSCall();
00230 
00231   if(rc)
00232     Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_symlink);
00233 
00234   link_handle->data.validator = buffstat.st_ctime;
00235 
00236   /* add handle to namespace */
00237   NamespaceAdd(parent_directory_handle->data.inode,
00238                parent_directory_handle->data.device,
00239                parent_directory_handle->data.validator,
00240                p_linkname->name,
00241                buffstat.st_ino, buffstat.st_dev, &link_handle->data.validator);
00242 
00243   /* set output handle */
00244   link_handle->data.inode = buffstat.st_ino;
00245   link_handle->data.device = buffstat.st_dev;
00246 
00247   if(link_attributes)
00248     {
00249       fsal_status_t status = posix2fsal_attributes(&buffstat, link_attributes);
00250 
00251       if(FSAL_IS_ERROR(status))
00252         {
00253           FSAL_CLEAR_MASK(link_attributes->asked_attributes);
00254           FSAL_SET_MASK(link_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00255         }
00256 
00257     }
00258 
00259   /* OK */
00260   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_symlink);
00261 }