nfs-ganesha 1.4

fsal_rename.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
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 POSIXFSAL_rename(fsal_handle_t * old_parentdir_handle,     /* IN */
00057                                fsal_name_t * p_old_name,        /* IN */
00058                                fsal_handle_t * new_parentdir_handle,     /* IN */
00059                                fsal_name_t * p_new_name,        /* IN */
00060                                fsal_op_context_t * 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   posixfsal_handle_t * p_old_parentdir_handle
00066     = (posixfsal_handle_t *) old_parentdir_handle;
00067   posixfsal_handle_t * p_new_parentdir_handle
00068     = (posixfsal_handle_t *) new_parentdir_handle;
00069   posixfsal_op_context_t * p_context = (posixfsal_op_context_t *) context;
00070   int rc, errsv;
00071   fsal_status_t status;
00072   fsal_posixdb_status_t statusdb;
00073   struct stat old_parent_buffstat, new_parent_buffstat, buffstat;
00074   fsal_path_t old_fsalpath, new_fsalpath;
00075   fsal_posixdb_fileinfo_t info;
00076 
00077   /* sanity checks.
00078    * note : src/tgt_dir_attributes are optional.
00079    */
00080   if(!p_old_parentdir_handle ||
00081      !p_new_parentdir_handle || !p_old_name || !p_new_name || !p_context)
00082     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_rename);
00083 
00084   /**************************************
00085    * Build the old path and the new one *
00086    **************************************/
00087   status =
00088       fsal_internal_getPathFromHandle(p_context, p_old_parentdir_handle, 1, &old_fsalpath,
00089                                       &old_parent_buffstat);
00090   if(FSAL_IS_ERROR(status))
00091     Return(status.major, status.minor, INDEX_FSAL_rename);
00092 
00093   /* optimisation : don't do the work two times if source dir = dest dir  */
00094   if(!POSIXFSAL_handlecmp(p_old_parentdir_handle, p_new_parentdir_handle, &status))
00095     {
00096       FSAL_pathcpy(&new_fsalpath, &old_fsalpath);
00097       new_parent_buffstat = old_parent_buffstat;
00098     }
00099   else
00100     {
00101       status =
00102           fsal_internal_getPathFromHandle(p_context, p_new_parentdir_handle, 1,
00103                                           &new_fsalpath, &new_parent_buffstat);
00104       if(FSAL_IS_ERROR(status))
00105         Return(status.major, status.minor, INDEX_FSAL_rename);
00106     }
00107 
00108   status = fsal_internal_appendFSALNameToFSALPath(&old_fsalpath, p_old_name);
00109   if(FSAL_IS_ERROR(status))
00110     Return(status.major, status.minor, INDEX_FSAL_mkdir);
00111   status = fsal_internal_appendFSALNameToFSALPath(&new_fsalpath, p_new_name);
00112   if(FSAL_IS_ERROR(status))
00113     Return(status.major, status.minor, INDEX_FSAL_mkdir);
00114 
00115   TakeTokenFSCall();
00116   rc = lstat(old_fsalpath.path, &buffstat);
00117   errsv = errno;
00118   ReleaseTokenFSCall();
00119   if(rc)
00120     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rename);
00121 
00122   if(FSAL_IS_ERROR(status = fsal_internal_posix2posixdb_fileinfo(&buffstat, &info)))
00123     Return(status.major, status.minor, INDEX_FSAL_rename);
00124 
00125   /********************
00126    * Check credential *
00127    ********************/
00128 
00129   if(FSAL_IS_ERROR
00130      (status =
00131       fsal_internal_testAccess(p_context, FSAL_W_OK | FSAL_X_OK, &old_parent_buffstat,
00132                                NULL)))
00133     Return(status.major, status.minor, INDEX_FSAL_rename);
00134 
00135   if(FSAL_IS_ERROR
00136      (status =
00137       fsal_internal_testAccess(p_context, FSAL_W_OK | FSAL_X_OK, &new_parent_buffstat,
00138                                NULL)))
00139     Return(status.major, status.minor, INDEX_FSAL_rename);
00140 
00141   /* Check sticky bit on directories */
00142 
00143   if((old_parent_buffstat.st_mode & S_ISVTX)    /* Sticky bit on the directory => the user who wants to delete the file must own it or its parent dir */
00144      && old_parent_buffstat.st_uid != p_context->credential.user
00145      && buffstat.st_uid != p_context->credential.user && p_context->credential.user != 0)
00146     Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_rename);
00147 
00148   if(new_parent_buffstat.st_mode & S_ISVTX)
00149     {                           /* Sticky bit on the directory => the user who wants to delete the file must own it or its parent dir */
00150       TakeTokenFSCall();
00151       rc = lstat(new_fsalpath.path, &buffstat);
00152       errsv = errno;
00153       ReleaseTokenFSCall();
00154       if(rc)
00155         {
00156           if(errsv != ENOENT)
00157             Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rename);
00158         }
00159       else if(new_parent_buffstat.st_uid != p_context->credential.user
00160               && buffstat.st_uid != p_context->credential.user
00161               && p_context->credential.user != 0)
00162         Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_rename);
00163     }
00164   /*************************************
00165    * Rename the file on the filesystem *
00166    *************************************/
00167   TakeTokenFSCall();
00168   rc = rename(old_fsalpath.path, new_fsalpath.path);
00169   errsv = errno;
00170   ReleaseTokenFSCall();
00171 
00172   if(rc)
00173     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rename);
00174 
00175   /***********************************
00176    * Rename the file in the database *
00177    ***********************************/
00178   statusdb = fsal_posixdb_replace(p_context->p_conn,
00179                                   &info,
00180                                   p_old_parentdir_handle,
00181                                   p_old_name, p_new_parentdir_handle, p_new_name);
00182 
00183   switch (statusdb.major)
00184     {
00185     case ERR_FSAL_POSIXDB_NOENT:
00186     case ERR_FSAL_POSIXDB_NOERR:
00187       break;
00188     default:
00189       if(FSAL_IS_ERROR(status = posixdb2fsal_error(statusdb)))
00190         Return(status.major, status.minor, INDEX_FSAL_rename);
00191     }
00192 
00193   /***********************
00194    * Fill the attributes *
00195    ***********************/
00196 
00197   if(p_src_dir_attributes)
00198     {
00199 
00200       status =
00201           POSIXFSAL_getattrs(p_old_parentdir_handle, p_context, p_src_dir_attributes);
00202 
00203       if(FSAL_IS_ERROR(status))
00204         {
00205           FSAL_CLEAR_MASK(p_src_dir_attributes->asked_attributes);
00206           FSAL_SET_MASK(p_src_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00207         }
00208 
00209     }
00210 
00211   if(p_tgt_dir_attributes)
00212     {
00213 
00214       status =
00215           POSIXFSAL_getattrs(p_new_parentdir_handle, p_context, p_tgt_dir_attributes);
00216 
00217       if(FSAL_IS_ERROR(status))
00218         {
00219           FSAL_CLEAR_MASK(p_tgt_dir_attributes->asked_attributes);
00220           FSAL_SET_MASK(p_tgt_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00221         }
00222 
00223     }
00224 
00225   /* OK */
00226   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_rename);
00227 
00228 }