nfs-ganesha 1.4

fsal_unlink.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/access_check.h"
00042 #include "fsal_convert.h"
00043 #include <unistd.h>
00044 
00068 fsal_status_t XFSFSAL_unlink(fsal_handle_t * p_parent_directory_handle,      /* IN */
00069                              fsal_name_t * p_object_name,       /* IN */
00070                              fsal_op_context_t * p_context,  /* IN */
00071                              fsal_attrib_list_t * p_parent_directory_attributes /* [IN/OUT ] */
00072     )
00073 {
00074 
00075   fsal_status_t status;
00076   int rc, errsv;
00077   struct stat buffstat, buffstat_parent;
00078   int fd;
00079 
00080   /* sanity checks. */
00081   if(!p_parent_directory_handle || !p_context || !p_object_name)
00082     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_unlink);
00083 
00084   /* build the FID path */
00085   TakeTokenFSCall();
00086   status =
00087       fsal_internal_handle2fd(p_context, p_parent_directory_handle, &fd, O_DIRECTORY);
00088   ReleaseTokenFSCall();
00089   if(FSAL_IS_ERROR(status))
00090     ReturnStatus(status, INDEX_FSAL_unlink);
00091 
00092   /* get directory metadata */
00093   TakeTokenFSCall();
00094   rc = fstat(fd, &buffstat_parent);
00095   errsv = errno;
00096   ReleaseTokenFSCall();
00097   if(rc)
00098     {
00099       close(fd);
00100 
00101       if(errsv == ENOENT)
00102         Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_unlink);
00103       else
00104         Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_unlink);
00105     }
00106 
00107   /* build the child path */
00108 
00109   /* get file metadata */
00110   TakeTokenFSCall();
00111   rc = fstatat(fd, p_object_name->name, &buffstat, AT_SYMLINK_NOFOLLOW);
00112   errsv = errno;
00113   ReleaseTokenFSCall();
00114   if(rc)
00115     {
00116       close(fd);
00117       Return(posix2fsal_error(errno), errno, INDEX_FSAL_unlink);
00118     }
00119 
00120   /* check access rights */
00121 
00122   /* Sticky bit on the directory => the user who wants to delete the file must own it or its parent dir */
00123   if((buffstat_parent.st_mode & S_ISVTX)
00124      && buffstat_parent.st_uid != ((xfsfsal_op_context_t *)p_context)->credential.user
00125      && buffstat.st_uid != ((xfsfsal_op_context_t *)p_context)->credential.user
00126      && ((xfsfsal_op_context_t *)p_context)->credential.user != 0)
00127     {
00128       close(fd);
00129       Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_unlink);
00130     }
00131 
00132   /* client must be able to lookup the parent directory and modify it */
00133   status =
00134       fsal_check_access(p_context, FSAL_W_OK | FSAL_X_OK, &buffstat_parent, NULL);
00135   if(FSAL_IS_ERROR(status))
00136     ReturnStatus(status, INDEX_FSAL_unlink);
00137 
00138   /******************************
00139    * DELETE FROM THE FILESYSTEM *
00140    ******************************/
00141   TakeTokenFSCall();
00142   /* If the object to delete is a directory, use 'rmdir' to delete the object, else use 'unlink' */
00143   rc = (S_ISDIR(buffstat.st_mode)) ? unlinkat(fd, p_object_name->name,
00144                                               AT_REMOVEDIR) : unlinkat(fd,
00145                                                                        p_object_name->name,
00146                                                                        0);
00147   errsv = errno;
00148   ReleaseTokenFSCall();
00149 
00150   close(fd);
00151 
00152   if(rc)
00153     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_unlink);
00154 
00155   /***********************
00156    * FILL THE ATTRIBUTES *
00157    ***********************/
00158 
00159   if(p_parent_directory_attributes)
00160     {
00161       status =
00162           XFSFSAL_getattrs(p_parent_directory_handle, p_context,
00163                            p_parent_directory_attributes);
00164       if(FSAL_IS_ERROR(status))
00165         {
00166           FSAL_CLEAR_MASK(p_parent_directory_attributes->asked_attributes);
00167           FSAL_SET_MASK(p_parent_directory_attributes->asked_attributes,
00168                         FSAL_ATTR_RDATTR_ERR);
00169         }
00170     }
00171   /* OK */
00172   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_unlink);
00173 
00174 }