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 00059 fsal_status_t FUSEFSAL_lookup(fsal_handle_t * parent_handle, /* IN */ 00060 fsal_name_t * p_filename, /* IN */ 00061 fsal_op_context_t * p_context, /* IN */ 00062 fsal_handle_t * obj_handle, /* OUT */ 00063 fsal_attrib_list_t * object_attributes /* [ IN/OUT ] */ 00064 ) 00065 { 00066 00067 int rc; 00068 struct stat stbuff; 00069 fusefsal_handle_t * object_handle = (fusefsal_handle_t *)obj_handle; 00070 fusefsal_handle_t * parent_directory_handle = (fusefsal_handle_t *)parent_handle; 00071 00072 /* sanity checks 00073 * note : object_attributes is optionnal 00074 * parent_directory_handle may be null for getting FS root. 00075 */ 00076 if(!object_handle || !p_context) 00077 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup); 00078 00079 /* no getattr => no lookup !! */ 00080 if(!p_fs_ops->getattr) 00081 Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_lookup); 00082 00083 /* set current FS context */ 00084 fsal_set_thread_context(p_context); 00085 00086 /* retrieves root handle */ 00087 00088 if(!parent_directory_handle) 00089 { 00090 LogFullDebug(COMPONENT_FSAL, "lookup: root handle"); 00091 00092 /* check that p_filename is NULL, 00093 * else, parent_directory_handle should not 00094 * be NULL. 00095 */ 00096 if(p_filename != NULL) 00097 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup); 00098 00099 /* get root handle */ 00100 TakeTokenFSCall(); 00101 rc = p_fs_ops->getattr("/", &stbuff); 00102 ReleaseTokenFSCall(); 00103 00104 /* error getting root ?! => EIO */ 00105 if(rc) 00106 Return(ERR_FSAL_IO, rc, INDEX_FSAL_lookup); 00107 00108 if(stbuff.st_ino == 0) 00109 { 00110 /* filesystem does not provide inodes ! */ 00111 LogDebug(COMPONENT_FSAL, 00112 "WARNING in lookup: filesystem does not provide inode numbers"); 00113 /* root will have inode nbr 1 */ 00114 stbuff.st_ino = 1; 00115 } 00116 00117 /* fill root handle */ 00118 object_handle->data.inode = stbuff.st_ino; 00119 object_handle->data.device = stbuff.st_dev; 00120 00121 rc = NamespaceGetGen(stbuff.st_ino, stbuff.st_dev, &object_handle->data.validator); 00122 00123 /* root not in namespace ?! => EIO */ 00124 if(rc) 00125 Return(ERR_FSAL_IO, rc, INDEX_FSAL_lookup); 00126 00127 /* set root attributes, if asked */ 00128 00129 if(object_attributes) 00130 { 00131 fsal_status_t status = posix2fsal_attributes(&stbuff, object_attributes); 00132 00133 if(FSAL_IS_ERROR(status)) 00134 { 00135 FSAL_CLEAR_MASK(object_attributes->asked_attributes); 00136 FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00137 } 00138 } 00139 00140 } 00141 else /* this is a real lookup(parent, name) */ 00142 { 00143 char parent_path[FSAL_MAX_PATH_LEN]; 00144 char child_path[FSAL_MAX_PATH_LEN]; 00145 00146 /* the filename should not be null */ 00147 if(p_filename == NULL) 00148 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup); 00149 00150 /* get directory path */ 00151 rc = NamespacePath(parent_directory_handle->data.inode, 00152 parent_directory_handle->data.device, 00153 parent_directory_handle->data.validator, parent_path); 00154 if(rc) 00155 Return(ERR_FSAL_STALE, rc, INDEX_FSAL_lookup); 00156 00157 LogFullDebug(COMPONENT_FSAL, "lookup: parent path='%s'", parent_path); 00158 00159 /* TODO: check the parent type */ 00160 00161 /* case of '.' and '..' */ 00162 00163 if(!strcmp(p_filename->name, ".")) 00164 { 00165 LogFullDebug(COMPONENT_FSAL, "lookup on '.'"); 00166 strcpy(child_path, parent_path); 00167 } 00168 else if(!strcmp(p_filename->name, "..")) 00169 { 00170 LogFullDebug(COMPONENT_FSAL, "lookup on '..'"); 00171 00172 /* removing last '/<name>' if path != '/' */ 00173 if(!strcmp(parent_path, "/")) 00174 { 00175 strcpy(child_path, parent_path); 00176 } 00177 else 00178 { 00179 char *p_char; 00180 00181 strcpy(child_path, parent_path); 00182 p_char = strrchr(child_path, '/'); 00183 00184 /* if path is '/<name>', don't remove the first '/' */ 00185 if(p_char == child_path) 00186 *(p_char + 1) = '\0'; 00187 else if(p_char) 00188 *p_char = '\0'; 00189 } 00190 } 00191 else 00192 { 00193 LogFullDebug(COMPONENT_FSAL, "lookup on '%s/%s'", parent_path, p_filename->name); 00194 FSAL_internal_append_path(child_path, parent_path, p_filename->name); 00195 } 00196 00197 TakeTokenFSCall(); 00198 rc = p_fs_ops->getattr(child_path, &stbuff); 00199 ReleaseTokenFSCall(); 00200 00201 LogFullDebug(COMPONENT_FSAL, "%s: gettattr status=%d", child_path, rc); 00202 00203 if(rc) 00204 Return(fuse2fsal_error(rc, FALSE), rc, INDEX_FSAL_lookup); 00205 00206 /* no '.' nor '..' in namespace */ 00207 if(strcmp(p_filename->name, ".") && strcmp(p_filename->name, "..")) 00208 { 00209 if(stbuff.st_ino == 0) 00210 { 00211 /* filesystem does not provide inodes ! */ 00212 LogDebug(COMPONENT_FSAL, 00213 "WARNING in lookup: filesystem does not provide inode numbers !!!"); 00214 00215 if(!parent_directory_handle || !p_filename || !p_filename->name) 00216 { 00217 LogCrit(COMPONENT_FSAL, 00218 "CRITICAL: Segfault avoided !!!!! %p %p %p", 00219 parent_directory_handle, p_filename, 00220 p_filename ? p_filename->name : NULL); 00221 } 00222 else 00223 { 00224 /* create a fake handle for child = hash of its parent and its name */ 00225 stbuff.st_ino = 00226 hash_peer(parent_directory_handle->data.inode, p_filename->name); 00227 LogFullDebug(COMPONENT_FSAL, "handle for %u, %s = %u", 00228 (int)parent_directory_handle->data.inode, p_filename->name, 00229 (int)stbuff.st_ino); 00230 } 00231 } 00232 00233 object_handle->data.validator = stbuff.st_ctime; 00234 00235 /* add handle to namespace */ 00236 NamespaceAdd(parent_directory_handle->data.inode, 00237 parent_directory_handle->data.device, 00238 parent_directory_handle->data.validator, 00239 p_filename->name, 00240 stbuff.st_ino, stbuff.st_dev, &object_handle->data.validator); 00241 } 00242 else 00243 { 00244 rc = NamespaceGetGen(stbuff.st_ino, stbuff.st_dev, &object_handle->data.validator); 00245 LogEvent(COMPONENT_FSAL, 00246 ". or .. is stale ??? ino=%d, dev=%d\n, validator=%d", 00247 (int)stbuff.st_ino, (int)stbuff.st_dev, 00248 (int)object_handle->data.validator); 00249 if(rc) 00250 Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_lookup); 00251 } 00252 00253 /* output handle */ 00254 object_handle->data.inode = stbuff.st_ino; 00255 object_handle->data.device = stbuff.st_dev; 00256 00257 if(object_attributes) 00258 { 00259 fsal_status_t status = posix2fsal_attributes(&stbuff, object_attributes); 00260 00261 if(FSAL_IS_ERROR(status)) 00262 { 00263 FSAL_CLEAR_MASK(object_attributes->asked_attributes); 00264 FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00265 } 00266 } 00267 00268 } 00269 00270 /* lookup complete ! */ 00271 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_lookup); 00272 00273 } 00274 00302 fsal_status_t FUSEFSAL_lookupJunction(fsal_handle_t * p_junction_handle, /* IN */ 00303 fsal_op_context_t * p_context, /* IN */ 00304 fsal_handle_t * p_fsoot_handle, /* OUT */ 00305 fsal_attrib_list_t * p_fsroot_attributes /* [ IN/OUT ] */ 00306 ) 00307 { 00308 00309 /* Not supported for FUSE FSAL */ 00310 Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_lookupJunction); 00311 00312 } 00313 00348 fsal_status_t FUSEFSAL_lookupPath(fsal_path_t * p_path, /* IN */ 00349 fsal_op_context_t * p_context, /* IN */ 00350 fsal_handle_t * object_handle, /* OUT */ 00351 fsal_attrib_list_t * object_attributes /* [ IN/OUT ] */ 00352 ) 00353 { 00354 00355 fsal_name_t obj_name = FSAL_NAME_INITIALIZER; /* empty string */ 00356 char *ptr_str; 00357 fsal_handle_t out_hdl; 00358 fsal_status_t status; 00359 int b_is_last = FALSE; /* is it the last lookup ? */ 00360 00361 /* sanity checks 00362 * note : object_attributes is optionnal. 00363 */ 00364 00365 if(!object_handle || !p_context || !p_path) 00366 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookupPath); 00367 00368 /* test whether the path begins with a slash */ 00369 00370 if(p_path->path[0] != '/') 00371 Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_lookupPath); 00372 00373 /* the pointer now points on the next name in the path, 00374 * skipping slashes. 00375 */ 00376 00377 ptr_str = p_path->path + 1; 00378 while(ptr_str[0] == '/') 00379 ptr_str++; 00380 00381 /* is the next name empty ? */ 00382 00383 if(ptr_str[0] == '\0') 00384 b_is_last = TRUE; 00385 00386 /* retrieves root directory */ 00387 00388 status = FUSEFSAL_lookup(NULL, /* looking up for root */ 00389 NULL, /* empty string to get root handle */ 00390 p_context, /* user's credentials */ 00391 &out_hdl, /* output root handle */ 00392 /* retrieves attributes if this is the last lookup : */ 00393 (b_is_last ? object_attributes : NULL)); 00394 00395 if(FSAL_IS_ERROR(status)) 00396 Return(status.major, status.minor, INDEX_FSAL_lookupPath); 00397 00398 /* exits if this was the last lookup */ 00399 00400 if(b_is_last) 00401 { 00402 (*object_handle) = out_hdl; 00403 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_lookupPath); 00404 } 00405 00406 /* proceed a step by step lookup */ 00407 00408 while(ptr_str[0]) 00409 { 00410 00411 fsal_handle_t in_hdl; 00412 char *dest_ptr; 00413 00414 /* preparing lookup */ 00415 00416 in_hdl = out_hdl; 00417 00418 /* compute next name */ 00419 obj_name.len = 0; 00420 dest_ptr = obj_name.name; 00421 while(ptr_str[0] != '\0' && ptr_str[0] != '/') 00422 { 00423 dest_ptr[0] = ptr_str[0]; 00424 dest_ptr++; 00425 ptr_str++; 00426 obj_name.len++; 00427 } 00428 /* final null char */ 00429 dest_ptr[0] = '\0'; 00430 00431 /* skip multiple slashes */ 00432 while(ptr_str[0] == '/') 00433 ptr_str++; 00434 00435 /* is the next name empty ? */ 00436 if(ptr_str[0] == '\0') 00437 b_is_last = TRUE; 00438 00439 /*call to FSAL_lookup */ 00440 status = FUSEFSAL_lookup(&in_hdl, /* parent directory handle */ 00441 &obj_name, /* object name */ 00442 p_context, /* user's credentials */ 00443 &out_hdl, /* output root handle */ 00444 /* retrieves attributes if this is the last lookup : */ 00445 (b_is_last ? object_attributes : NULL)); 00446 00447 if(FSAL_IS_ERROR(status)) 00448 Return(status.major, status.minor, INDEX_FSAL_lookupPath); 00449 00450 /* ptr_str is ok, we are ready for next loop */ 00451 } 00452 00453 (*object_handle) = out_hdl; 00454 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_lookupPath); 00455 00456 }