nfs-ganesha 1.4

fsal_rename.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 
00056 fsal_status_t LUSTREFSAL_rename(fsal_handle_t * p_old_parentdir_handle,   /* IN */
00057                                 fsal_name_t * p_old_name,       /* IN */
00058                                 fsal_handle_t * p_new_parentdir_handle,   /* IN */
00059                                 fsal_name_t * p_new_name,       /* IN */
00060                                 fsal_op_context_t * p_context,    /* IN */
00061                                 fsal_attrib_list_t * p_src_dir_attributes,      /* [ IN/OUT ] */
00062                                 fsal_attrib_list_t * p_tgt_dir_attributes       /* [ IN/OUT ] */
00063     )
00064 {
00065 
00066   int rc, errsv;
00067   fsal_status_t status;
00068   struct stat old_parent_buffstat, new_parent_buffstat, buffstat;
00069   fsal_path_t old_fsalpath, new_fsalpath;
00070   int src_equal_tgt = FALSE;
00071 
00072   /* sanity checks.
00073    * note : src/tgt_dir_attributes are optional.
00074    */
00075   if(!p_old_parentdir_handle || !p_new_parentdir_handle
00076      || !p_old_name || !p_new_name || !p_context)
00077     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_rename);
00078 
00079   /* Get directory access path by fid */
00080 
00081   status = fsal_internal_Handle2FidPath(p_context, p_old_parentdir_handle, &old_fsalpath);
00082   if(FSAL_IS_ERROR(status))
00083     ReturnStatus(status, INDEX_FSAL_rename);
00084 
00085   /* retrieve directory metadata for checking access rights */
00086 
00087   TakeTokenFSCall();
00088   rc = lstat(old_fsalpath.path, &old_parent_buffstat);
00089   errsv = errno;
00090   ReleaseTokenFSCall();
00091 
00092   if(rc)
00093     {
00094       if(errsv == ENOENT)
00095         Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_rename);
00096       else
00097         Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rename);
00098     }
00099 
00100   /* optimisation : don't do the job twice if source dir = dest dir  */
00101   if(!LUSTREFSAL_handlecmp(p_old_parentdir_handle, p_new_parentdir_handle, &status))
00102     {
00103       FSAL_pathcpy(&new_fsalpath, &old_fsalpath);
00104       src_equal_tgt = TRUE;
00105       new_parent_buffstat = old_parent_buffstat;
00106     }
00107   else
00108     {
00109       status =
00110           fsal_internal_Handle2FidPath(p_context, p_new_parentdir_handle, &new_fsalpath);
00111       if(FSAL_IS_ERROR(status))
00112         ReturnStatus(status, INDEX_FSAL_rename);
00113 
00114       /* retrieve destination attrs */
00115       TakeTokenFSCall();
00116       rc = lstat(new_fsalpath.path, &new_parent_buffstat);
00117       errsv = errno;
00118       ReleaseTokenFSCall();
00119 
00120       if(rc)
00121         {
00122           if(errsv == ENOENT)
00123             Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_rename);
00124           else
00125             Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rename);
00126         }
00127 
00128     }
00129 
00130   /* check access rights */
00131 
00132   status =
00133       fsal_internal_testAccess(p_context, FSAL_W_OK | FSAL_X_OK, &old_parent_buffstat,
00134                                NULL);
00135   if(FSAL_IS_ERROR(status))
00136     ReturnStatus(status, INDEX_FSAL_rename);
00137 
00138   if(!src_equal_tgt)
00139     {
00140       status =
00141           fsal_internal_testAccess(p_context, FSAL_W_OK | FSAL_X_OK, &new_parent_buffstat,
00142                                    NULL);
00143       if(FSAL_IS_ERROR(status))
00144         ReturnStatus(status, INDEX_FSAL_rename);
00145     }
00146 
00147   /* build file paths */
00148 
00149   status = fsal_internal_appendNameToPath(&old_fsalpath, p_old_name);
00150   if(FSAL_IS_ERROR(status))
00151     Return(status.major, status.minor, INDEX_FSAL_rename);
00152   status = fsal_internal_appendNameToPath(&new_fsalpath, p_new_name);
00153   if(FSAL_IS_ERROR(status))
00154     Return(status.major, status.minor, INDEX_FSAL_rename);
00155 
00156   TakeTokenFSCall();
00157   rc = lstat(old_fsalpath.path, &buffstat);
00158   errsv = errno;
00159   ReleaseTokenFSCall();
00160   if(rc)
00161     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rename);
00162 
00163   /* Check sticky bits */
00164 
00165   /* Sticky bit on the source directory => the user who wants to delete the file must own it or its parent dir */
00166   if((old_parent_buffstat.st_mode & S_ISVTX)
00167      && old_parent_buffstat.st_uid != p_context->credential.user
00168      && buffstat.st_uid != p_context->credential.user && p_context->credential.user != 0)
00169     Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_rename);
00170 
00171   /* Sticky bit on the target directory => the user who wants to create the file must own it or its parent dir */
00172   if(new_parent_buffstat.st_mode & S_ISVTX)
00173     {
00174       TakeTokenFSCall();
00175       rc = lstat(new_fsalpath.path, &buffstat);
00176       errsv = errno;
00177       ReleaseTokenFSCall();
00178       if(rc)
00179         {
00180           if(errsv != ENOENT)
00181             Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rename);
00182         }
00183       else if(new_parent_buffstat.st_uid != p_context->credential.user
00184               && buffstat.st_uid != p_context->credential.user
00185               && p_context->credential.user != 0)
00186         Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_rename);
00187     }
00188 
00189   /*************************************
00190    * Rename the file on the filesystem *
00191    *************************************/
00192   TakeTokenFSCall();
00193   rc = rename(old_fsalpath.path, new_fsalpath.path);
00194   errsv = errno;
00195   ReleaseTokenFSCall();
00196 
00197   if(rc)
00198     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rename);
00199 
00200   /***********************
00201    * Fill the attributes *
00202    ***********************/
00203 
00204   if(p_src_dir_attributes)
00205     {
00206 
00207       status =
00208           LUSTREFSAL_getattrs(p_old_parentdir_handle, p_context, p_src_dir_attributes);
00209 
00210       if(FSAL_IS_ERROR(status))
00211         {
00212           FSAL_CLEAR_MASK(p_src_dir_attributes->asked_attributes);
00213           FSAL_SET_MASK(p_src_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00214         }
00215 
00216     }
00217 
00218   if(p_tgt_dir_attributes)
00219     {
00220 
00221       status =
00222           LUSTREFSAL_getattrs(p_new_parentdir_handle, p_context, p_tgt_dir_attributes);
00223 
00224       if(FSAL_IS_ERROR(status))
00225         {
00226           FSAL_CLEAR_MASK(p_tgt_dir_attributes->asked_attributes);
00227           FSAL_SET_MASK(p_tgt_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00228         }
00229 
00230     }
00231 
00232   /* OK */
00233   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_rename);
00234 
00235 }