nfs-ganesha 1.4
|
00001 /* 00002 * vim:expandtab:shiftwidth=4:tabstop=4: 00003 */ 00004 00013 #ifdef HAVE_CONFIG_H 00014 #include "config.h" 00015 #endif 00016 00017 #include "fsal.h" 00018 #include "fsal_internal.h" 00019 #include "fsal_convert.h" 00020 #include <string.h> 00021 #include <unistd.h> 00022 00046 fsal_status_t LUSTREFSAL_readlink(fsal_handle_t * p_linkhandle, /* IN */ 00047 fsal_op_context_t * p_context, /* IN */ 00048 fsal_path_t * p_link_content, /* OUT */ 00049 fsal_attrib_list_t * p_link_attributes /* [ IN/OUT ] */ 00050 ) 00051 { 00052 00053 int rc, errsv; 00054 fsal_status_t status; 00055 char link_content_out[FSAL_MAX_PATH_LEN]; 00056 fsal_path_t fsalpath; 00057 00058 /* sanity checks. 00059 * note : link_attributes is optional. 00060 */ 00061 if(!p_linkhandle || !p_context || !p_link_content) 00062 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readlink); 00063 00064 status = fsal_internal_Handle2FidPath(p_context, p_linkhandle, &fsalpath); 00065 if(FSAL_IS_ERROR(status)) 00066 ReturnStatus(status, INDEX_FSAL_readlink); 00067 00068 memset(link_content_out, 0, FSAL_MAX_PATH_LEN); 00069 00070 /* Read the link on the filesystem */ 00071 00072 TakeTokenFSCall(); 00073 rc = readlink(fsalpath.path, link_content_out, FSAL_MAX_PATH_LEN); 00074 errsv = errno; 00075 ReleaseTokenFSCall(); 00076 00077 /* rc is the length for the symlink content or -1 on error !!! */ 00078 if(rc < 0) 00079 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_readlink); 00080 00081 /* convert char * to fsal_path_t */ 00082 status = FSAL_str2path(link_content_out, FSAL_MAX_PATH_LEN, p_link_content); 00083 00084 if(FSAL_IS_ERROR(status)) 00085 ReturnStatus(status, INDEX_FSAL_readlink); 00086 00087 /* retrieves object attributes, if asked */ 00088 00089 if(p_link_attributes) 00090 { 00091 00092 status = LUSTREFSAL_getattrs(p_linkhandle, p_context, p_link_attributes); 00093 00094 /* On error, we set a flag in the returned attributes */ 00095 00096 if(FSAL_IS_ERROR(status)) 00097 { 00098 FSAL_CLEAR_MASK(p_link_attributes->asked_attributes); 00099 FSAL_SET_MASK(p_link_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00100 } 00101 00102 } 00103 00104 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readlink); 00105 00106 } 00107 00137 fsal_status_t LUSTREFSAL_symlink(fsal_handle_t * p_parent_directory_handle, /* IN */ 00138 fsal_name_t * p_linkname, /* IN */ 00139 fsal_path_t * p_linkcontent, /* IN */ 00140 fsal_op_context_t * p_context, /* IN */ 00141 fsal_accessmode_t accessmode, /* IN (ignored) */ 00142 fsal_handle_t * p_link_handle, /* OUT */ 00143 fsal_attrib_list_t * p_link_attributes /* [ IN/OUT ] */ 00144 ) 00145 { 00146 00147 int rc, errsv; 00148 fsal_status_t status; 00149 fsal_path_t fsalpath; 00150 struct stat buffstat; 00151 int setgid_bit = FALSE; 00152 00153 /* sanity checks. 00154 * note : link_attributes is optional. 00155 */ 00156 if(!p_parent_directory_handle || !p_context || 00157 !p_link_handle || !p_linkname || !p_linkcontent) 00158 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_symlink); 00159 00160 /* Tests if symlinking is allowed by configuration. */ 00161 00162 if(!global_fs_info.symlink_support) 00163 Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_symlink); 00164 00165 /* build the new path and check the permissions on the parent directory */ 00166 status = fsal_internal_Handle2FidPath(p_context, p_parent_directory_handle, &fsalpath); 00167 if(FSAL_IS_ERROR(status)) 00168 ReturnStatus(status, INDEX_FSAL_symlink); 00169 00170 /* retrieve directory metadata, for checking access */ 00171 TakeTokenFSCall(); 00172 rc = lstat(fsalpath.path, &buffstat); 00173 errsv = errno; 00174 ReleaseTokenFSCall(); 00175 00176 if(rc) 00177 { 00178 if(errsv == ENOENT) 00179 Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_symlink); 00180 else 00181 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_symlink); 00182 } 00183 00184 if(buffstat.st_mode & S_ISGID) 00185 setgid_bit = TRUE; 00186 00187 status = fsal_internal_testAccess(p_context, FSAL_W_OK, &buffstat, NULL); 00188 if(FSAL_IS_ERROR(status)) 00189 ReturnStatus(status, INDEX_FSAL_symlink); 00190 00191 /* build symlink path */ 00192 00193 status = fsal_internal_appendNameToPath(&fsalpath, p_linkname); 00194 if(FSAL_IS_ERROR(status)) 00195 ReturnStatus(status, INDEX_FSAL_symlink); 00196 00197 /* create the symlink on the filesystem. */ 00198 00199 TakeTokenFSCall(); 00200 rc = symlink(p_linkcontent->path, fsalpath.path); 00201 errsv = errno; 00202 ReleaseTokenFSCall(); 00203 00204 if(rc) 00205 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_symlink); 00206 00207 /* Get symlink handle */ 00208 TakeTokenFSCall(); 00209 status = fsal_internal_Path2Handle(p_context, &fsalpath, p_link_handle); 00210 ReleaseTokenFSCall(); 00211 if(FSAL_IS_ERROR(status)) 00212 ReturnStatus(status, INDEX_FSAL_lookup); 00213 00214 /* chown the symlink to the current user/group */ 00215 00216 TakeTokenFSCall(); 00217 rc = lchown(fsalpath.path, p_context->credential.user, 00218 setgid_bit ? -1 : p_context->credential.group); 00219 errsv = errno; 00220 ReleaseTokenFSCall(); 00221 00222 if(rc) 00223 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_symlink); 00224 00225 /* get attributes if asked */ 00226 00227 if(p_link_attributes) 00228 { 00229 00230 status = LUSTREFSAL_getattrs(p_link_handle, p_context, p_link_attributes); 00231 00232 /* On error, we set a flag in the returned attributes */ 00233 00234 if(FSAL_IS_ERROR(status)) 00235 { 00236 FSAL_CLEAR_MASK(p_link_attributes->asked_attributes); 00237 FSAL_SET_MASK(p_link_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00238 } 00239 00240 } 00241 00242 /* OK */ 00243 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_symlink); 00244 }