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 #ifdef _SOLARIS
00018 #include "solaris_port.h"
00019 #endif                          /* _SOLARIS */
00020 
00021 #include <string.h>
00022 #ifdef _USE_GSSRPC
00023 #include <gssrpc/rpc.h>
00024 #include <gssrpc/xdr.h>
00025 #else
00026 #include <rpc/rpc.h>
00027 #include <rpc/xdr.h>
00028 #endif
00029 #include "nfs4.h"
00030 
00031 #include "fsal_internal.h"
00032 #include "fsal_convert.h"
00033 #include "fsal_common.h"
00034 
00035 #include "nfs_proto_functions.h"
00036 #include "fsal_nfsv4_macros.h"
00037 
00073 extern struct timeval timeout;
00074 
00075 fsal_status_t PROXYFSAL_lookup(fsal_handle_t * parent_directory_handle,    /* IN */
00076                                fsal_name_t * p_filename,        /* IN */
00077                                fsal_op_context_t * context,      /* IN */
00078                                fsal_handle_t * object_handle,      /* OUT */
00079                                fsal_attrib_list_t * object_attributes   /* [ IN/OUT ] */
00080     )
00081 {
00082 
00083   int rc;
00084   COMPOUND4args argnfs4;
00085   COMPOUND4res resnfs4;
00086   nfs_fh4 nfs4fh;
00087   bitmap4 bitmap;
00088   uint32_t bitmap_val[2];
00089   component4 name;
00090   char nameval[MAXNAMLEN];
00091   fsal_attrib_list_t attributes;
00092   unsigned int index_getfh = 0;
00093   unsigned int index_getattr = 0;
00094   proxyfsal_op_context_t * p_context = (proxyfsal_op_context_t *)context;
00095 
00096 #define FSAL_LOOKUP_NB_OP_ALLOC 4
00097   nfs_argop4 argoparray[FSAL_LOOKUP_NB_OP_ALLOC];
00098   nfs_resop4 resoparray[FSAL_LOOKUP_NB_OP_ALLOC];
00099   uint32_t bitmap_res[2];
00100 
00101   fsal_proxy_internal_fattr_t fattr_internal;
00102   char padfilehandle[FSAL_PROXY_FILEHANDLE_MAX_LEN];
00103 
00104   struct timeval timeout = TIMEOUTRPC;
00105   /* sanity checks
00106    * note : object_attributes is optionnal
00107    *        parent_directory_handle may be null for getting FS root.
00108    */
00109   if(!object_handle || !p_context)
00110     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup);
00111 
00112   /* Setup results structures */
00113   argnfs4.argarray.argarray_val = argoparray;
00114   resnfs4.resarray.resarray_val = resoparray;
00115   fsal_internal_proxy_setup_fattr(&fattr_internal);
00116   argnfs4.minorversion = 0;
00117   argnfs4.argarray.argarray_len = 0;
00118 
00119   /* >> retrieve root handle filehandle here << */
00120   bitmap.bitmap4_val = bitmap_val;
00121   bitmap.bitmap4_len = 2;
00122   fsal_internal_proxy_create_fattr_bitmap(&bitmap);
00123 
00124   if(!parent_directory_handle)
00125     {
00126 
00127       /* check that p_filename is NULL,
00128        * else, parent_directory_handle should not
00129        * be NULL.
00130        */
00131       if(p_filename != NULL)
00132         Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup);
00133 
00134       /* argnfs4.tag.utf8string_val = "GANESHA NFSv4 Proxy: Lookup Root" ; */
00135       argnfs4.tag.utf8string_val = NULL;
00136       argnfs4.tag.utf8string_len = 0;
00137 
00138 #define FSAL_LOOKUP_IDX_OP_PUTROOTFH      0
00139 #define FSAL_LOOKUP_IDX_OP_GETATTR_ROOT   1
00140 #define FSAL_LOOKUP_IDX_OP_GETFH_ROOT     2
00141       COMPOUNDV4_ARG_ADD_OP_PUTROOTFH(argnfs4);
00142       COMPOUNDV4_ARG_ADD_OP_GETATTR(argnfs4, bitmap);
00143       COMPOUNDV4_ARG_ADD_OP_GETFH(argnfs4);
00144 
00145       index_getattr = FSAL_LOOKUP_IDX_OP_GETATTR_ROOT;
00146       index_getfh = FSAL_LOOKUP_IDX_OP_GETFH_ROOT;
00147 
00148       resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETATTR_ROOT].nfs_resop4_u.
00149           opgetattr.GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val = bitmap_res;
00150       resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETATTR_ROOT].nfs_resop4_u.
00151           opgetattr.GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2;
00152 
00153       resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETATTR_ROOT].nfs_resop4_u.
00154           opgetattr.GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_val =
00155           (char *)&fattr_internal;
00156       resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETATTR_ROOT].nfs_resop4_u.
00157           opgetattr.GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len =
00158           sizeof(fattr_internal);
00159 
00160       resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETFH_ROOT].nfs_resop4_u.opgetfh.
00161           GETFH4res_u.resok4.object.nfs_fh4_val = (char *)padfilehandle;
00162       resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETFH_ROOT].nfs_resop4_u.opgetfh.
00163           GETFH4res_u.resok4.object.nfs_fh4_len = FSAL_PROXY_FILEHANDLE_MAX_LEN;
00164     }
00165   else                          /* this is a real lookup(parent, name)  */
00166     {
00167       PRINT_HANDLE("PROXYFSAL_lookup parent", parent_directory_handle);
00168 
00169       /* the filename should not be null */
00170       if(p_filename == NULL)
00171         Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup);
00172 
00173       /* >> Be careful about junction crossing, symlinks, hardlinks,...
00174        * You may check the parent type if it's sored into the handle <<
00175        */
00176 
00177       switch (((proxyfsal_handle_t *)parent_directory_handle)->data.object_type_reminder)
00178         {
00179         case FSAL_TYPE_DIR:
00180           /* OK */
00181           break;
00182 
00183         case FSAL_TYPE_JUNCTION:
00184           /* This is a junction */
00185           Return(ERR_FSAL_XDEV, 0, INDEX_FSAL_lookup);
00186 
00187         case FSAL_TYPE_FILE:
00188         case FSAL_TYPE_LNK:
00189         case FSAL_TYPE_XATTR:
00190           /* not a directory */
00191           Return(ERR_FSAL_NOTDIR, 0, INDEX_FSAL_lookup);
00192 
00193         default:
00194           Return(ERR_FSAL_SERVERFAULT, 0, INDEX_FSAL_lookup);
00195         }
00196 
00197       /* >> Call your filesystem lookup function here << */
00198       if(fsal_internal_proxy_extract_fh(&nfs4fh, parent_directory_handle) == FALSE)
00199         Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup);
00200 
00201       memset((char *)&name, 0, sizeof(component4));
00202       name.utf8string_val = nameval;
00203       name.utf8string_len = sizeof(nameval);
00204       if(fsal_internal_proxy_fsal_name_2_utf8(p_filename, &name) == FALSE)
00205         Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup);
00206 
00207       if(!FSAL_namecmp(p_filename, (fsal_name_t *) & FSAL_DOT))
00208         {
00209           /* argnfs4.tag.utf8string_val = "GANESHA NFSv4 Proxy: Lookup current" ; */
00210           argnfs4.tag.utf8string_val = NULL;
00211           argnfs4.tag.utf8string_len = 0;
00212 
00213 #define FSAL_LOOKUP_IDX_OP_DOT_PUTFH     0
00214 #define FSAL_LOOKUP_IDX_OP_DOT_GETATTR   1
00215 #define FSAL_LOOKUP_IDX_OP_DOT_GETFH     2
00216           COMPOUNDV4_ARG_ADD_OP_PUTFH(argnfs4, nfs4fh);
00217           COMPOUNDV4_ARG_ADD_OP_GETATTR(argnfs4, bitmap);
00218           COMPOUNDV4_ARG_ADD_OP_GETFH(argnfs4);
00219 
00220           index_getattr = FSAL_LOOKUP_IDX_OP_DOT_GETATTR;
00221           index_getfh = FSAL_LOOKUP_IDX_OP_DOT_GETFH;
00222 
00223           resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_GETATTR].nfs_resop4_u.
00224               opgetattr.GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val =
00225               bitmap_res;
00226           resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_GETATTR].nfs_resop4_u.
00227               opgetattr.GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2;
00228 
00229           resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_GETATTR].nfs_resop4_u.
00230               opgetattr.GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_val =
00231               (char *)&fattr_internal;
00232           resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_GETATTR].nfs_resop4_u.
00233               opgetattr.GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len =
00234               sizeof(fattr_internal);
00235 
00236           resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_GETFH].nfs_resop4_u.
00237               opgetfh.GETFH4res_u.resok4.object.nfs_fh4_val = (char *)padfilehandle;
00238           resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_GETFH].nfs_resop4_u.
00239               opgetfh.GETFH4res_u.resok4.object.nfs_fh4_len =
00240               FSAL_PROXY_FILEHANDLE_MAX_LEN;
00241         }
00242       else if(!FSAL_namecmp(p_filename, (fsal_name_t *) & FSAL_DOT_DOT))
00243         {
00244           /* argnfs4.tag.utf8string_val = "GANESHA NFSv4 Proxy: Lookup parent" ; */
00245           argnfs4.tag.utf8string_val = NULL;
00246           argnfs4.tag.utf8string_len = 0;
00247 
00248 #define FSAL_LOOKUP_IDX_OP_DOT_DOT_PUTFH     0
00249 #define FSAL_LOOKUP_IDX_OP_DOT_DOT_LOOKUPP   1
00250 #define FSAL_LOOKUP_IDX_OP_DOT_DOT_GETATTR   2
00251 #define FSAL_LOOKUP_IDX_OP_DOT_DOT_GETFH     3
00252           COMPOUNDV4_ARG_ADD_OP_PUTFH(argnfs4, nfs4fh);
00253           COMPOUNDV4_ARG_ADD_OP_LOOKUPP(argnfs4);
00254           COMPOUNDV4_ARG_ADD_OP_GETATTR(argnfs4, bitmap);
00255           COMPOUNDV4_ARG_ADD_OP_GETFH(argnfs4);
00256 
00257           index_getattr = FSAL_LOOKUP_IDX_OP_DOT_DOT_GETATTR;
00258           index_getfh = FSAL_LOOKUP_IDX_OP_DOT_DOT_GETFH;
00259 
00260           resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_DOT_GETATTR].nfs_resop4_u.
00261               opgetattr.GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val =
00262               bitmap_res;
00263           resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_DOT_GETATTR].nfs_resop4_u.
00264               opgetattr.GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2;
00265 
00266           resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_DOT_GETATTR].nfs_resop4_u.
00267               opgetattr.GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_val =
00268               (char *)&fattr_internal;
00269           resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_DOT_GETATTR].nfs_resop4_u.
00270               opgetattr.GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len =
00271               sizeof(fattr_internal);
00272 
00273           resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_DOT_GETFH].nfs_resop4_u.
00274               opgetfh.GETFH4res_u.resok4.object.nfs_fh4_val = (char *)padfilehandle;
00275           resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_DOT_GETFH].nfs_resop4_u.
00276               opgetfh.GETFH4res_u.resok4.object.nfs_fh4_len =
00277               FSAL_PROXY_FILEHANDLE_MAX_LEN;
00278         }
00279       else
00280         {
00281           /* argnfs4.tag.utf8string_val = "GANESHA NFSv4 Proxy: Lookup name" ; */
00282           argnfs4.tag.utf8string_val = NULL;
00283           argnfs4.tag.utf8string_len = 0;
00284 
00285 #define FSAL_LOOKUP_IDX_OP_PUTFH     0
00286 #define FSAL_LOOKUP_IDX_OP_LOOKUP    1
00287 #define FSAL_LOOKUP_IDX_OP_GETATTR   2
00288 #define FSAL_LOOKUP_IDX_OP_GETFH     3
00289           COMPOUNDV4_ARG_ADD_OP_PUTFH(argnfs4, nfs4fh);
00290           COMPOUNDV4_ARG_ADD_OP_LOOKUP(argnfs4, name);
00291           COMPOUNDV4_ARG_ADD_OP_GETATTR(argnfs4, bitmap);
00292           COMPOUNDV4_ARG_ADD_OP_GETFH(argnfs4);
00293 
00294           index_getattr = FSAL_LOOKUP_IDX_OP_GETATTR;
00295           index_getfh = FSAL_LOOKUP_IDX_OP_GETFH;
00296 
00297           resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETATTR].nfs_resop4_u.
00298               opgetattr.GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val =
00299               bitmap_res;
00300           resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETATTR].nfs_resop4_u.
00301               opgetattr.GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2;
00302 
00303           resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETATTR].nfs_resop4_u.
00304               opgetattr.GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_val =
00305               (char *)&fattr_internal;
00306           resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETATTR].nfs_resop4_u.
00307               opgetattr.GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len =
00308               sizeof(fattr_internal);
00309 
00310           resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETFH].nfs_resop4_u.opgetfh.
00311               GETFH4res_u.resok4.object.nfs_fh4_val = (char *)padfilehandle;
00312           resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETFH].nfs_resop4_u.opgetfh.
00313               GETFH4res_u.resok4.object.nfs_fh4_len = FSAL_PROXY_FILEHANDLE_MAX_LEN;
00314         }
00315     }
00316 
00317   TakeTokenFSCall();
00318 
00319   /* Call the NFSv4 function */
00320   COMPOUNDV4_EXECUTE(p_context, argnfs4, resnfs4, rc);
00321   if(rc != RPC_SUCCESS)
00322     {
00323       ReleaseTokenFSCall();
00324 
00325       Return(ERR_FSAL_IO, rc, INDEX_FSAL_lookup);
00326     }
00327   ReleaseTokenFSCall();
00328 
00329   if(resnfs4.status != NFS4_OK)
00330     return fsal_internal_proxy_error_convert(resnfs4.status, INDEX_FSAL_lookup);
00331 
00332   /* Use NFSv4 service function to build the FSAL_attr */
00333   if(nfs4_Fattr_To_FSAL_attr(&attributes,
00334                              &resnfs4.resarray.resarray_val[index_getattr].nfs_resop4_u.
00335                              opgetattr.GETATTR4res_u.resok4.obj_attributes) != NFS4_OK)
00336     {
00337       FSAL_CLEAR_MASK(object_attributes->asked_attributes);
00338       FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00339 
00340       Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_lookup);
00341     }
00342 
00343   if(object_attributes)
00344     {
00345       memcpy(object_attributes, &attributes, sizeof(attributes));
00346     }
00347 
00348   /* Build the handle */
00349   if(fsal_internal_proxy_create_fh
00350      (&resnfs4.resarray.resarray_val[index_getfh].nfs_resop4_u.opgetfh.GETFH4res_u.
00351       resok4.object, attributes.type, attributes.fileid, object_handle) == FALSE)
00352     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup);
00353 
00354   PRINT_HANDLE("PROXYFSAL_lookup object found", object_handle);
00355 
00356   /* Return attributes if asked */
00357   if(object_attributes)
00358     {
00359       memcpy(object_attributes, &attributes, sizeof(attributes));
00360     }
00361 
00362   /* lookup complete ! */
00363   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_lookup);
00364 
00365 }
00366 
00394 fsal_status_t PROXYFSAL_lookupJunction(fsal_handle_t * p_junction_handle,  /* IN */
00395                                        fsal_op_context_t * p_context,      /* IN */
00396                                        fsal_handle_t * p_fsoot_handle,     /* OUT */
00397                                        fsal_attrib_list_t * p_fsroot_attributes /* [ IN/OUT ] */
00398     )
00399 {
00400   /* sanity checks
00401    * note : p_fsroot_attributes is optionnal
00402    */
00403   if(!p_junction_handle || !p_fsoot_handle || !p_context)
00404     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookupJunction);
00405 
00406   /* >> you can also check object type if it is in stored in the handle << */
00407 
00408   if(((proxyfsal_handle_t *)p_junction_handle)->data.object_type_reminder != FSAL_TYPE_JUNCTION)
00409     Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_lookupJunction);
00410 
00411   TakeTokenFSCall();
00412 
00413   /* >> traverse the junction here << */
00414 
00415   ReleaseTokenFSCall();
00416 
00417   /* >> convert the error code and return on error << */
00418 
00419   /* >> set output handle << */
00420 
00421   if(p_fsroot_attributes)
00422     {
00423 
00424       /* >> fill output attributes if asked << */
00425 
00426     }
00427 
00428   /* lookup complete ! */
00429   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_lookupJunction);
00430 }
00431 
00466 fsal_status_t PROXYFSAL_lookupPath(fsal_path_t * p_path,        /* IN */
00467                                    fsal_op_context_t * p_context,  /* IN */
00468                                    fsal_handle_t * object_handle,  /* OUT */
00469                                    fsal_attrib_list_t * object_attributes       /* [ IN/OUT ] */
00470     )
00471 {
00472   fsal_name_t obj_name = FSAL_NAME_INITIALIZER; /* empty string */
00473   char *ptr_str;
00474   proxyfsal_handle_t out_hdl;
00475   fsal_status_t status;
00476   int b_is_last = FALSE;        /* is it the last lookup ? */
00477 
00478 /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
00479  *  this function may be adapted to most FSALs
00480  *<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
00481 
00482   /* sanity checks
00483    * note : object_attributes is optionnal.
00484    */
00485 
00486   if(!object_handle || !p_context || !p_path)
00487     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookupPath);
00488 
00489   /* test whether the path begins with a slash */
00490 
00491   if(p_path->path[0] != '/')
00492     Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_lookupPath);
00493 
00494   /* the pointer now points on the next name in the path,
00495    * skipping slashes.
00496    */
00497 
00498   ptr_str = p_path->path + 1;
00499   while(ptr_str[0] == '/')
00500     ptr_str++;
00501 
00502   /* is the next name empty ? */
00503 
00504   if(ptr_str[0] == '\0')
00505     b_is_last = TRUE;
00506 
00507   /* retrieves root directory */
00508 
00509   status = PROXYFSAL_lookup(NULL,       /* looking up for root */
00510                             NULL,       /* empty string to get root handle */
00511                             p_context,  /* user's credentials */
00512                             (fsal_handle_t *) &out_hdl,   /* output root handle */
00513                             /* retrieves attributes if this is the last lookup : */
00514                             (b_is_last ? object_attributes : NULL));
00515 
00516   if(FSAL_IS_ERROR(status))
00517     Return(status.major, status.minor, INDEX_FSAL_lookupPath);
00518 
00519   /* exits if this was the last lookup */
00520 
00521   if(b_is_last)
00522     {
00523       (*(proxyfsal_handle_t *)object_handle) = out_hdl;
00524       Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_lookupPath);
00525     }
00526 
00527   /* proceed a step by step lookup */
00528 
00529   while(ptr_str[0])
00530     {
00531 
00532       proxyfsal_handle_t in_hdl;
00533       char *dest_ptr;
00534 
00535       /* preparing lookup */
00536 
00537       in_hdl = out_hdl;
00538 
00539       /* compute next name */
00540       obj_name.len = 0;
00541       dest_ptr = obj_name.name;
00542       while(ptr_str[0] != '\0' && ptr_str[0] != '/')
00543         {
00544           dest_ptr[0] = ptr_str[0];
00545           dest_ptr++;
00546           ptr_str++;
00547           obj_name.len++;
00548         }
00549       /* final null char */
00550       dest_ptr[0] = '\0';
00551 
00552       /* skip multiple slashes */
00553       while(ptr_str[0] == '/')
00554         ptr_str++;
00555 
00556       /* is the next name empty ? */
00557       if(ptr_str[0] == '\0')
00558         b_is_last = TRUE;
00559 
00560       /*call to PROXYFSAL_lookup */
00561       status = PROXYFSAL_lookup((fsal_handle_t *) &in_hdl,        /* parent directory handle */
00562                                 &obj_name,      /* object name */
00563                                 p_context,      /* user's credentials */
00564                                 (fsal_handle_t *) &out_hdl,       /* output root handle */
00565                                 /* retrieves attributes if this is the last lookup : */
00566                                 (b_is_last ? object_attributes : NULL));
00567 
00568       if(FSAL_IS_ERROR(status))
00569         Return(status.major, status.minor, INDEX_FSAL_lookupPath);
00570 
00571       /* if the target object is a junction, an we allow cross junction lookups,
00572        * we cross it.
00573        */
00574       if(global_fs_info.auth_exportpath_xdev
00575          && (out_hdl.data.object_type_reminder == FSAL_TYPE_JUNCTION))
00576         {
00577           proxyfsal_handle_t tmp_hdl;
00578 
00579           tmp_hdl = out_hdl;
00580 
00581           /*call to PROXYFSAL_lookup */
00582           status = PROXYFSAL_lookupJunction((fsal_handle_t *) &tmp_hdl,   /* object handle */
00583                                             p_context,  /* user's credentials */
00584                                             (fsal_handle_t *) &out_hdl,   /* output root handle */
00585                                             /* retrieves attributes if this is the last lookup : */
00586                                             (b_is_last ? object_attributes : NULL));
00587 
00588         }
00589 
00590       /* ptr_str is ok, we are ready for next loop */
00591     }
00592 
00593   (*(proxyfsal_handle_t *)object_handle) = out_hdl;
00594   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_lookupPath);
00595 
00596 }