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 <string.h>
00018 #include "fsal.h"
00019 #include "fsal_internal.h"
00020 #include "fsal_convert.h"
00021 
00049 fsal_status_t POSIXFSAL_lookup(fsal_handle_t * parent_directory_handle,  /* IN */
00050                                fsal_name_t * p_filename,        /* IN */
00051                                fsal_op_context_t * context,      /* IN */
00052                                fsal_handle_t * object_handle,    /* OUT */
00053                                fsal_attrib_list_t * p_object_attributes /* [ IN/OUT ] */
00054     )
00055 {
00056   posixfsal_handle_t * p_parent_directory_handle
00057     = (posixfsal_handle_t *) parent_directory_handle;
00058   posixfsal_op_context_t * p_context = (posixfsal_op_context_t *) context;
00059   posixfsal_handle_t * p_object_handle = (posixfsal_handle_t *) object_handle;
00060   int rc, errsv;
00061   fsal_status_t status;
00062 /*   fsal_posixdb_status_t statusdb; */
00063   fsal_posixdb_fileinfo_t infofs;
00064   struct stat buffstat;
00065   fsal_path_t pathfsal;
00066 
00067   /* sanity checks
00068    * note : object_attributes is optionnal
00069    *        parent_directory_handle may be null for getting FS root.
00070    */
00071   if(!p_object_handle || !p_context)
00072     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup);
00073 
00074   /* filename is NULL => lookup "/" */
00075   if((p_parent_directory_handle && !p_filename)
00076      || (!p_parent_directory_handle && p_filename))
00077     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup);
00078 
00079   /* get informations about the parent */
00080   if(!p_parent_directory_handle)
00081     {                           /* lookup '/' */
00082       TakeTokenFSCall();
00083       rc = lstat("/", &buffstat);
00084       errsv = errno;
00085       ReleaseTokenFSCall();
00086       if(rc)
00087         Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_lookup);
00088     }
00089   else
00090     {
00091       status =
00092           fsal_internal_getPathFromHandle(p_context, p_parent_directory_handle, 1,
00093                                           &pathfsal, &buffstat);
00094       if(FSAL_IS_ERROR(status))
00095         Return(status.major, status.minor, INDEX_FSAL_lookup);
00096     }
00097 
00098   /* Be careful about junction crossing, symlinks, hardlinks,... */
00099   switch (posix2fsal_type(buffstat.st_mode))
00100     {
00101     case FSAL_TYPE_DIR:
00102       // OK
00103       break;
00104 
00105     case FSAL_TYPE_JUNCTION:
00106       // This is a junction
00107       Return(ERR_FSAL_XDEV, 0, INDEX_FSAL_lookup);
00108 
00109     case FSAL_TYPE_FILE:
00110     case FSAL_TYPE_LNK:
00111     case FSAL_TYPE_XATTR:
00112       // not a directory 
00113       Return(ERR_FSAL_NOTDIR, 0, INDEX_FSAL_lookup);
00114 
00115     default:
00116       Return(ERR_FSAL_SERVERFAULT, 0, INDEX_FSAL_lookup);
00117     }
00118 
00119   if(!p_parent_directory_handle)
00120     {                           /* lookup '/' */
00121       /* convert struct stat to fsal_posixdb_fileinfo_t */
00122 
00123       if(FSAL_IS_ERROR(status = fsal_internal_posix2posixdb_fileinfo(&buffstat, &infofs)))
00124         Return(status.major, status.minor, INDEX_FSAL_lookup);
00125 
00126       /* get The handle of '/' */
00127       status =
00128           fsal_internal_getInfoFromName(p_context, NULL, NULL, &infofs, p_object_handle);
00129       if(FSAL_IS_ERROR(status))
00130         Return(status.major, status.minor, INDEX_FSAL_lookup);
00131 
00132     }
00133   else
00134     {
00135 
00136       LogFullDebug(COMPONENT_FSAL, "lookup of %llu.%i/%s\n", p_parent_directory_handle->data.id,
00137                    p_parent_directory_handle->data.ts, p_filename->name);
00138 
00139       /* check rights to enter into the directory */
00140       status = fsal_internal_testAccess(p_context, FSAL_X_OK, &buffstat, NULL);
00141       if(FSAL_IS_ERROR(status))
00142         Return(status.major, status.minor, INDEX_FSAL_lookup);
00143 
00144       /* stat the file to see if it exists and get some information */
00145       status = fsal_internal_appendFSALNameToFSALPath(&pathfsal, p_filename);
00146       if(FSAL_IS_ERROR(status))
00147         Return(status.major, status.minor, INDEX_FSAL_lookup);
00148 
00149       TakeTokenFSCall();
00150       rc = lstat(pathfsal.path, &buffstat);
00151       errsv = errno;
00152       ReleaseTokenFSCall();
00153       if(rc)
00154         Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_lookup);
00155 
00156       /* getHandleFromName */
00157       if(!FSAL_namecmp(p_filename, (fsal_name_t *) & FSAL_DOT))
00158         {
00159           /* lookup "." */
00160           memcpy(p_object_handle, p_parent_directory_handle, sizeof(posixfsal_handle_t));
00161 
00162         }
00163       else if(!FSAL_namecmp(p_filename, (fsal_name_t *) & FSAL_DOT_DOT))
00164         {
00165           /* lookup ".." */
00166                 /* statusdb = */(void) fsal_posixdb_getParentDirHandle(p_context->p_conn,
00167                                                      p_parent_directory_handle,
00168                                                      p_object_handle);
00169         }
00170       else
00171         {
00172           /* convert struct stat to fsal_posixdb_fileinfo_t */
00173           if(FSAL_IS_ERROR
00174              (status = fsal_internal_posix2posixdb_fileinfo(&buffstat, &infofs)))
00175             Return(status.major, status.minor, INDEX_FSAL_lookup);
00176 
00177           /* get The handle of the file */
00178           status =
00179               fsal_internal_getInfoFromName(p_context, p_parent_directory_handle,
00180                                             p_filename, &infofs, p_object_handle);
00181           if(FSAL_IS_ERROR(status))
00182             Return(status.major, status.minor, INDEX_FSAL_lookup);
00183         }
00184 
00185     }
00186 
00187   if(p_object_attributes)
00188     {
00189 
00190       /* convert posix attributes to fsal attributes */
00191       status = posix2fsal_attributes(&buffstat, p_object_attributes);
00192 
00193       if(FSAL_IS_ERROR(status))
00194         {
00195           FSAL_CLEAR_MASK(p_object_attributes->asked_attributes);
00196           FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00197         }
00198     }
00199 
00200   /* lookup complete ! */
00201   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_lookup);
00202 
00203 }
00204 
00227 fsal_status_t POSIXFSAL_lookupPath(fsal_path_t * p_path,        /* IN */
00228                                    fsal_op_context_t * context,  /* IN */
00229                                    fsal_handle_t * object_hdl,  /* OUT */
00230                                    fsal_attrib_list_t * object_attributes       /* [ IN/OUT ] */
00231     )
00232 {
00233   posixfsal_op_context_t * p_context = (posixfsal_op_context_t *) context;
00234   posixfsal_handle_t * object_handle = (posixfsal_handle_t *) object_hdl;
00235   fsal_name_t obj_name = FSAL_NAME_INITIALIZER; /* empty string */
00236   char *ptr_str;
00237   posixfsal_handle_t out_hdl;
00238   fsal_status_t status;
00239   int b_is_last = FALSE;        /* is it the last lookup ? */
00240 
00241   /* sanity checks
00242    * note : object_attributes is optionnal.
00243    */
00244 
00245   if(!object_handle || !p_context || !p_path)
00246     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookupPath);
00247 
00248   /* test whether the path begins with a slash */
00249 
00250   if(p_path->path[0] != '/')
00251     Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_lookupPath);
00252 
00253   /* the pointer now points on the next name in the path,
00254    * skipping slashes.
00255    */
00256 
00257   ptr_str = p_path->path + 1;
00258   while(ptr_str[0] == '/')
00259     ptr_str++;
00260 
00261   /* is the next name empty ? */
00262 
00263   if(ptr_str[0] == '\0')
00264     b_is_last = TRUE;
00265 
00266   /* retrieves root directory */
00267 
00268   status = POSIXFSAL_lookup(NULL,       /* looking up for root */
00269                             NULL,       /* empty string to get root handle */
00270                             p_context,  /* user's p_contextentials */
00271                             &out_hdl,   /* output root handle */
00272                             /* retrieves attributes if this is the last lookup : */
00273                             (b_is_last ? object_attributes : NULL));
00274 
00275   if(FSAL_IS_ERROR(status))
00276     Return(status.major, status.minor, INDEX_FSAL_lookupPath);
00277 
00278   /* exits if this was the last lookup */
00279 
00280   if(b_is_last)
00281     {
00282       (*object_handle) = out_hdl;
00283       Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_lookupPath);
00284     }
00285 
00286   /* proceed a step by step lookup */
00287 
00288   while(ptr_str[0])
00289     {
00290 
00291       posixfsal_handle_t in_hdl;
00292       char *dest_ptr;
00293 
00294       /* preparing lookup */
00295 
00298       in_hdl = out_hdl;
00299 
00300       /* compute next name */
00301       dest_ptr = obj_name.name;
00302       obj_name.len = 0;
00303       while(ptr_str[0] != '\0' && ptr_str[0] != '/')
00304         {
00305           dest_ptr[0] = ptr_str[0];
00306           dest_ptr++;
00307           ptr_str++;
00308           obj_name.len++;
00309         }
00310       /* final null char */
00311       dest_ptr[0] = '\0';
00312 
00313       /* skip multiple slashes */
00314       while(ptr_str[0] == '/')
00315         ptr_str++;
00316 
00317       /* is the next name empty ? */
00318       if(ptr_str[0] == '\0')
00319         b_is_last = TRUE;
00320 
00321       /*call to FSAL_lookup */
00322       status = POSIXFSAL_lookup(&in_hdl,        /* parent directory handle */
00323                                 &obj_name,      /* object name */
00324                                 p_context,      /* user's p_contextentials */
00325                                 &out_hdl,       /* output root handle */
00326                                 /* retrieves attributes if this is the last lookup : */
00327                                 (b_is_last ? object_attributes : NULL));
00328 
00329       if(FSAL_IS_ERROR(status))
00330         Return(status.major, status.minor, INDEX_FSAL_lookupPath);
00331 
00332       /* ptr_str is ok, we are ready for next loop */
00333     }
00334 
00335   (*object_handle) = out_hdl;
00336   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_lookupPath);
00337 
00338 }
00339 
00363 fsal_status_t POSIXFSAL_lookupJunction(fsal_handle_t * p_junction_handle,  /* IN */
00364                                        fsal_op_context_t * p_context,      /* IN */
00365                                        fsal_handle_t * p_fsoot_handle,     /* OUT */
00366                                        fsal_attrib_list_t * p_fsroot_attributes /* [ IN/OUT ] */
00367     )
00368 {
00369   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_lookupJunction);
00370 }