func: static int read_directory(BDRVVVFATState* s, int mapping_index)
  
  {
  
      mapping_t* mapping = array_get(&(s->mapping), mapping_index);
  
      direntry_t* direntry;
  
      const char* dirname = mapping->path;
  
      int first_cluster = mapping->begin;
  
      int parent_index = mapping->info.dir.parent_mapping_index;
  
      mapping_t* parent_mapping = (mapping_t*)
  
          (parent_index >= 0 ? array_get(&(s->mapping), parent_index) : NULL);
  
      int first_cluster_of_parent = parent_mapping ? parent_mapping->begin : -1;
  
  
  
      DIR* dir=opendir(dirname);
  
      struct dirent* entry;
  
      int i;
  
  
  
      assert(mapping->mode & MODE_DIRECTORY);
  
  
  
      if(!dir) {
  
          mapping->end = mapping->begin;
  
          return -1;
  
      }
  
  
  
      i = mapping->info.dir.first_dir_index =
  
              first_cluster == 0 ? 0 : s->directory.next;
  
  
  
      if (first_cluster != 0) {
  
          /* create the top entries of a subdirectory */
  
          (void)create_short_and_long_name(s, i, ".", 1);
  
          (void)create_short_and_long_name(s, i, "..", 1);
  
      }
  
  
  
      /* actually read the directory, and allocate the mappings */
  
      while((entry=readdir(dir))) {
  
          unsigned int length=strlen(dirname)+2+strlen(entry->d_name);
  
          char* buffer;
  
          direntry_t* direntry;
  
          struct stat st;
  
          int is_dot=!strcmp(entry->d_name,".");
  
          int is_dotdot=!strcmp(entry->d_name,"..");
  
  
  
          if(first_cluster == 0 && (is_dotdot || is_dot))
  
              continue;
  
  
  
          buffer = g_malloc(length);
  
          snprintf(buffer,length,"%s/%s",dirname,entry->d_name);
  
  
  
          if(stat(buffer,&st)<0) {
  
              g_free(buffer);
  
              continue;
  
          }
  
  
  
          /* create directory entry for this file */
  
          if (!is_dot && !is_dotdot) {
  
              direntry = create_short_and_long_name(s, i, entry->d_name, 0);
  
          } else {
  
              direntry = array_get(&(s->directory), is_dot ? i : i + 1);
  
          }
  
          direntry->attributes=(S_ISDIR(st.st_mode)?0x10:0x20);
  
          direntry->reserved[0]=direntry->reserved[1]=0;
  
          direntry->ctime=fat_datetime(st.st_ctime,1);
  
          direntry->cdate=fat_datetime(st.st_ctime,0);
  
          direntry->adate=fat_datetime(st.st_atime,0);
  
          direntry->begin_hi=0;
  
          direntry->mtime=fat_datetime(st.st_mtime,1);
  
          direntry->mdate=fat_datetime(st.st_mtime,0);
  
          if(is_dotdot)
  
              set_begin_of_direntry(direntry, first_cluster_of_parent);
  
          else if(is_dot)
  
              set_begin_of_direntry(direntry, first_cluster);
  
          else
  
              direntry->begin=0; /* do that later */
  
          if (st.st_size > 0x7fffffff) {
  
              fprintf(stderr, "File %s is larger than 2GB\n", buffer);
  
              g_free(buffer);
  
              closedir(dir);
  
              return -2;
  
          }
  
          direntry->size=cpu_to_le32(S_ISDIR(st.st_mode)?0:st.st_size);
  
  
  
          /* create mapping for this file */
  
          if(!is_dot && !is_dotdot && (S_ISDIR(st.st_mode) || st.st_size)) {
  
              s->current_mapping = array_get_next(&(s->mapping));
  
              s->current_mapping->begin=0;
  
              s->current_mapping->end=st.st_size;
  
              /*
  
               * we get the direntry of the most recent direntry, which
  
               * contains the short name and all the relevant information.
  
               */
  
              s->current_mapping->dir_index=s->directory.next-1;
  
              s->current_mapping->first_mapping_index = -1;
  
              if (S_ISDIR(st.st_mode)) {
  
                  s->current_mapping->mode = MODE_DIRECTORY;
  
                  s->current_mapping->info.dir.parent_mapping_index =
  
                      mapping_index;
  
              } else {
  
                  s->current_mapping->mode = MODE_UNDEFINED;
  
                  s->current_mapping->info.file.offset = 0;
  
              }
  
              s->current_mapping->path=buffer;
  
              s->current_mapping->read_only =
  
                  (st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0;
  
          } else {
  
              g_free(buffer);
  
          }
  
      }
  
      closedir(dir);
  
  
  
      /* fill with zeroes up to the end of the cluster */
  
      while(s->directory.next%(0x10*s->sectors_per_cluster)) {
  
          direntry_t* direntry=array_get_next(&(s->directory));
  
          memset(direntry,0,sizeof(direntry_t));
  
      }
  
  
  
  /* TODO: if there are more entries, bootsector has to be adjusted! */
  
  #define ROOT_ENTRIES (0x02 * 0x10 * s->sectors_per_cluster)
  
      if (mapping_index == 0 && s->directory.next < ROOT_ENTRIES) {
  
          /* root directory */
  
          int cur = s->directory.next;
  
          array_ensure_allocated(&(s->directory), ROOT_ENTRIES - 1);
  
          s->directory.next = ROOT_ENTRIES;
  
          memset(array_get(&(s->directory), cur), 0,
  
                  (ROOT_ENTRIES - cur) * sizeof(direntry_t));
  
      }
  
  
  
      /* re-get the mapping, since s->mapping was possibly realloc()ed */
  
      mapping = array_get(&(s->mapping), mapping_index);
  
      first_cluster += (s->directory.next - mapping->info.dir.first_dir_index)
  
          * 0x20 / s->cluster_size;
  
      mapping->end = first_cluster;
  
  
  
      direntry = array_get(&(s->directory), mapping->dir_index);
  
      set_begin_of_direntry(direntry, mapping->begin);
  
  
  
      return 0;
  
  }
  