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 "fsal_common.h" 00021 #include "namespace.h" 00022 #include <string.h> 00023 00052 fsal_status_t FUSEFSAL_readlink(fsal_handle_t * link_hdl, /* IN */ 00053 fsal_op_context_t * p_context, /* IN */ 00054 fsal_path_t * p_link_content, /* OUT */ 00055 fsal_attrib_list_t * link_attributes /* [ IN/OUT ] */ 00056 ) 00057 { 00058 fusefsal_handle_t * linkhandle = (fusefsal_handle_t *)link_hdl; 00059 int rc; 00060 fsal_status_t st; 00061 char link_content_out[FSAL_MAX_PATH_LEN]; 00062 char object_path[FSAL_MAX_PATH_LEN]; 00063 00064 /* sanity checks. 00065 * note : link_attributes is optional. 00066 */ 00067 if(!linkhandle || !p_context || !p_link_content) 00068 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readlink); 00069 00070 /* get the full path for this inode */ 00071 rc = NamespacePath(linkhandle->data.inode, linkhandle->data.device, linkhandle->data.validator, 00072 object_path); 00073 if(rc) 00074 Return(ERR_FSAL_STALE, rc, INDEX_FSAL_readlink); 00075 00076 /* set context for the next operation, so it can be retrieved by FS thread */ 00077 fsal_set_thread_context(p_context); 00078 00079 if(p_fs_ops->readlink) 00080 { 00081 TakeTokenFSCall(); 00082 00083 rc = p_fs_ops->readlink(object_path, link_content_out, FSAL_MAX_PATH_LEN); 00084 00085 ReleaseTokenFSCall(); 00086 00087 if(rc) 00088 Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_readlink); 00089 00090 } 00091 else 00092 /* return empty link */ 00093 link_content_out[0] = '\0'; 00094 00095 /* convert string to fsal_path_t */ 00096 00097 st = FSAL_str2path(link_content_out, FSAL_MAX_PATH_LEN, p_link_content); 00098 00099 if(FSAL_IS_ERROR(st)) 00100 Return(st.major, st.minor, INDEX_FSAL_readlink); 00101 00102 /* retrieves object attributes, if asked */ 00103 00104 if(link_attributes) 00105 { 00106 00107 fsal_status_t status; 00108 00109 status = FUSEFSAL_getattrs(link_hdl, p_context, link_attributes); 00110 00111 /* On error, we set a flag in the returned attributes */ 00112 00113 if(FSAL_IS_ERROR(status)) 00114 { 00115 FSAL_CLEAR_MASK(link_attributes->asked_attributes); 00116 FSAL_SET_MASK(link_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00117 } 00118 00119 } 00120 00121 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readlink); 00122 00123 } 00124 00159 fsal_status_t FUSEFSAL_symlink(fsal_handle_t * parent, /* IN */ 00160 fsal_name_t * p_linkname, /* IN */ 00161 fsal_path_t * p_linkcontent, /* IN */ 00162 fsal_op_context_t * p_context, /* IN */ 00163 fsal_accessmode_t accessmode, /* IN (ignored) */ 00164 fsal_handle_t * link_hdl, /* OUT */ 00165 fsal_attrib_list_t * link_attributes /* [ IN/OUT ] */ 00166 ) 00167 { 00168 00169 int rc; 00170 char parent_path[FSAL_MAX_PATH_LEN]; 00171 char child_path[FSAL_MAX_PATH_LEN]; 00172 struct stat buffstat; 00173 fusefsal_handle_t * parent_directory_handle = (fusefsal_handle_t *)parent; 00174 fusefsal_handle_t * link_handle = (fusefsal_handle_t *)link_hdl; 00175 00176 /* sanity checks. 00177 * note : link_attributes is optional. 00178 */ 00179 if(!parent_directory_handle || 00180 !p_context || !link_handle || !p_linkname || !p_linkcontent) 00181 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_symlink); 00182 00183 /* Tests if symlinking is allowed by configuration and filesystem. */ 00184 00185 if(!global_fs_info.symlink_support || !p_fs_ops->symlink) 00186 Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_symlink); 00187 00188 /* get the full path for parent inode */ 00189 rc = NamespacePath(parent_directory_handle->data.inode, 00190 parent_directory_handle->data.device, 00191 parent_directory_handle->data.validator, parent_path); 00192 if(rc) 00193 Return(ERR_FSAL_STALE, rc, INDEX_FSAL_symlink); 00194 00195 /* append child name to parent path */ 00196 FSAL_internal_append_path(child_path, parent_path, p_linkname->name); 00197 00198 /* set context for the next operation, so it can be retrieved by FS thread */ 00199 fsal_set_thread_context(p_context); 00200 00201 TakeTokenFSCall(); 00202 00203 rc = p_fs_ops->symlink(p_linkcontent->path, child_path); 00204 00205 ReleaseTokenFSCall(); 00206 00207 if(rc) 00208 Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_symlink); 00209 00210 /* set the owner for the newly created entry */ 00211 00212 if(p_fs_ops->chown) 00213 { 00214 TakeTokenFSCall(); 00215 rc = p_fs_ops->chown(child_path, p_context->credential.user, 00216 p_context->credential.group); 00217 ReleaseTokenFSCall(); 00218 00219 LogFullDebug(COMPONENT_FSAL, "chown: status = %d", rc); 00220 00221 if(rc) 00222 Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_symlink); 00223 } 00224 00225 /* get info about this symlink */ 00226 00227 TakeTokenFSCall(); 00228 rc = p_fs_ops->getattr(child_path, &buffstat); 00229 ReleaseTokenFSCall(); 00230 00231 if(rc) 00232 Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_symlink); 00233 00234 link_handle->data.validator = buffstat.st_ctime; 00235 00236 /* add handle to namespace */ 00237 NamespaceAdd(parent_directory_handle->data.inode, 00238 parent_directory_handle->data.device, 00239 parent_directory_handle->data.validator, 00240 p_linkname->name, 00241 buffstat.st_ino, buffstat.st_dev, &link_handle->data.validator); 00242 00243 /* set output handle */ 00244 link_handle->data.inode = buffstat.st_ino; 00245 link_handle->data.device = buffstat.st_dev; 00246 00247 if(link_attributes) 00248 { 00249 fsal_status_t status = posix2fsal_attributes(&buffstat, link_attributes); 00250 00251 if(FSAL_IS_ERROR(status)) 00252 { 00253 FSAL_CLEAR_MASK(link_attributes->asked_attributes); 00254 FSAL_SET_MASK(link_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00255 } 00256 00257 } 00258 00259 /* OK */ 00260 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_symlink); 00261 }