nfs-ganesha 1.4
|
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 }