static int check_directory_consistency(BDRVVVFATState *s,

	int cluster_num, const char* path)

{

    int ret = 0;

    unsigned char* cluster = qemu_malloc(s->cluster_size);

    direntry_t* direntries = (direntry_t*)cluster;

    mapping_t* mapping = find_mapping_for_cluster(s, cluster_num);



    long_file_name lfn;

    int path_len = strlen(path);

    char path2[PATH_MAX];



    assert(path_len < PATH_MAX); /* len was tested before! */

    pstrcpy(path2, sizeof(path2), path);

    path2[path_len] = '/';

    path2[path_len + 1] = '\0';



    if (mapping) {

	const char* basename = get_basename(mapping->path);

	const char* basename2 = get_basename(path);



	assert(mapping->mode & MODE_DIRECTORY);



	assert(mapping->mode & MODE_DELETED);

	mapping->mode &= ~MODE_DELETED;



	if (strcmp(basename, basename2))

	    schedule_rename(s, cluster_num, strdup(path));

    } else

	/* new directory */

	schedule_mkdir(s, cluster_num, strdup(path));



    lfn_init(&lfn);

    do {

	int i;

	int subret = 0;



	ret++;



	if (s->used_clusters[cluster_num] & USED_ANY) {

	    fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);

	    return 0;

	}

	s->used_clusters[cluster_num] = USED_DIRECTORY;



DLOG(fprintf(stderr, "read cluster %d (sector %d)\n", (int)cluster_num, (int)cluster2sector(s, cluster_num)));

	subret = vvfat_read(s->bs, cluster2sector(s, cluster_num), cluster,

		s->sectors_per_cluster);

	if (subret) {

	    fprintf(stderr, "Error fetching direntries\n");

	fail:

	    free(cluster);

	    return 0;

	}



	for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {

	    int cluster_count = 0;



DLOG(fprintf(stderr, "check direntry %d: \n", i); print_direntry(direntries + i));

	    if (is_volume_label(direntries + i) || is_dot(direntries + i) ||

		    is_free(direntries + i))

		continue;



	    subret = parse_long_name(&lfn, direntries + i);

	    if (subret < 0) {

		fprintf(stderr, "Error in long name\n");

		goto fail;

	    }

	    if (subret == 0 || is_free(direntries + i))

		continue;



	    if (fat_chksum(direntries+i) != lfn.checksum) {

		subret = parse_short_name(s, &lfn, direntries + i);

		if (subret < 0) {

		    fprintf(stderr, "Error in short name (%d)\n", subret);

		    goto fail;

		}

		if (subret > 0 || !strcmp((char*)lfn.name, ".")

			|| !strcmp((char*)lfn.name, ".."))

		    continue;

	    }

	    lfn.checksum = 0x100; /* cannot use long name twice */



	    if (path_len + 1 + lfn.len >= PATH_MAX) {

		fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);

		goto fail;

	    }

            pstrcpy(path2 + path_len + 1, sizeof(path2) - path_len - 1,

                    (char*)lfn.name);



	    if (is_directory(direntries + i)) {

		if (begin_of_direntry(direntries + i) == 0) {

		    DLOG(fprintf(stderr, "invalid begin for directory: %s\n", path2); print_direntry(direntries + i));

		    goto fail;

		}

		cluster_count = check_directory_consistency(s,

			begin_of_direntry(direntries + i), path2);

		if (cluster_count == 0) {

		    DLOG(fprintf(stderr, "problem in directory %s:\n", path2); print_direntry(direntries + i));

		    goto fail;

		}

	    } else if (is_file(direntries + i)) {

		/* check file size with FAT */

		cluster_count = get_cluster_count_for_direntry(s, direntries + i, path2);

		if (cluster_count !=

			(le32_to_cpu(direntries[i].size) + s->cluster_size

			 - 1) / s->cluster_size) {

		    DLOG(fprintf(stderr, "Cluster count mismatch\n"));

		    goto fail;

		}

	    } else

		assert(0); /* cluster_count = 0; */



	    ret += cluster_count;

	}



	cluster_num = modified_fat_get(s, cluster_num);

    } while(!fat_eof(s, cluster_num));



    free(cluster);

    return ret;

}

static int check_directory_consistency(BDRVVVFATState *s,

	int cluster_num, const char* path)

{

    int ret = 0;

    unsigned char* cluster = qemu_malloc(s->cluster_size);

    direntry_t* direntries = (direntry_t*)cluster;

    mapping_t* mapping = find_mapping_for_cluster(s, cluster_num);



    long_file_name lfn;

    int path_len = strlen(path);

    char path2[PATH_MAX];



    assert(path_len < PATH_MAX); 

    pstrcpy(path2, sizeof(path2), path);

    path2[path_len] = '/';

    path2[path_len + 1] = '\0';



    if (mapping) {

	const char* basename = get_basename(mapping->path);

	const char* basename2 = get_basename(path);



	assert(mapping->mode & MODE_DIRECTORY);



	assert(mapping->mode & MODE_DELETED);

	mapping->mode &= ~MODE_DELETED;



	if (strcmp(basename, basename2))

	    schedule_rename(s, cluster_num, strdup(path));

    } else

	

	schedule_mkdir(s, cluster_num, strdup(path));



    lfn_init(&lfn);

    do {

	int i;

	int subret = 0;



	ret++;



	if (s->used_clusters[cluster_num] & USED_ANY) {

	    fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);

	    return 0;

	}

	s->used_clusters[cluster_num] = USED_DIRECTORY;



DLOG(fprintf(stderr, "read cluster %d (sector %d)\n", (int)cluster_num, (int)cluster2sector(s, cluster_num)));

	subret = vvfat_read(s->bs, cluster2sector(s, cluster_num), cluster,

		s->sectors_per_cluster);

	if (subret) {

	    fprintf(stderr, "Error fetching direntries\n");

	fail:

	    free(cluster);

	    return 0;

	}



	for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {

	    int cluster_count = 0;



DLOG(fprintf(stderr, "check direntry %d: \n", i); print_direntry(direntries + i));

	    if (is_volume_label(direntries + i) || is_dot(direntries + i) ||

		    is_free(direntries + i))

		continue;



	    subret = parse_long_name(&lfn, direntries + i);

	    if (subret < 0) {

		fprintf(stderr, "Error in long name\n");

		goto fail;

	    }

	    if (subret == 0 || is_free(direntries + i))

		continue;



	    if (fat_chksum(direntries+i) != lfn.checksum) {

		subret = parse_short_name(s, &lfn, direntries + i);

		if (subret < 0) {

		    fprintf(stderr, "Error in short name (%d)\n", subret);

		    goto fail;

		}

		if (subret > 0 || !strcmp((char*)lfn.name, ".")

			|| !strcmp((char*)lfn.name, ".."))

		    continue;

	    }

	    lfn.checksum = 0x100; 



	    if (path_len + 1 + lfn.len >= PATH_MAX) {

		fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);

		goto fail;

	    }

            pstrcpy(path2 + path_len + 1, sizeof(path2) - path_len - 1,

                    (char*)lfn.name);



	    if (is_directory(direntries + i)) {

		if (begin_of_direntry(direntries + i) == 0) {

		    DLOG(fprintf(stderr, "invalid begin for directory: %s\n", path2); print_direntry(direntries + i));

		    goto fail;

		}

		cluster_count = check_directory_consistency(s,

			begin_of_direntry(direntries + i), path2);

		if (cluster_count == 0) {

		    DLOG(fprintf(stderr, "problem in directory %s:\n", path2); print_direntry(direntries + i));

		    goto fail;

		}

	    } else if (is_file(direntries + i)) {

		

		cluster_count = get_cluster_count_for_direntry(s, direntries + i, path2);

		if (cluster_count !=

			(le32_to_cpu(direntries[i].size) + s->cluster_size

			 - 1) / s->cluster_size) {

		    DLOG(fprintf(stderr, "Cluster count mismatch\n"));

		    goto fail;

		}

	    } else

		assert(0); 



	    ret += cluster_count;

	}



	cluster_num = modified_fat_get(s, cluster_num);

    } while(!fat_eof(s, cluster_num));



    free(cluster);

    return ret;

}

	    schedule_rename(s, cluster_num, strdup(path)); 	schedule_mkdir(s, cluster_num, strdup(path));
static int FUNC_0(BDRVVVFATState *VAR_0,

	int VAR_1, const char* VAR_2)

{

    int VAR_3 = 0;

    unsigned char* VAR_4 = qemu_malloc(VAR_0->cluster_size);

    direntry_t* direntries = (direntry_t*)VAR_4;

    mapping_t* mapping = find_mapping_for_cluster(VAR_0, VAR_1);



    long_file_name lfn;

    int VAR_5 = strlen(VAR_2);

    char VAR_6[PATH_MAX];



    assert(VAR_5 < PATH_MAX); 

    pstrcpy(VAR_6, sizeof(VAR_6), VAR_2);

    VAR_6[VAR_5] = '/';

    VAR_6[VAR_5 + 1] = '\0';



    if (mapping) {

	const char* VAR_7 = get_basename(mapping->VAR_2);

	const char* VAR_8 = get_basename(VAR_2);



	assert(mapping->mode & MODE_DIRECTORY);



	assert(mapping->mode & MODE_DELETED);

	mapping->mode &= ~MODE_DELETED;



	if (strcmp(VAR_7, VAR_8))

	    schedule_rename(VAR_0, VAR_1, strdup(VAR_2));

    } else

	

	schedule_mkdir(VAR_0, VAR_1, strdup(VAR_2));



    lfn_init(&lfn);

    do {

	int VAR_9;

	int VAR_10 = 0;



	VAR_3++;



	if (VAR_0->used_clusters[VAR_1] & USED_ANY) {

	    fprintf(stderr, "VAR_4 %d used more than once\n", (int)VAR_1);

	    return 0;

	}

	VAR_0->used_clusters[VAR_1] = USED_DIRECTORY;



DLOG(fprintf(stderr, "read VAR_4 %d (sector %d)\n", (int)VAR_1, (int)cluster2sector(VAR_0, VAR_1)));

	VAR_10 = vvfat_read(VAR_0->bs, cluster2sector(VAR_0, VAR_1), VAR_4,

		VAR_0->sectors_per_cluster);

	if (VAR_10) {

	    fprintf(stderr, "Error fetching direntries\n");

	fail:

	    free(VAR_4);

	    return 0;

	}



	for (VAR_9 = 0; VAR_9 < 0x10 * VAR_0->sectors_per_cluster; VAR_9++) {

	    int cluster_count = 0;



DLOG(fprintf(stderr, "check direntry %d: \n", VAR_9); print_direntry(direntries + VAR_9));

	    if (is_volume_label(direntries + VAR_9) || is_dot(direntries + VAR_9) ||

		    is_free(direntries + VAR_9))

		continue;



	    VAR_10 = parse_long_name(&lfn, direntries + VAR_9);

	    if (VAR_10 < 0) {

		fprintf(stderr, "Error in long name\n");

		goto fail;

	    }

	    if (VAR_10 == 0 || is_free(direntries + VAR_9))

		continue;



	    if (fat_chksum(direntries+VAR_9) != lfn.checksum) {

		VAR_10 = parse_short_name(VAR_0, &lfn, direntries + VAR_9);

		if (VAR_10 < 0) {

		    fprintf(stderr, "Error in short name (%d)\n", VAR_10);

		    goto fail;

		}

		if (VAR_10 > 0 || !strcmp((char*)lfn.name, ".")

			|| !strcmp((char*)lfn.name, ".."))

		    continue;

	    }

	    lfn.checksum = 0x100; 



	    if (VAR_5 + 1 + lfn.len >= PATH_MAX) {

		fprintf(stderr, "Name too long: %VAR_0/%VAR_0\n", VAR_2, lfn.name);

		goto fail;

	    }

            pstrcpy(VAR_6 + VAR_5 + 1, sizeof(VAR_6) - VAR_5 - 1,

                    (char*)lfn.name);



	    if (is_directory(direntries + VAR_9)) {

		if (begin_of_direntry(direntries + VAR_9) == 0) {

		    DLOG(fprintf(stderr, "invalid begin for directory: %VAR_0\n", VAR_6); print_direntry(direntries + VAR_9));

		    goto fail;

		}

		cluster_count = FUNC_0(VAR_0,

			begin_of_direntry(direntries + VAR_9), VAR_6);

		if (cluster_count == 0) {

		    DLOG(fprintf(stderr, "problem in directory %VAR_0:\n", VAR_6); print_direntry(direntries + VAR_9));

		    goto fail;

		}

	    } else if (is_file(direntries + VAR_9)) {

		

		cluster_count = get_cluster_count_for_direntry(VAR_0, direntries + VAR_9, VAR_6);

		if (cluster_count !=

			(le32_to_cpu(direntries[VAR_9].size) + VAR_0->cluster_size

			 - 1) / VAR_0->cluster_size) {

		    DLOG(fprintf(stderr, "Cluster count mismatch\n"));

		    goto fail;

		}

	    } else

		assert(0); 



	    VAR_3 += cluster_count;

	}



	VAR_1 = modified_fat_get(VAR_0, VAR_1);

    } while(!fat_eof(VAR_0, VAR_1));



    free(VAR_4);

    return VAR_3;

}

static int FUNC_0(BDRVVVFATState *VAR_0,
int VAR_1, const char* VAR_2)
{ int VAR_3 = 0; unsigned char* VAR_4 = qemu_malloc(VAR_0->cluster_size); direntry_t* direntries = (direntry_t*)VAR_4; mapping_t* mapping = find_mapping_for_cluster(VAR_0, VAR_1); long_file_name lfn; int VAR_5 = strlen(VAR_2); char VAR_6[PATH_MAX]; assert(VAR_5 < PATH_MAX); pstrcpy(VAR_6, sizeof(VAR_6), VAR_2); VAR_6[VAR_5] = '/'; VAR_6[VAR_5 + 1] = '\0'; if (mapping) { const char* VAR_7 = get_basename(mapping->VAR_2); const char* VAR_8 = get_basename(VAR_2); assert(mapping->mode & MODE_DIRECTORY); assert(mapping->mode & MODE_DELETED); mapping->mode &= ~MODE_DELETED; if (strcmp(VAR_7, VAR_8))
schedule_rename(VAR_0, VAR_1, strdup(VAR_2)); } else schedule_mkdir(VAR_0, VAR_1, strdup(VAR_2)); lfn_init(&lfn); do { int VAR_9; int VAR_10 = 0; VAR_3++; if (VAR_0->used_clusters[VAR_1] & USED_ANY) { fprintf(stderr, "VAR_4 %d used more than once\n", (int)VAR_1); return 0; } VAR_0->used_clusters[VAR_1] = USED_DIRECTORY; DLOG(fprintf(stderr, "read VAR_4 %d (sector %d)\n", (int)VAR_1, (int)cluster2sector(VAR_0, VAR_1))); VAR_10 = vvfat_read(VAR_0->bs, cluster2sector(VAR_0, VAR_1), VAR_4,
VAR_0->sectors_per_cluster); if (VAR_10) { fprintf(stderr, "Error fetching direntries\n"); fail:
free(VAR_4); return 0; } for (VAR_9 = 0; VAR_9 < 0x10 * VAR_0->sectors_per_cluster; VAR_9++) { int cluster_count = 0; DLOG(fprintf(stderr, "check direntry %d: \n", VAR_9); print_direntry(direntries + VAR_9)); if (is_volume_label(direntries + VAR_9) || is_dot(direntries + VAR_9) ||
is_free(direntries + VAR_9))
continue; VAR_10 = parse_long_name(&lfn, direntries + VAR_9); if (VAR_10 < 0) { fprintf(stderr, "Error in long name\n"); goto fail; } if (VAR_10 == 0 || is_free(direntries + VAR_9))
continue; if (fat_chksum(direntries+VAR_9) != lfn.checksum) { VAR_10 = parse_short_name(VAR_0, &lfn, direntries + VAR_9); if (VAR_10 < 0) { fprintf(stderr, "Error in short name (%d)\n", VAR_10); goto fail; } if (VAR_10 > 0 || !strcmp((char*)lfn.name, ".")
|| !strcmp((char*)lfn.name, ".."))
continue; } lfn.checksum = 0x100; if (VAR_5 + 1 + lfn.len >= PATH_MAX) { fprintf(stderr, "Name too long: %VAR_0/%VAR_0\n", VAR_2, lfn.name); goto fail; } pstrcpy(VAR_6 + VAR_5 + 1, sizeof(VAR_6) - VAR_5 - 1,
(char*)lfn.name); if (is_directory(direntries + VAR_9)) { if (begin_of_direntry(direntries + VAR_9) == 0) { DLOG(fprintf(stderr, "invalid begin for directory: %VAR_0\n", VAR_6); print_direntry(direntries + VAR_9)); goto fail; } cluster_count = FUNC_0(VAR_0,
begin_of_direntry(direntries + VAR_9), VAR_6); if (cluster_count == 0) { DLOG(fprintf(stderr, "problem in directory %VAR_0:\n", VAR_6); print_direntry(direntries + VAR_9)); goto fail; } } else if (is_file(direntries + VAR_9)) { cluster_count = get_cluster_count_for_direntry(VAR_0, direntries + VAR_9, VAR_6); if (cluster_count !=
(le32_to_cpu(direntries[VAR_9].size) + VAR_0->cluster_size
- 1) / VAR_0->cluster_size) { DLOG(fprintf(stderr, "Cluster count mismatch\n")); goto fail; } } else assert(0); VAR_3 += cluster_count; } VAR_1 = modified_fat_get(VAR_0, VAR_1); } while(!fat_eof(VAR_0, VAR_1)); free(VAR_4); return VAR_3; }