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