nfs-ganesha 1.4

fsal_rename.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
00003  *
00004  * Copyright CEA/DAM/DIF  (2008)
00005  * contributeur : Philippe DENIEL   philippe.deniel@cea.fr
00006  *                Thomas LEIBOVICI  thomas.leibovici@cea.fr
00007  *
00008  *
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 3 of the License, or (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  * ------------- 
00024  */
00025 
00035 #ifdef HAVE_CONFIG_H
00036 #include "config.h"
00037 #endif
00038 
00039 #include "fsal.h"
00040 #include "fsal_internal.h"
00041 #include "fsal_convert.h"
00042 
00077 fsal_status_t GPFSFSAL_rename(fsal_handle_t * p_old_parentdir_handle,       /* IN */
00078                           fsal_name_t * p_old_name,     /* IN */
00079                           fsal_handle_t * p_new_parentdir_handle,       /* IN */
00080                           fsal_name_t * p_new_name,     /* IN */
00081                           fsal_op_context_t * p_context,        /* IN */
00082                           fsal_attrib_list_t * p_src_dir_attributes,    /* [ IN/OUT ] */
00083                           fsal_attrib_list_t * p_tgt_dir_attributes     /* [ IN/OUT ] */
00084     )
00085 {
00086 
00087   fsal_status_t status;
00088   struct stat buffstat;
00089   int src_equal_tgt = FALSE;
00090   fsal_accessflags_t access_mask = 0;
00091   fsal_attrib_list_t src_dir_attrs, tgt_dir_attrs;
00092 
00093   /* sanity checks.
00094    * note : src/tgt_dir_attributes are optional.
00095    */
00096   if(!p_old_parentdir_handle || !p_new_parentdir_handle
00097      || !p_old_name || !p_new_name || !p_context)
00098     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_rename);
00099 
00100   /* retrieve directory metadata for checking access rights */
00101 
00102   src_dir_attrs.asked_attributes = GPFS_SUPPORTED_ATTRIBUTES;
00103   status = GPFSFSAL_getattrs(p_old_parentdir_handle, p_context, &src_dir_attrs);
00104   if(FSAL_IS_ERROR(status))
00105     {
00106       ReturnStatus(status, INDEX_FSAL_rename);
00107     }
00108 
00109   /* optimisation : don't do the job twice if source dir = dest dir  */
00110   if(!FSAL_handlecmp(p_old_parentdir_handle, p_new_parentdir_handle, &status))
00111     {
00112       src_equal_tgt = TRUE;
00113       tgt_dir_attrs = src_dir_attrs;
00114     }
00115   else
00116     {
00117       /* retrieve destination attrs */
00118       tgt_dir_attrs.asked_attributes = GPFS_SUPPORTED_ATTRIBUTES;
00119       status = GPFSFSAL_getattrs(p_new_parentdir_handle, p_context, &tgt_dir_attrs);
00120       if(FSAL_IS_ERROR(status))
00121         {
00122           ReturnStatus(status, INDEX_FSAL_rename);
00123         }
00124     }
00125 
00126   /* check access rights */
00127 
00128   /* Set both mode and ace4 mask */
00129   access_mask = FSAL_MODE_MASK_SET(FSAL_W_OK | FSAL_X_OK) |
00130                 FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_DELETE_CHILD);
00131 
00132   if(!p_context->export_context->fe_static_fs_info->accesscheck_support)
00133   status = fsal_internal_testAccess(p_context, access_mask, NULL, &src_dir_attrs);
00134   else
00135     status = fsal_internal_access(p_context, p_old_parentdir_handle, access_mask,
00136                                   &src_dir_attrs);
00137   if(FSAL_IS_ERROR(status)) {
00138     ReturnStatus(status, INDEX_FSAL_rename);
00139   }
00140 
00141   if(!src_equal_tgt)
00142     {
00143       access_mask = FSAL_MODE_MASK_SET(FSAL_W_OK | FSAL_X_OK) |
00144                 FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_ADD_FILE |
00145                                    FSAL_ACE_PERM_ADD_SUBDIRECTORY);
00146 
00147           if(!p_context->export_context->fe_static_fs_info->accesscheck_support)
00148             status = fsal_internal_testAccess(p_context, access_mask, NULL, &tgt_dir_attrs);
00149           else
00150             status = fsal_internal_access(p_context, p_new_parentdir_handle, access_mask,
00151                                           &tgt_dir_attrs);
00152       if(FSAL_IS_ERROR(status)) {
00153         ReturnStatus(status, INDEX_FSAL_rename);
00154       }
00155     }
00156 
00157   /* build file paths */
00158   TakeTokenFSCall();
00159   status = fsal_internal_stat_name(p_context, p_old_parentdir_handle, p_old_name, &buffstat);
00160   ReleaseTokenFSCall();
00161   if(FSAL_IS_ERROR(status))
00162     ReturnStatus(status, INDEX_FSAL_rename);
00163 
00164   /* Check sticky bits */
00165 
00166   /* Sticky bit on the source directory => the user who wants to delete the file must own it or its parent dir */
00167   if((fsal2unix_mode(src_dir_attrs.mode) & S_ISVTX) &&
00168      src_dir_attrs.owner != p_context->credential.user &&
00169      buffstat.st_uid != p_context->credential.user && p_context->credential.user != 0) {
00170     Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_rename);
00171   }
00172 
00173   /* Sticky bit on the target directory => the user who wants to create the file must own it or its parent dir */
00174   if(fsal2unix_mode(tgt_dir_attrs.mode) & S_ISVTX)
00175     {
00176       TakeTokenFSCall();
00177       status = fsal_internal_stat_name(p_context, p_new_parentdir_handle, p_new_name, &buffstat);
00178       ReleaseTokenFSCall();
00179 
00180       if(FSAL_IS_ERROR(status))
00181         {
00182           if(status.major != ERR_FSAL_NOENT)
00183             {
00184               ReturnStatus(status, INDEX_FSAL_rename);
00185             }
00186         }
00187       else
00188         {
00189 
00190           if(tgt_dir_attrs.owner != p_context->credential.user
00191              && buffstat.st_uid != p_context->credential.user
00192              && p_context->credential.user != 0)
00193             {
00194               Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_rename);
00195             }
00196         }
00197     }
00198 
00199   /*************************************
00200    * Rename the file on the filesystem *
00201    *************************************/
00202   TakeTokenFSCall();
00203   status = fsal_internal_rename_fh(p_context, p_old_parentdir_handle,
00204                                    p_new_parentdir_handle, p_old_name,
00205                                    p_new_name);
00206   ReleaseTokenFSCall();
00207 
00208   if(FSAL_IS_ERROR(status))
00209     ReturnStatus(status, INDEX_FSAL_rename);
00210 
00211   /***********************
00212    * Fill the attributes *
00213    ***********************/
00214 
00215   if(p_src_dir_attributes)
00216     {
00217 
00218       status = GPFSFSAL_getattrs(p_old_parentdir_handle, p_context, p_src_dir_attributes);
00219 
00220       if(FSAL_IS_ERROR(status))
00221         {
00222           FSAL_CLEAR_MASK(p_src_dir_attributes->asked_attributes);
00223           FSAL_SET_MASK(p_src_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00224         }
00225 
00226     }
00227 
00228   if(p_tgt_dir_attributes)
00229     {
00230 
00231       status = GPFSFSAL_getattrs(p_new_parentdir_handle, p_context, p_tgt_dir_attributes);
00232 
00233       if(FSAL_IS_ERROR(status))
00234         {
00235           FSAL_CLEAR_MASK(p_tgt_dir_attributes->asked_attributes);
00236           FSAL_SET_MASK(p_tgt_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00237         }
00238 
00239     }
00240 
00241   /* OK */
00242   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_rename);
00243 
00244 }