nfs-ganesha 1.4

fsal_dirs.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=4:tabstop=4:
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/access_check.h"
00021 #include "fsal_convert.h"
00022 #include <string.h>
00023 
00044 fsal_status_t XFSFSAL_opendir(fsal_handle_t * p_dir_handle,  /* IN */
00045                               fsal_op_context_t * p_context, /* IN */
00046                               fsal_dir_t *dir_desc, /* OUT */
00047                               fsal_attrib_list_t * p_dir_attributes     /* [ IN/OUT ] */
00048     )
00049 {
00050   xfsfsal_dir_t * p_dir_descriptor = (xfsfsal_dir_t *) dir_desc;
00051   int rc = 0 , errsv = 0 ;
00052   fsal_status_t status;
00053 
00054   struct stat buffstat;
00055 
00056   /* sanity checks
00057    * note : dir_attributes is optionnal.
00058    */
00059   if(!p_dir_handle || !p_context || !p_dir_descriptor)
00060     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_opendir);
00061 
00062   /* get the path of the directory */
00063   TakeTokenFSCall();
00064   status =
00065       fsal_internal_handle2fd(p_context, p_dir_handle, &p_dir_descriptor->fd,
00066                               O_RDONLY | O_DIRECTORY);
00067   ReleaseTokenFSCall();
00068 
00069   if(FSAL_IS_ERROR(status))
00070     ReturnStatus(status, INDEX_FSAL_opendir);
00071 
00072   /* get directory metadata */
00073   TakeTokenFSCall();
00074   rc = fstat(p_dir_descriptor->fd, &buffstat);
00075   ReleaseTokenFSCall();
00076 
00077   if(rc != 0)
00078     {
00079       close(p_dir_descriptor->fd);
00080       if(rc == ENOENT)
00081         Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_opendir);
00082       else
00083         Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_opendir);
00084     }
00085 
00086   /* Test access rights for this directory */
00087   status = fsal_check_access(p_context, FSAL_R_OK, &buffstat, NULL);
00088   if(FSAL_IS_ERROR(status))
00089     ReturnStatus(status, INDEX_FSAL_opendir);
00090 
00091   /* if everything is OK, fills the dir_desc structure : */
00092 
00093   memcpy(&(p_dir_descriptor->context), p_context, sizeof(xfsfsal_op_context_t));
00094   memcpy(&(p_dir_descriptor->handle), p_dir_handle, sizeof(xfsfsal_handle_t));
00095 
00096   if(p_dir_attributes)
00097     {
00098       status = posix2fsal_attributes(&buffstat, p_dir_attributes);
00099       if(FSAL_IS_ERROR(status))
00100         {
00101           FSAL_CLEAR_MASK(p_dir_attributes->asked_attributes);
00102           FSAL_SET_MASK(p_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00103         }
00104     }
00105 
00106   p_dir_descriptor->dir_offset = 0;
00107 
00108   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_opendir);
00109 
00110 }
00111 
00112 /*
00113  * Common code used by fsal_lookup and fsal_readdir -
00114  * given the name try to stat an entry. If an entry is
00115  * regular file or directory then open it and use fd2handle
00116  * to get a real handle, otherwise use inum2handle to fake
00117  * a handle.
00118  */
00119 fsal_status_t
00120 xfsfsal_stat_by_name(fsal_op_context_t * context,
00121                      int atfd,
00122                      const char *name,
00123                      fsal_handle_t *handle,
00124                      fsal_attrib_list_t * attributes)
00125 {
00126   int rc;
00127   int errsv;
00128   struct stat buffstat;
00129   fsal_status_t st;
00130 
00131   TakeTokenFSCall();
00132   rc = fstatat(atfd, name, &buffstat, AT_SYMLINK_NOFOLLOW);
00133   errsv = errno;
00134   ReleaseTokenFSCall();
00135   if(rc < 0)
00136       ReturnCode(posix2fsal_error(errsv), errsv);
00137 
00138   if(S_ISDIR(buffstat.st_mode) ||  S_ISREG(buffstat.st_mode))
00139     {
00140       int tmpfd;
00141 
00142       TakeTokenFSCall();
00143       tmpfd = openat(atfd, name, O_RDONLY | O_NOFOLLOW, 0600);
00144       errsv = errno;
00145       ReleaseTokenFSCall();
00146       if(tmpfd < 0)
00147           ReturnCode(posix2fsal_error(errsv), errsv);
00148 
00149       st = fsal_internal_fd2handle(context, tmpfd, handle);
00150       close(tmpfd);
00151     } 
00152   else
00153     {
00154        st = fsal_internal_inum2handle(context, buffstat.st_ino, handle);
00155     }
00156 
00157   if(FSAL_IS_ERROR(st))
00158     return st;
00159 
00160   if(attributes)
00161     {
00162       st = posix2fsal_attributes(&buffstat, attributes);
00163       if(FSAL_IS_ERROR(st))
00164         {
00165           FSAL_CLEAR_MASK(attributes->asked_attributes);
00166           FSAL_SET_MASK(attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00167         }
00168     }
00169   return st;
00170 }
00171 
00172 
00207 struct linux_dirent
00208 {
00209   long d_ino;
00210   long d_off;                   /* Be careful, SYS_getdents is a 32 bits call */
00211   unsigned short d_reclen;
00212   char d_name[];
00213 };
00214 
00215 #define BUF_SIZE 1024
00216 
00217 fsal_status_t XFSFSAL_readdir(fsal_dir_t * dir_descriptor, /* IN */
00218                               fsal_cookie_t startposition,  /* IN */
00219                               fsal_attrib_mask_t get_attr_mask, /* IN */
00220                               fsal_mdsize_t buffersize, /* IN */
00221                               fsal_dirent_t * p_pdirent,        /* OUT */
00222                               fsal_cookie_t * end_position,        /* OUT */
00223                               fsal_count_t * p_nb_entries,      /* OUT */
00224                               fsal_boolean_t * p_end_of_dir     /* OUT */
00225     )
00226 {
00227   xfsfsal_dir_t * p_dir_descriptor = (xfsfsal_dir_t * ) dir_descriptor;
00228   xfsfsal_cookie_t start_position;
00229   xfsfsal_cookie_t * p_end_position = (xfsfsal_cookie_t *) end_position;
00230   fsal_status_t st;
00231   fsal_count_t max_dir_entries;
00232   char buff[BUF_SIZE];
00233   struct linux_dirent *dp = NULL;
00234   int bpos = 0;
00235 
00236   int rc = 0;
00237 
00238   memset(buff, 0, BUF_SIZE);
00239 
00240   /*****************/
00241   /* sanity checks */
00242   /*****************/
00243 
00244   if(!p_dir_descriptor || !p_pdirent || !p_end_position || !p_nb_entries || !p_end_of_dir)
00245     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readdir);
00246 
00247   max_dir_entries = (buffersize / sizeof(fsal_dirent_t));
00248 
00249   /***************************/
00250   /* seek into the directory */
00251   /***************************/
00252   memcpy( (char *)&start_position.data.cookie, (char *)&startposition.data, sizeof( off_t ) ) ;
00253   rc = errno = 0;
00254   lseek(p_dir_descriptor->fd, start_position.data.cookie, SEEK_SET);
00255   rc = errno;
00256 
00257   if(rc)
00258     Return(posix2fsal_error(rc), rc, INDEX_FSAL_readdir);
00259 
00260   /************************/
00261   /* browse the directory */
00262   /************************/
00263 
00264   *p_nb_entries = 0;
00265   while(*p_nb_entries < max_dir_entries)
00266     {
00267     /***********************/
00268       /* read the next entry */
00269     /***********************/
00270       TakeTokenFSCall();
00271       rc = syscall(SYS_getdents, p_dir_descriptor->fd, buff, BUF_SIZE);
00272       ReleaseTokenFSCall();
00273       if(rc < 0)
00274         {
00275           rc = errno;
00276           Return(posix2fsal_error(rc), rc, INDEX_FSAL_readdir);
00277         }
00278       /* End of directory */
00279       if(rc == 0)
00280         {
00281           *p_end_of_dir = 1;
00282           break;
00283         }
00284 
00285     /***********************************/
00286       /* Get information about the entry */
00287     /***********************************/
00288 
00289       for(bpos = 0; bpos < rc;)
00290         {
00291           dp = (struct linux_dirent *)(buff + bpos);
00292           bpos += dp->d_reclen;
00293 
00294           /* LogFullDebug(COMPONENT_FSAL, "\tino=%8ld|%8lx off=%d|%x reclen=%d|%x name=%s|%d", dp->d_ino, dp->d_ino, (int)dp->d_off, (int)dp->d_off, 
00295              dp->d_reclen, dp->d_reclen, dp->d_name, (int)dp->d_name[0]  ) ; */
00296 
00297           if(!(*p_nb_entries < max_dir_entries))
00298             break;
00299 
00300           /* skip . and .. */
00301           if(!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
00302             continue;
00303 
00304           /* build the full path of the file into "fsalpath */
00305           if(FSAL_IS_ERROR
00306              (st =
00307               FSAL_str2name(dp->d_name, FSAL_MAX_NAME_LEN,
00308                             &(p_pdirent[*p_nb_entries].name))))
00309             ReturnStatus(st, INDEX_FSAL_readdir);
00310 
00311           p_pdirent[*p_nb_entries].attributes.asked_attributes = get_attr_mask;
00312           st = xfsfsal_stat_by_name((fsal_op_context_t *)&(p_dir_descriptor->context),
00313                                     p_dir_descriptor->fd, dp->d_name, 
00314                                     &p_pdirent[*p_nb_entries].handle,
00315                                     &p_pdirent[*p_nb_entries].attributes);
00316 
00317           if(FSAL_IS_ERROR(st))
00318             ReturnStatus(st, INDEX_FSAL_readdir);
00319 
00320           ((xfsfsal_cookie_t *) (&p_pdirent[*p_nb_entries].cookie))->data.cookie = dp->d_off;
00321           p_pdirent[*p_nb_entries].nextentry = NULL;
00322           if(*p_nb_entries)
00323             p_pdirent[*p_nb_entries - 1].nextentry = &(p_pdirent[*p_nb_entries]);
00324 
00325           memcpy((char *)p_end_position, (char *)&p_pdirent[*p_nb_entries].cookie,
00326                  sizeof(xfsfsal_cookie_t));
00327 
00328           (*p_nb_entries)++;
00329         }                       /* for */
00330     }                           /* While */
00331 
00332   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readdir);
00333 
00334 }
00335 
00347 fsal_status_t XFSFSAL_closedir(fsal_dir_t * p_dir_descriptor /* IN */
00348     )
00349 {
00350 
00351   int rc;
00352 
00353   /* sanity checks */
00354   if(!p_dir_descriptor)
00355     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_closedir);
00356 
00357   rc = close(((xfsfsal_dir_t *)p_dir_descriptor)->fd);
00358   if(rc != 0)
00359     Return(posix2fsal_error(errno), errno, INDEX_FSAL_closedir);
00360 
00361   /* fill dir_descriptor with zeros */
00362   memset(p_dir_descriptor, 0, sizeof(xfsfsal_dir_t));
00363 
00364   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_closedir);
00365 
00366 }