nfs-ganesha 1.4

fsal_lookup.c

Go to the documentation of this file.
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 }