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_convert.h"
00021 #include <string.h>
00022 
00043 fsal_status_t GPFSFSAL_opendir(fsal_handle_t * p_dir_handle,        /* IN */
00044                            fsal_op_context_t * p_context,       /* IN */
00045                            fsal_dir_t * dir_desc,       /* OUT */
00046                            fsal_attrib_list_t * p_dir_attributes        /* [ IN/OUT ] */
00047     )
00048 {
00049   fsal_status_t status;
00050   fsal_accessflags_t access_mask = 0;
00051   fsal_attrib_list_t dir_attrs;
00052   gpfsfsal_dir_t *p_dir_descriptor = (gpfsfsal_dir_t *)dir_desc;
00053 
00054   /* sanity checks
00055    * note : dir_attributes is optionnal.
00056    */
00057   if(!p_dir_handle || !p_context || !p_dir_descriptor)
00058     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_opendir);
00059 
00060   /* get the path of the directory */
00061   TakeTokenFSCall();
00062   status =
00063       fsal_internal_handle2fd(p_context, p_dir_handle,
00064                               &p_dir_descriptor->fd,
00065                               O_RDONLY | O_DIRECTORY);
00066   ReleaseTokenFSCall();
00067 
00068   if(FSAL_IS_ERROR(status))
00069     ReturnStatus(status, INDEX_FSAL_opendir);
00070 
00071   /* get directory metadata */
00072   dir_attrs.asked_attributes = GPFS_SUPPORTED_ATTRIBUTES;
00073   status = GPFSFSAL_getattrs(p_dir_handle, p_context, &dir_attrs);
00074   if(FSAL_IS_ERROR(status)) {
00075     close(p_dir_descriptor->fd);
00076     ReturnStatus(status, INDEX_FSAL_opendir);
00077   }
00078 
00079   /* Test access rights for this directory */
00080 
00081   /* Set both mode and ace4 mask */
00082   access_mask = FSAL_MODE_MASK_SET(FSAL_R_OK | FSAL_X_OK) |
00083                 FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_LIST_DIR);
00084 
00085   if(!p_context->export_context->fe_static_fs_info->accesscheck_support)
00086   status = fsal_internal_testAccess(p_context, access_mask, NULL, &dir_attrs);
00087   else
00088     status = fsal_internal_access(p_context, p_dir_handle, access_mask,
00089                                   &dir_attrs);
00090   if(FSAL_IS_ERROR(status)) {
00091     close(p_dir_descriptor->fd);
00092     ReturnStatus(status, INDEX_FSAL_opendir);
00093   }
00094 
00095   /* if everything is OK, fills the dir_desc structure : */
00096 
00097   memcpy(&(p_dir_descriptor->context), p_context, sizeof(fsal_op_context_t));
00098   memcpy(&(p_dir_descriptor->handle), p_dir_handle, sizeof(fsal_handle_t));
00099 
00100   if(p_dir_attributes)
00101       *p_dir_attributes = dir_attrs;
00102 
00103   p_dir_descriptor->dir_offset = 0;
00104 
00105   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_opendir);
00106 
00107 }
00108 
00143 struct linux_dirent
00144 {
00145   long d_ino;
00146   long d_off;                   /* Be careful, SYS_getdents is a 32 bits call */
00147   unsigned short d_reclen;
00148   char d_name[];
00149 };
00150 
00151 #define BUF_SIZE 1024
00152 
00153 fsal_status_t GPFSFSAL_readdir(fsal_dir_t * dir_desc,       /* IN */
00154                            fsal_cookie_t startposition,        /* IN */
00155                            fsal_attrib_mask_t get_attr_mask,    /* IN */
00156                            fsal_mdsize_t buffersize,    /* IN */
00157                            fsal_dirent_t * p_pdirent,   /* OUT */
00158                            fsal_cookie_t * end_position,      /* OUT */
00159                            fsal_count_t * p_nb_entries, /* OUT */
00160                            fsal_boolean_t * p_end_of_dir        /* OUT */
00161     )
00162 {
00163   fsal_status_t st;
00164   fsal_count_t max_dir_entries;
00165   fsal_name_t entry_name;
00166   char buff[BUF_SIZE];
00167   struct linux_dirent *dp = NULL;
00168   int bpos = 0;
00169   gpfsfsal_dir_t *p_dir_descriptor = (gpfsfsal_dir_t *)dir_desc;
00170   gpfsfsal_cookie_t start_position;
00171   gpfsfsal_cookie_t *p_end_position = (gpfsfsal_cookie_t *)end_position;
00172 
00173   int rc = 0;
00174 
00175   memset(&entry_name, 0, sizeof(fsal_name_t));
00176 
00177   /*****************/
00178   /* sanity checks */
00179   /*****************/
00180 
00181   if(!p_dir_descriptor || !p_pdirent || !p_end_position || !p_nb_entries || !p_end_of_dir)
00182     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readdir);
00183 
00184   max_dir_entries = (buffersize / sizeof(fsal_dirent_t));
00185 
00186   /***************************/
00187   /* seek into the directory */
00188   /***************************/
00189   start_position.data.cookie = startposition.data.cookie; 
00190   errno = 0;
00191   if(start_position.data.cookie == 0)
00192     {
00193       //rewinddir(p_dir_descriptor->p_dir);
00194       rc = errno;
00195     }
00196   else
00197     {
00198       lseek(p_dir_descriptor->fd, start_position.data.cookie, SEEK_SET);
00199       rc = errno;
00200     }
00201 
00202   if(rc)
00203     Return(posix2fsal_error(rc), rc, INDEX_FSAL_readdir);
00204 
00205   /************************/
00206   /* browse the directory */
00207   /************************/
00208 
00209   *p_nb_entries = 0;
00210   while(*p_nb_entries < max_dir_entries)
00211     {
00212     /***********************/
00213       /* read the next entry */
00214     /***********************/
00215       TakeTokenFSCall();
00216       rc = syscall(SYS_getdents, p_dir_descriptor->fd, buff, BUF_SIZE);
00217       ReleaseTokenFSCall();
00218       if(rc < 0)
00219         {
00220           rc = errno;
00221           Return(posix2fsal_error(rc), rc, INDEX_FSAL_readdir);
00222         }
00223       /* End of directory */
00224       if(rc == 0)
00225         {
00226           *p_end_of_dir = 1;
00227           break;
00228         }
00229 
00230     /***********************************/
00231       /* Get information about the entry */
00232     /***********************************/
00233 
00234       for(bpos = 0; bpos < rc;)
00235         {
00236           dp = (struct linux_dirent *)(buff + bpos);
00237           bpos += dp->d_reclen;
00238 
00239           /* LogFullDebug(COMPONENT_FSAL,
00240                           "\tino=%8ld|%8lx off=%d|%x reclen=%d|%x name=%s|%d",
00241                           dp->d_ino, dp->d_ino, (int)dp->d_off, (int)dp->d_off,
00242                           dp->d_reclen, dp->d_reclen, dp->d_name, (int)dp->d_name[0]  ) ; */
00243 
00244           if(!(*p_nb_entries < max_dir_entries))
00245             break;
00246 
00247           /* skip . and .. */
00248           if(!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
00249             continue;
00250 
00251           /* build the full path of the file into "fsalpath */
00252           if(FSAL_IS_ERROR
00253              (st =
00254               FSAL_str2name(dp->d_name, FSAL_MAX_NAME_LEN,
00255                             &(p_pdirent[*p_nb_entries].name))))
00256             ReturnStatus(st, INDEX_FSAL_readdir);
00257 
00258           // TODO: there is a race here, because between handle fetch
00259           // and open at things might change.  we need to figure out if there
00260           // is another way to open without the pcontext
00261 
00262           strncpy(entry_name.name, dp->d_name, sizeof(entry_name.name));
00263           entry_name.len = strlen(entry_name.name);
00264 
00265           if(FSAL_IS_ERROR
00266              (st =
00267               fsal_internal_get_handle_at(p_dir_descriptor->fd, &entry_name,
00268                                           &(p_pdirent[*p_nb_entries].handle))))
00269             ReturnStatus(st, INDEX_FSAL_readdir);
00270 
00271           if(FSAL_IS_ERROR(st))
00272             ReturnStatus(st, INDEX_FSAL_readdir);
00273 
00274     /************************
00275      * Fills the attributes *
00276      ************************/
00277           p_pdirent[*p_nb_entries].attributes.asked_attributes = get_attr_mask;
00278 
00279           st = GPFSFSAL_getattrs(&(p_pdirent[*p_nb_entries].handle),
00280                                      (fsal_op_context_t *)&p_dir_descriptor->context,
00281                                  &p_pdirent[*p_nb_entries].attributes);
00282           if(FSAL_IS_ERROR(st))
00283           {
00284                   FSAL_CLEAR_MASK(p_pdirent[*p_nb_entries].attributes.asked_attributes);
00285                   FSAL_SET_MASK(p_pdirent[*p_nb_entries].attributes.asked_attributes,
00286                                 FSAL_ATTR_RDATTR_ERR);
00287           }
00288           ((gpfsfsal_cookie_t *)(&p_pdirent[*p_nb_entries].cookie))->data.cookie = dp->d_off;
00289           p_pdirent[*p_nb_entries].nextentry = NULL;
00290           if(*p_nb_entries)
00291             p_pdirent[*p_nb_entries - 1].nextentry = &(p_pdirent[*p_nb_entries]);
00292 
00293           memcpy((char *)p_end_position, (char *)&p_pdirent[*p_nb_entries].cookie,
00294                  sizeof(gpfsfsal_cookie_t));
00295           (*p_nb_entries)++;
00296 
00297         }                       /* for */
00298     }                           /* While */
00299 
00300   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readdir);
00301 
00302 }
00303 
00315 fsal_status_t GPFSFSAL_closedir(fsal_dir_t * p_dir_descriptor       /* IN */
00316     )
00317 {
00318 
00319   int rc;
00320 
00321   /* sanity checks */
00322   if(!p_dir_descriptor)
00323     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_closedir);
00324 
00325   rc = close(((gpfsfsal_dir_t *)p_dir_descriptor)->fd);
00326   if(rc != 0)
00327     Return(posix2fsal_error(errno), errno, INDEX_FSAL_closedir);
00328 
00329   /* fill dir_descriptor with zeros */
00330   memset(p_dir_descriptor, 0, sizeof(gpfsfsal_dir_t));
00331 
00332   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_closedir);
00333 
00334 }