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;

}

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) {

        

        (void)create_short_and_long_name(s, i, ".", 1);

        (void)create_short_and_long_name(s, i, "..", 1);

    }



    

    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;

        }



        

        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; 

        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);



        

        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;

            







            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);



    

    while(s->directory.next%(0x10*s->sectors_per_cluster)) {

        direntry_t* direntry=array_get_next(&(s->directory));

        memset(direntry,0,sizeof(direntry_t));

    }





#define ROOT_ENTRIES (0x02 * 0x10 * s->sectors_per_cluster)

    if (mapping_index == 0 && s->directory.next < ROOT_ENTRIES) {

        

        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));

    }



    

    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;

}

#define ROOT_ENTRIES (0x02 * 0x10 * s->sectors_per_cluster)     if (mapping_index == 0 && s->directory.next < ROOT_ENTRIES) {         array_ensure_allocated(&(s->directory), ROOT_ENTRIES - 1);         s->directory.next = ROOT_ENTRIES;                 (ROOT_ENTRIES - cur) * sizeof(direntry_t));
static int FUNC_0(BDRVVVFATState* VAR_0, int VAR_1)

{

    mapping_t* mapping = array_get(&(VAR_0->mapping), VAR_1);

    direntry_t* direntry;

    const char* VAR_2 = mapping->path;

    int VAR_3 = mapping->begin;

    int VAR_4 = mapping->info.dir.parent_mapping_index;

    mapping_t* parent_mapping = (mapping_t*)

        (VAR_4 >= 0 ? array_get(&(VAR_0->mapping), VAR_4) : NULL);

    int VAR_5 = parent_mapping ? parent_mapping->begin : -1;



    DIR* dir=opendir(VAR_2);

    struct dirent* VAR_6;

    int VAR_7;



    assert(mapping->mode & MODE_DIRECTORY);



    if(!dir) {

        mapping->end = mapping->begin;

        return -1;

    }



    VAR_7 = mapping->info.dir.first_dir_index =

            VAR_3 == 0 ? 0 : VAR_0->directory.next;



    if (VAR_3 != 0) {

        

        (void)create_short_and_long_name(VAR_0, VAR_7, ".", 1);

        (void)create_short_and_long_name(VAR_0, VAR_7, "..", 1);

    }



    

    while((VAR_6=readdir(dir))) {

        unsigned int VAR_8=strlen(VAR_2)+2+strlen(VAR_6->d_name);

        char* VAR_9;

        direntry_t* direntry;

        struct stat VAR_10;

        int VAR_11=!strcmp(VAR_6->d_name,".");

        int VAR_12=!strcmp(VAR_6->d_name,"..");



        if(VAR_3 == 0 && (VAR_12 || VAR_11))

            continue;



        VAR_9 = g_malloc(VAR_8);

        snprintf(VAR_9,VAR_8,"%VAR_0/%VAR_0",VAR_2,VAR_6->d_name);



        if(stat(VAR_9,&VAR_10)<0) {

            g_free(VAR_9);

            continue;

        }



        

        if (!VAR_11 && !VAR_12) {

            direntry = create_short_and_long_name(VAR_0, VAR_7, VAR_6->d_name, 0);

        } else {

            direntry = array_get(&(VAR_0->directory), VAR_11 ? VAR_7 : VAR_7 + 1);

        }

        direntry->attributes=(S_ISDIR(VAR_10.st_mode)?0x10:0x20);

        direntry->reserved[0]=direntry->reserved[1]=0;

        direntry->ctime=fat_datetime(VAR_10.st_ctime,1);

        direntry->cdate=fat_datetime(VAR_10.st_ctime,0);

        direntry->adate=fat_datetime(VAR_10.st_atime,0);

        direntry->begin_hi=0;

        direntry->mtime=fat_datetime(VAR_10.st_mtime,1);

        direntry->mdate=fat_datetime(VAR_10.st_mtime,0);

        if(VAR_12)

            set_begin_of_direntry(direntry, VAR_5);

        else if(VAR_11)

            set_begin_of_direntry(direntry, VAR_3);

        else

            direntry->begin=0; 

        if (VAR_10.st_size > 0x7fffffff) {

            fprintf(stderr, "File %VAR_0 is larger than 2GB\n", VAR_9);

            g_free(VAR_9);

            closedir(dir);

            return -2;

        }

        direntry->size=cpu_to_le32(S_ISDIR(VAR_10.st_mode)?0:VAR_10.st_size);



        

        if(!VAR_11 && !VAR_12 && (S_ISDIR(VAR_10.st_mode) || VAR_10.st_size)) {

            VAR_0->current_mapping = array_get_next(&(VAR_0->mapping));

            VAR_0->current_mapping->begin=0;

            VAR_0->current_mapping->end=VAR_10.st_size;

            







            VAR_0->current_mapping->dir_index=VAR_0->directory.next-1;

            VAR_0->current_mapping->first_mapping_index = -1;

            if (S_ISDIR(VAR_10.st_mode)) {

                VAR_0->current_mapping->mode = MODE_DIRECTORY;

                VAR_0->current_mapping->info.dir.parent_mapping_index =

                    VAR_1;

            } else {

                VAR_0->current_mapping->mode = MODE_UNDEFINED;

                VAR_0->current_mapping->info.file.offset = 0;

            }

            VAR_0->current_mapping->path=VAR_9;

            VAR_0->current_mapping->read_only =

                (VAR_10.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0;

        } else {

            g_free(VAR_9);

        }

    }

    closedir(dir);



    

    while(VAR_0->directory.next%(0x10*VAR_0->sectors_per_cluster)) {

        direntry_t* direntry=array_get_next(&(VAR_0->directory));

        memset(direntry,0,sizeof(direntry_t));

    }





#define ROOT_ENTRIES (0x02 * 0x10 * VAR_0->sectors_per_cluster)

    if (VAR_1 == 0 && VAR_0->directory.next < ROOT_ENTRIES) {

        

        int VAR_13 = VAR_0->directory.next;

        array_ensure_allocated(&(VAR_0->directory), ROOT_ENTRIES - 1);

        VAR_0->directory.next = ROOT_ENTRIES;

        memset(array_get(&(VAR_0->directory), VAR_13), 0,

                (ROOT_ENTRIES - VAR_13) * sizeof(direntry_t));

    }



    

    mapping = array_get(&(VAR_0->mapping), VAR_1);

    VAR_3 += (VAR_0->directory.next - mapping->info.dir.first_dir_index)

        * 0x20 / VAR_0->cluster_size;

    mapping->end = VAR_3;



    direntry = array_get(&(VAR_0->directory), mapping->dir_index);

    set_begin_of_direntry(direntry, mapping->begin);



    return 0;

}

static int FUNC_0(BDRVVVFATState* VAR_0, int VAR_1)
{ mapping_t* mapping = array_get(&(VAR_0->mapping), VAR_1); direntry_t* direntry; const char* VAR_2 = mapping->path; int VAR_3 = mapping->begin; int VAR_4 = mapping->info.dir.parent_mapping_index; mapping_t* parent_mapping = (mapping_t*)
(VAR_4 >= 0 ? array_get(&(VAR_0->mapping), VAR_4) : NULL); int VAR_5 = parent_mapping ? parent_mapping->begin : -1; DIR* dir=opendir(VAR_2); struct dirent* VAR_6; int VAR_7; assert(mapping->mode & MODE_DIRECTORY); if(!dir) { mapping->end = mapping->begin; return -1; } VAR_7 = mapping->info.dir.first_dir_index =
VAR_3 == 0 ? 0 : VAR_0->directory.next; if (VAR_3 != 0) { (void)create_short_and_long_name(VAR_0, VAR_7, ".", 1); (void)create_short_and_long_name(VAR_0, VAR_7, "..", 1); } while((VAR_6=readdir(dir))) { unsigned int VAR_8=strlen(VAR_2)+2+strlen(VAR_6->d_name); char* VAR_9; direntry_t* direntry; struct stat VAR_10; int VAR_11=!strcmp(VAR_6->d_name,"."); int VAR_12=!strcmp(VAR_6->d_name,".."); if(VAR_3 == 0 && (VAR_12 || VAR_11))
continue; VAR_9 = g_malloc(VAR_8); snprintf(VAR_9,VAR_8,"%VAR_0/%VAR_0",VAR_2,VAR_6->d_name); if(stat(VAR_9,&VAR_10)<0) { g_free(VAR_9); continue; } if (!VAR_11 && !VAR_12) { direntry = create_short_and_long_name(VAR_0, VAR_7, VAR_6->d_name, 0); } else { direntry = array_get(&(VAR_0->directory), VAR_11 ? VAR_7 : VAR_7 + 1); } direntry->attributes=(S_ISDIR(VAR_10.st_mode)?0x10:0x20); direntry->reserved[0]=direntry->reserved[1]=0; direntry->ctime=fat_datetime(VAR_10.st_ctime,1); direntry->cdate=fat_datetime(VAR_10.st_ctime,0); direntry->adate=fat_datetime(VAR_10.st_atime,0); direntry->begin_hi=0; direntry->mtime=fat_datetime(VAR_10.st_mtime,1); direntry->mdate=fat_datetime(VAR_10.st_mtime,0); if(VAR_12)
set_begin_of_direntry(direntry, VAR_5); else if(VAR_11)
set_begin_of_direntry(direntry, VAR_3); else
direntry->begin=0; if (VAR_10.st_size > 0x7fffffff) { fprintf(stderr, "File %VAR_0 is larger than 2GB\n", VAR_9); g_free(VAR_9); closedir(dir); return -2; } direntry->size=cpu_to_le32(S_ISDIR(VAR_10.st_mode)?0:VAR_10.st_size); if(!VAR_11 && !VAR_12 && (S_ISDIR(VAR_10.st_mode) || VAR_10.st_size)) { VAR_0->current_mapping = array_get_next(&(VAR_0->mapping)); VAR_0->current_mapping->begin=0; VAR_0->current_mapping->end=VAR_10.st_size; VAR_0->current_mapping->dir_index=VAR_0->directory.next-1; VAR_0->current_mapping->first_mapping_index = -1; if (S_ISDIR(VAR_10.st_mode)) { VAR_0->current_mapping->mode = MODE_DIRECTORY; VAR_0->current_mapping->info.dir.parent_mapping_index =
VAR_1; } else { VAR_0->current_mapping->mode = MODE_UNDEFINED; VAR_0->current_mapping->info.file.offset = 0; } VAR_0->current_mapping->path=VAR_9; VAR_0->current_mapping->read_only =
(VAR_10.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0; } else { g_free(VAR_9); } } closedir(dir); while(VAR_0->directory.next%(0x10*VAR_0->sectors_per_cluster)) { direntry_t* direntry=array_get_next(&(VAR_0->directory)); memset(direntry,0,sizeof(direntry_t)); } #define ROOT_ENTRIES (0x02 * 0x10 * VAR_0->sectors_per_cluster)
if (VAR_1 == 0 && VAR_0->directory.next < ROOT_ENTRIES) { int VAR_13 = VAR_0->directory.next; array_ensure_allocated(&(VAR_0->directory), ROOT_ENTRIES - 1); VAR_0->directory.next = ROOT_ENTRIES; memset(array_get(&(VAR_0->directory), VAR_13), 0,
(ROOT_ENTRIES - VAR_13) * sizeof(direntry_t)); } mapping = array_get(&(VAR_0->mapping), VAR_1); VAR_3 += (VAR_0->directory.next - mapping->info.dir.first_dir_index)
* 0x20 / VAR_0->cluster_size; mapping->end = VAR_3; direntry = array_get(&(VAR_0->directory), mapping->dir_index); set_begin_of_direntry(direntry, mapping->begin); return 0; }