nfs-ganesha 1.4

fsal_unlink.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 
00045 fsal_status_t POSIXFSAL_unlink(fsal_handle_t * parent_directory_handle,  /* IN */
00046                                fsal_name_t * p_object_name,     /* IN */
00047                                fsal_op_context_t * context,      /* IN */
00048                                fsal_attrib_list_t * p_parent_directory_attributes       /* [IN/OUT ] */
00049     )
00050 {
00051   posixfsal_handle_t * p_parent_directory_handle
00052     = (posixfsal_handle_t *) parent_directory_handle;
00053   posixfsal_op_context_t * p_context = (posixfsal_op_context_t *) context;
00054   fsal_status_t status;
00055   fsal_posixdb_status_t statusdb;
00056   int rc, errsv;
00057   struct stat buffstat, buffstat_parent;
00058   fsal_path_t fsalpath;
00059   fsal_posixdb_fileinfo_t info;
00060 
00061   /* sanity checks. */
00062   if(!p_parent_directory_handle || !p_context || !p_object_name)
00063     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_unlink);
00064 
00065   /* check credential */
00066   /* need to be able to 'read' the parent directory & to delete it */
00067 
00068   /* build the destination path */
00069   status =
00070       fsal_internal_getPathFromHandle(p_context, p_parent_directory_handle, 1, &fsalpath,
00071                                       &buffstat_parent);
00072   if(FSAL_IS_ERROR(status))
00073     Return(status.major, status.minor, INDEX_FSAL_unlink);
00074 
00075   status = fsal_internal_appendFSALNameToFSALPath(&fsalpath, p_object_name);
00076   if(FSAL_IS_ERROR(status))
00077     Return(status.major, status.minor, INDEX_FSAL_unlink);
00078 
00079   /* 
00080    *  Action depends on the object type to be deleted.
00081    */
00082 
00083   TakeTokenFSCall();
00084   rc = lstat(fsalpath.path, &buffstat);
00085   errsv = errno;
00086   ReleaseTokenFSCall();
00087   if(rc)
00088     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_unlink);
00089 
00090   if(FSAL_IS_ERROR(status = fsal_internal_posix2posixdb_fileinfo(&buffstat, &info)))
00091     Return(status.major, status.minor, INDEX_FSAL_unlink);
00092 
00093   /**************************************************************
00094    * Lock the handle entry related to this file in the database *
00095    **************************************************************/
00096 
00097   statusdb = fsal_posixdb_lockHandleForUpdate(p_context->p_conn, &info);
00098   if(FSAL_IS_ERROR(status = posixdb2fsal_error(statusdb)))
00099     {
00100       fsal_posixdb_cancelHandleLock(p_context->p_conn);
00101       Return(status.major, status.minor, INDEX_FSAL_unlink);
00102     }
00103 
00104   /****************
00105    * CHECK ACCESS *
00106    ****************/
00107   if((buffstat_parent.st_mode & S_ISVTX)        /* Sticky bit on the directory => the user who wants to delete the file must own it or its parent dir */
00108      && buffstat_parent.st_uid != p_context->credential.user
00109      && buffstat.st_uid != p_context->credential.user && p_context->credential.user != 0)
00110     {
00111       fsal_posixdb_cancelHandleLock(p_context->p_conn);
00112       Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_unlink);
00113     }
00114 
00115   if(FSAL_IS_ERROR
00116      (status =
00117       fsal_internal_testAccess(p_context, FSAL_W_OK | FSAL_X_OK, &buffstat_parent, NULL)))
00118     {
00119       fsal_posixdb_cancelHandleLock(p_context->p_conn);
00120       Return(status.major, status.minor, INDEX_FSAL_unlink);
00121     }
00122 
00123   /******************************
00124    * DELETE FROM THE FILESYSTEM *
00125    ******************************/
00126   TakeTokenFSCall();
00127   /* If the object to delete is a directory, use 'rmdir' to delete the object, else use 'unlink' */
00128   rc = (S_ISDIR(buffstat.st_mode)) ? rmdir(fsalpath.path) : unlink(fsalpath.path);
00129   errsv = errno;
00130   ReleaseTokenFSCall();
00131   if(rc)
00132     {
00133       fsal_posixdb_cancelHandleLock(p_context->p_conn);
00134       Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_unlink);
00135     }
00136 
00137   /****************************
00138    * DELETE FROM THE DATABASE *
00139    ****************************/
00140 
00141   /* We have to delete the path from the database, and the handle if the object was a directory or has no more hardlink */
00142   statusdb =
00143       fsal_posixdb_delete(p_context->p_conn, p_parent_directory_handle, p_object_name,
00144                           &info);
00145   /* After this operation, there's no need to 'fsal_posixdb_cancelHandleLock' because the transaction is ended */
00146   switch (statusdb.major)
00147     {
00148     case ERR_FSAL_POSIXDB_NOERR:
00149     case ERR_FSAL_POSIXDB_NOENT:
00150       /* nothing to do */
00151       break;
00152     default:
00153       if(FSAL_IS_ERROR(status = posixdb2fsal_error(statusdb)))
00154         Return(status.major, status.minor, INDEX_FSAL_unlink);
00155     }
00156 
00157   /***********************
00158    * FILL THE ATTRIBUTES *
00159    ***********************/
00160 
00161   if(p_parent_directory_attributes)
00162     {
00163       status = posix2fsal_attributes(&buffstat_parent, 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           Return(status.major, status.minor, INDEX_FSAL_opendir);
00170         }
00171     }
00172   /* OK */
00173   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_unlink);
00174 
00175 }