nfs-ganesha 1.4

fsal_dirs.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
00003  */
00004 
00014 #ifdef HAVE_CONFIG_H
00015 #include "config.h"
00016 #endif
00017 
00018 #include "fsal.h"
00019 #include "fsal_internal.h"
00020 #include "fsal_convert.h"
00021 #include "abstract_mem.h"
00022 #include <string.h>
00023 
00044 fsal_status_t POSIXFSAL_opendir(fsal_handle_t * dir_handle,      /* IN */
00045                                 fsal_op_context_t * context,     /* IN */
00046                                 fsal_dir_t * dir_descriptor,     /* OUT */
00047                                 fsal_attrib_list_t * p_dir_attributes   /* [ IN/OUT ] */
00048     )
00049 {
00050   posixfsal_handle_t * p_dir_handle = (posixfsal_handle_t *) dir_handle;
00051   posixfsal_op_context_t * p_context = (posixfsal_op_context_t *) context;
00052   posixfsal_dir_t * p_dir_descriptor = (posixfsal_dir_t *) dir_descriptor;
00053   int rc;
00054   fsal_status_t status;
00055 
00056   fsal_path_t fsalpath;
00057   struct stat buffstat;
00058 
00059   /* sanity checks
00060    * note : dir_attributes is optionnal.
00061    */
00062   if(!p_dir_handle || !p_context || !p_dir_descriptor)
00063     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_opendir);
00064 
00065   /* get the path of the directory */
00066   status =
00067       fsal_internal_getPathFromHandle(p_context, p_dir_handle, 1, &fsalpath, &buffstat);
00068   if(FSAL_IS_ERROR(status))
00069     Return(status.major, status.minor, INDEX_FSAL_opendir);
00070 
00071   /* Test access rights for this directory */
00072 
00073   status = fsal_internal_testAccess(p_context, FSAL_R_OK, &buffstat, NULL);
00074   if(FSAL_IS_ERROR(status))
00075     Return(status.major, status.minor, INDEX_FSAL_opendir);
00076 
00077   /* if everything is OK, fills the dir_desc structure : */
00078 
00079   TakeTokenFSCall();
00080   p_dir_descriptor->p_dir = opendir(fsalpath.path);
00081   ReleaseTokenFSCall();
00082   if(!p_dir_descriptor->p_dir)
00083     Return(posix2fsal_error(errno), errno, INDEX_FSAL_opendir);
00084 
00085   memcpy(&(p_dir_descriptor->context), p_context, sizeof(posixfsal_op_context_t));
00086   memcpy(&(p_dir_descriptor->path), &fsalpath, sizeof(fsal_path_t));
00087   memcpy(&(p_dir_descriptor->handle), p_dir_handle, sizeof(posixfsal_handle_t));
00088 
00089 #ifdef _USE_POSIXDB_READDIR_BLOCK
00090   p_dir_descriptor->p_dbentries = NULL;
00091   p_dir_descriptor->dbentries_count = 0;
00092   /* fill the p_dbentries list */
00093   statusdb = fsal_posixdb_getChildren(p_dir_descriptor->context.p_conn,
00094                                       &(p_dir_descriptor->handle),
00095                                       FSAL_POSIXDB_MAXREADDIRBLOCKSIZE,
00096                                       &(p_dir_descriptor->p_dbentries),
00097                                       &(p_dir_descriptor->dbentries_count));
00098   if(FSAL_POSIXDB_IS_ERROR(statusdb))   /* too many entries in the directory, or another error */
00099     p_dir_descriptor->dbentries_count = -1;
00100 
00101 #endif
00102   if(p_dir_attributes)
00103     {
00104 
00105       TakeTokenFSCall();
00106       rc = lstat(fsalpath.path, &buffstat);
00107       ReleaseTokenFSCall();
00108       if(rc)                    /* lstat failed */
00109         goto attr_err;
00110 
00111       status = posix2fsal_attributes(&buffstat, p_dir_attributes);
00112       if(FSAL_IS_ERROR(status))
00113         {
00114  attr_err:
00115           FSAL_CLEAR_MASK(p_dir_attributes->asked_attributes);
00116           FSAL_SET_MASK(p_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00117         }
00118     }
00119 
00120   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_opendir);
00121 
00122 }
00123 
00157 fsal_status_t POSIXFSAL_readdir(fsal_dir_t * dir_descriptor,     /* IN */
00158                                 fsal_cookie_t start_pos,      /* IN */
00159                                 fsal_attrib_mask_t get_attr_mask,       /* IN */
00160                                 fsal_mdsize_t buffersize,       /* IN */
00161                                 fsal_dirent_t * p_pdirent,      /* OUT */
00162                                 fsal_cookie_t * end_position,    /* OUT */
00163                                 fsal_count_t * p_nb_entries,    /* OUT */
00164                                 fsal_boolean_t * p_end_of_dir   /* OUT */
00165     )
00166 {
00167   posixfsal_dir_t * p_dir_descriptor = (posixfsal_dir_t *) dir_descriptor;
00168   posixfsal_cookie_t start_position, telldir_pos;
00169   posixfsal_cookie_t * p_end_position = (posixfsal_cookie_t *) end_position;
00170   fsal_status_t st;
00171   fsal_posixdb_status_t stdb;
00172   fsal_count_t max_dir_entries;
00173   struct dirent *dp;
00174   struct dirent dpe;
00175   struct stat buffstat;
00176   fsal_path_t fsalpath;
00177   fsal_posixdb_fileinfo_t infofs;
00178   int rc;
00179 
00180   /*****************/
00181   /* sanity checks */
00182   /*****************/
00183 
00184   if(!p_dir_descriptor || !p_pdirent || !p_end_position || !p_nb_entries || !p_end_of_dir)
00185     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readdir);
00186 
00187   max_dir_entries = (buffersize / sizeof(fsal_dirent_t));
00188 
00189   /***************************/
00190   /* seek into the directory */
00191   /***************************/
00192   memcpy ( (char *)&start_position.data.cookie, (char *)&start_pos.data, sizeof( off_t ) ) ;
00193 
00194   errno = 0;
00195   if(start_position.data.cookie == 0)
00196     {
00197       rewinddir(p_dir_descriptor->p_dir);
00198       rc = errno;
00199     }
00200   else
00201     {
00202       seekdir(p_dir_descriptor->p_dir, start_position.data.cookie);
00203       rc = errno;
00204     }
00205 
00206   if(rc)
00207     {
00208       st.major = posix2fsal_error(rc);
00209       st.minor = rc;
00210       goto readdir_error;
00211     }
00212 
00213   /************************/
00214   /* browse the directory */
00215   /************************/
00216 
00217   *p_nb_entries = 0;
00218   while(*p_nb_entries < max_dir_entries)
00219     {
00220     /***********************/
00221       /* read the next entry */
00222     /***********************/
00223       TakeTokenFSCall();
00224       rc = readdir_r(p_dir_descriptor->p_dir, &dpe, &dp);
00225       ReleaseTokenFSCall();
00226       if(rc)
00227         {
00228           st.major = posix2fsal_error(errno);
00229           st.minor = errno;
00230           goto readdir_error;
00231         }                       /* End of directory */
00232       if(!dp)
00233         {
00234           *p_end_of_dir = 1;
00235           break;
00236         }
00237 
00238     /***********************************/
00239       /* Get information about the entry */
00240     /***********************************/
00241 
00242       /* build the full path of the file into "fsalpath */
00243       if(FSAL_IS_ERROR
00244          (st =
00245           FSAL_str2name(dp->d_name, FSAL_MAX_NAME_LEN, &(p_pdirent[*p_nb_entries].name))))
00246         goto readdir_error;
00247       memcpy(&fsalpath, &(p_dir_descriptor->path), sizeof(fsal_path_t));
00248       st = fsal_internal_appendFSALNameToFSALPath(&fsalpath,
00249                                                   &(p_pdirent[*p_nb_entries].name));
00250       if(FSAL_IS_ERROR(st))
00251         goto readdir_error;
00252 
00253       /* get object info */
00254       TakeTokenFSCall();
00255       rc = lstat(fsalpath.path, &buffstat);
00256       ReleaseTokenFSCall();
00257       if(rc)
00258         {
00259           st.major = posix2fsal_error(errno);
00260           st.minor = errno;
00261           goto readdir_error;
00262         }
00263       if(FSAL_IS_ERROR(st = fsal_internal_posix2posixdb_fileinfo(&buffstat, &infofs)))
00264         goto readdir_error;
00265 
00266     /********************/
00267       /* fills the handle */
00268     /********************/
00269 
00270       /* check for "." and ".." */
00271       if(!strcmp(dp->d_name, "."))
00272         {
00273           memcpy(&(p_pdirent[*p_nb_entries].handle), &(p_dir_descriptor->handle),
00274                  sizeof(posixfsal_handle_t));
00275         }
00276       else if(!strcmp(dp->d_name, ".."))
00277         {
00278           stdb = fsal_posixdb_getParentDirHandle(p_dir_descriptor->context.p_conn,
00279                                                  &(p_dir_descriptor->handle),
00280                                                  (posixfsal_handle_t *) &(p_pdirent[*p_nb_entries].handle));
00281           if(FSAL_POSIXDB_IS_ERROR(stdb) && FSAL_IS_ERROR(st = posixdb2fsal_error(stdb)))
00282             goto readdir_error;
00283         }
00284       else
00285         {
00286 #ifdef _USE_POSIXDB_READDIR_BLOCK
00287           if(p_dir_descriptor->dbentries_count > -1)
00288             {                   /* look for the entry in dbentries */
00289               st = fsal_internal_getInfoFromChildrenList(&(p_dir_descriptor->context),
00290                                                          &(p_dir_descriptor->handle),
00291                                                          &(p_pdirent[*p_nb_entries].name),
00292                                                          &infofs,
00293                                                          p_dir_descriptor->p_dbentries,
00294                                                          p_dir_descriptor->
00295                                                          dbentries_count,
00296                                                          &(p_pdirent[*p_nb_entries].
00297                                                            handle));
00298             }
00299           else
00300 #endif
00301             {                   /* get handle for the entry */
00302               st = fsal_internal_getInfoFromName(&(p_dir_descriptor->context),
00303                                                  &(p_dir_descriptor->handle),
00304                                                  &(p_pdirent[*p_nb_entries].name),
00305                                                  &infofs,
00306                                                  (posixfsal_handle_t *) &(p_pdirent[*p_nb_entries].handle));
00307             }
00308           if(FSAL_IS_ERROR(st))
00309             goto readdir_error;
00310         }                       /* end of name check for "." and ".." */
00311 
00312     /************************
00313      * Fills the attributes *
00314      ************************/
00315       p_pdirent[*p_nb_entries].attributes.asked_attributes = get_attr_mask;
00316       st = posix2fsal_attributes(&buffstat, &(p_pdirent[*p_nb_entries].attributes));
00317       if(FSAL_IS_ERROR(st))
00318         goto readdir_error;
00319 
00320       /*
00321        * 
00322        **/
00323       telldir_pos.data.cookie = telldir(p_dir_descriptor->p_dir);
00324       memcpy(&p_pdirent[*p_nb_entries].cookie, &telldir_pos, sizeof(fsal_cookie_t));
00325       p_pdirent[*p_nb_entries].nextentry = NULL;
00326       if(*p_nb_entries)
00327         p_pdirent[*p_nb_entries - 1].nextentry = &(p_pdirent[*p_nb_entries]);
00328 
00329       memcpy(p_end_position, &p_pdirent[*p_nb_entries].cookie, sizeof(fsal_cookie_t));
00330       (*p_nb_entries)++;
00331     };
00332 
00333   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readdir);
00334 
00335   /* return error, and free what must be freed */
00336  readdir_error:
00337   Return(st.major, st.minor, INDEX_FSAL_readdir);
00338 }
00339 
00351 fsal_status_t POSIXFSAL_closedir(fsal_dir_t * dir_descriptor     /* IN */  )
00352 {
00353   posixfsal_dir_t * p_dir_descriptor = (posixfsal_dir_t *) dir_descriptor;
00354   int rc;
00355 
00356   /* sanity checks */
00357   if(!p_dir_descriptor)
00358     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_closedir);
00359 
00360 #ifdef _USE_POSIXDB_READDIR_BLOCK
00361   if(p_dir_descriptor->p_dbentries)
00362     gsh_free(p_dir_descriptor->p_dbentries);
00363 #endif
00364 
00365   rc = closedir(p_dir_descriptor->p_dir);
00366   if(rc != 0)
00367     Return(posix2fsal_error(errno), errno, INDEX_FSAL_closedir);
00368 
00369   /* fill dir_descriptor with zeros */
00370   memset(p_dir_descriptor, 0, sizeof(posixfsal_dir_t));
00371 
00372   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_closedir);
00373 
00374 }