nfs-ganesha 1.4
|
00001 /* 00002 * vim:expandtab:shiftwidth=8:tabstop=8: 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 00045 fsal_status_t POSIXFSAL_readlink(fsal_handle_t * linkhandle, /* IN */ 00046 fsal_op_context_t * context, /* IN */ 00047 fsal_path_t * p_link_content, /* OUT */ 00048 fsal_attrib_list_t * p_link_attributes /* [ IN/OUT ] */ 00049 ) 00050 { 00051 posixfsal_handle_t * p_linkhandle = (posixfsal_handle_t *) linkhandle; 00052 posixfsal_op_context_t * p_context = (posixfsal_op_context_t *) context; 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_getPathFromHandle(p_context, p_linkhandle, 0, &fsalpath, NULL); 00065 if(FSAL_IS_ERROR(status)) 00066 Return(status.major, status.minor, 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 00083 status = FSAL_str2path(link_content_out, FSAL_MAX_PATH_LEN, p_link_content); 00084 00085 if(FSAL_IS_ERROR(status)) 00086 Return(status.major, status.minor, INDEX_FSAL_readlink); 00087 00088 /* retrieves object attributes, if asked */ 00089 00090 if(p_link_attributes) 00091 { 00092 00093 status = POSIXFSAL_getattrs(p_linkhandle, p_context, p_link_attributes); 00094 00095 /* On error, we set a flag in the returned attributes */ 00096 00097 if(FSAL_IS_ERROR(status)) 00098 { 00099 FSAL_CLEAR_MASK(p_link_attributes->asked_attributes); 00100 FSAL_SET_MASK(p_link_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00101 } 00102 00103 } 00104 00105 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readlink); 00106 00107 } 00108 00138 fsal_status_t POSIXFSAL_symlink(fsal_handle_t * parent_directory_handle, /* IN */ 00139 fsal_name_t * p_linkname, /* IN */ 00140 fsal_path_t * p_linkcontent, /* IN */ 00141 fsal_op_context_t * context, /* IN */ 00142 fsal_accessmode_t accessmode, /* IN (ignored) */ 00143 fsal_handle_t * link_handle, /* OUT */ 00144 fsal_attrib_list_t * p_link_attributes /* [ IN/OUT ] */ 00145 ) 00146 { 00147 posixfsal_handle_t * p_parent_directory_handle 00148 = (posixfsal_handle_t *) parent_directory_handle; 00149 posixfsal_op_context_t * p_context = (posixfsal_op_context_t *) context; 00150 posixfsal_handle_t * p_link_handle = (posixfsal_handle_t *) link_handle; 00151 int rc, errsv; 00152 fsal_status_t status; 00153 fsal_path_t fsalpath; 00154 fsal_posixdb_fileinfo_t infofs; 00155 struct stat buffstat; 00156 00157 /* sanity checks. 00158 * note : link_attributes is optional. 00159 */ 00160 if(!p_parent_directory_handle || 00161 !p_context || !p_link_handle || !p_linkname || !p_linkcontent) 00162 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_symlink); 00163 00164 /* Tests if symlinking is allowed by configuration. */ 00165 00166 if(!global_fs_info.symlink_support) 00167 Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_symlink); 00168 00169 /* build the new path and check the permissions on the parent directory */ 00170 status = 00171 fsal_internal_getPathFromHandle(p_context, p_parent_directory_handle, 1, &fsalpath, 00172 &buffstat); 00173 if(FSAL_IS_ERROR(status)) 00174 Return(status.major, status.minor, INDEX_FSAL_symlink); 00175 00176 status = fsal_internal_testAccess(p_context, FSAL_W_OK, &buffstat, NULL); 00177 if(FSAL_IS_ERROR(status)) 00178 Return(status.major, status.minor, INDEX_FSAL_symlink); 00179 00180 status = fsal_internal_appendFSALNameToFSALPath(&fsalpath, p_linkname); 00181 if(FSAL_IS_ERROR(status)) 00182 Return(status.major, status.minor, INDEX_FSAL_symlink); 00183 00184 /* create the symlink on the filesystem. */ 00185 00186 TakeTokenFSCall(); 00187 rc = symlink(p_linkcontent->path, fsalpath.path); 00188 errsv = errno; 00189 ReleaseTokenFSCall(); 00190 00191 if(rc) 00192 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_symlink); 00193 00194 /* stat the file & add it to the database */ 00195 TakeTokenFSCall(); 00196 rc = lstat(fsalpath.path, &buffstat); 00197 errsv = errno; 00198 ReleaseTokenFSCall(); 00199 00200 if(rc) 00201 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_symlink); 00202 00203 if(FSAL_IS_ERROR(status = fsal_internal_posix2posixdb_fileinfo(&buffstat, &infofs))) 00204 Return(status.major, status.minor, INDEX_FSAL_symlink); 00205 if(FSAL_IS_ERROR 00206 (status = 00207 fsal_internal_posixdb_add_entry(p_context->p_conn, p_linkname, &infofs, 00208 p_parent_directory_handle, p_link_handle))) 00209 Return(status.major, status.minor, INDEX_FSAL_symlink); 00210 00211 /* chown the symlink to the current user */ 00212 00213 TakeTokenFSCall(); 00214 rc = lchown(fsalpath.path, p_context->credential.user, -1); 00215 errsv = errno; 00216 ReleaseTokenFSCall(); 00217 00218 if(rc) 00219 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_symlink); 00220 00221 /* get attributes if asked */ 00222 00223 if(p_link_attributes) 00224 { 00225 00226 status = posix2fsal_attributes(&buffstat, p_link_attributes); 00227 00228 if(FSAL_IS_ERROR(status)) 00229 { 00230 FSAL_CLEAR_MASK(p_link_attributes->asked_attributes); 00231 FSAL_SET_MASK(p_link_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00232 } 00233 00234 } 00235 00236 /* OK */ 00237 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_symlink); 00238 }