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 00034 #ifdef HAVE_CONFIG_H 00035 #include "config.h" 00036 #endif 00037 00038 #include "fsal.h" 00039 #include "fsal_internal.h" 00040 #include "fsal_convert.h" 00041 #include <string.h> 00042 #include <unistd.h> 00043 00067 fsal_status_t GPFSFSAL_readlink(fsal_handle_t * p_linkhandle, /* IN */ 00068 fsal_op_context_t * p_context, /* IN */ 00069 fsal_path_t * p_link_content, /* OUT */ 00070 fsal_attrib_list_t * p_link_attributes /* [ IN/OUT ] */ 00071 ) 00072 { 00073 00074 /* int errsv; */ 00075 fsal_status_t status; 00076 char link_content_out[FSAL_MAX_PATH_LEN]; 00077 00078 /* sanity checks. 00079 * note : link_attributes is optional. 00080 */ 00081 if(!p_linkhandle || !p_context || !p_link_content) 00082 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readlink); 00083 00084 /* Read the link on the filesystem */ 00085 TakeTokenFSCall(); 00086 status = 00087 fsal_readlink_by_handle(p_context, p_linkhandle, link_content_out, 00088 FSAL_MAX_PATH_LEN); 00089 /* errsv = errno; */ 00090 ReleaseTokenFSCall(); 00091 00092 if(FSAL_IS_ERROR(status)) 00093 ReturnStatus(status, INDEX_FSAL_readlink); 00094 00095 /* convert char * to fsal_path_t */ 00096 status = FSAL_str2path(link_content_out, FSAL_MAX_PATH_LEN, p_link_content); 00097 00098 if(FSAL_IS_ERROR(status)) 00099 ReturnStatus(status, INDEX_FSAL_readlink); 00100 00101 /* retrieves object attributes, if asked */ 00102 00103 if(p_link_attributes) 00104 { 00105 00106 status = GPFSFSAL_getattrs(p_linkhandle, p_context, p_link_attributes); 00107 00108 /* On error, we set a flag in the returned attributes */ 00109 00110 if(FSAL_IS_ERROR(status)) 00111 { 00112 FSAL_CLEAR_MASK(p_link_attributes->asked_attributes); 00113 FSAL_SET_MASK(p_link_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00114 } 00115 00116 } 00117 00118 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readlink); 00119 00120 } 00121 00151 fsal_status_t GPFSFSAL_symlink(fsal_handle_t * p_parent_directory_handle, /* IN */ 00152 fsal_name_t * p_linkname, /* IN */ 00153 fsal_path_t * p_linkcontent, /* IN */ 00154 fsal_op_context_t * p_context, /* IN */ 00155 fsal_accessmode_t accessmode, /* IN (ignored) */ 00156 fsal_handle_t * p_link_handle, /* OUT */ 00157 fsal_attrib_list_t * p_link_attributes /* [ IN/OUT ] */ 00158 ) 00159 { 00160 00161 int rc, errsv; 00162 fsal_status_t status; 00163 int fd; 00164 int setgid_bit = FALSE; 00165 fsal_accessflags_t access_mask = 0; 00166 fsal_attrib_list_t parent_dir_attrs; 00167 00168 /* sanity checks. 00169 * note : link_attributes is optional. 00170 */ 00171 if(!p_parent_directory_handle || !p_context || 00172 !p_link_handle || !p_linkname || !p_linkcontent) 00173 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_symlink); 00174 00175 /* Tests if symlinking is allowed by configuration. */ 00176 00177 if(!global_fs_info.symlink_support) 00178 Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_symlink); 00179 00180 TakeTokenFSCall(); 00181 status = 00182 fsal_internal_handle2fd(p_context, p_parent_directory_handle, &fd, 00183 O_RDONLY | O_DIRECTORY); 00184 ReleaseTokenFSCall(); 00185 00186 if(FSAL_IS_ERROR(status)) 00187 ReturnStatus(status, INDEX_FSAL_symlink); 00188 00189 /* retrieve directory metadata, for checking access */ 00190 parent_dir_attrs.asked_attributes = GPFS_SUPPORTED_ATTRIBUTES; 00191 status = GPFSFSAL_getattrs(p_parent_directory_handle, p_context, &parent_dir_attrs); 00192 if(FSAL_IS_ERROR(status)) 00193 { 00194 close(fd); 00195 ReturnStatus(status, INDEX_FSAL_symlink); 00196 } 00197 00198 if(fsal2unix_mode(parent_dir_attrs.mode) & S_ISGID) 00199 setgid_bit = TRUE; 00200 00201 /* Set both mode and ace4 mask */ 00202 access_mask = FSAL_MODE_MASK_SET(FSAL_W_OK | FSAL_X_OK) | 00203 FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_ADD_FILE); 00204 00205 if(!p_context->export_context->fe_static_fs_info->accesscheck_support) 00206 status = fsal_internal_testAccess(p_context, access_mask, NULL, &parent_dir_attrs); 00207 else 00208 status = fsal_internal_access(p_context, p_parent_directory_handle,access_mask, 00209 &parent_dir_attrs); 00210 if(FSAL_IS_ERROR(status)) 00211 { 00212 close(fd); 00213 ReturnStatus(status, INDEX_FSAL_symlink); 00214 } 00215 00216 /* build symlink path */ 00217 00218 /* create the symlink on the filesystem. */ 00219 00220 TakeTokenFSCall(); 00221 rc = symlinkat(p_linkcontent->path, fd, p_linkname->name); 00222 errsv = errno; 00223 ReleaseTokenFSCall(); 00224 00225 if(rc) 00226 { 00227 close(fd); 00228 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_symlink); 00229 } 00230 00231 /* now get the associated handle, while there is a race, there is 00232 also a race lower down */ 00233 status = fsal_internal_get_handle_at(fd, p_linkname, p_link_handle); 00234 00235 if(FSAL_IS_ERROR(status)) 00236 { 00237 close(fd); 00238 ReturnStatus(status, INDEX_FSAL_symlink); 00239 } 00240 00241 /* chown the symlink to the current user/group */ 00242 TakeTokenFSCall(); 00243 rc = fchownat(fd, p_linkname->name, p_context->credential.user, 00244 setgid_bit ? -1 : p_context->credential.group, AT_SYMLINK_NOFOLLOW); 00245 errsv = errno; 00246 ReleaseTokenFSCall(); 00247 00248 close(fd); 00249 00250 if(rc) 00251 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_symlink); 00252 00253 /* get attributes if asked */ 00254 00255 if(p_link_attributes) 00256 { 00257 00258 status = GPFSFSAL_getattrs(p_link_handle, p_context, p_link_attributes); 00259 00260 /* On error, we set a flag in the returned attributes */ 00261 00262 if(FSAL_IS_ERROR(status)) 00263 { 00264 FSAL_CLEAR_MASK(p_link_attributes->asked_attributes); 00265 FSAL_SET_MASK(p_link_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00266 } 00267 00268 } 00269 00270 /* OK */ 00271 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_symlink); 00272 }