symbian-qemu-0.9.1-12/qemu-symbian-svp/block-vvfat.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /* vim:set shiftwidth=4 ts=8: */
       
     2 /*
       
     3  * QEMU Block driver for virtual VFAT (shadows a local directory)
       
     4  *
       
     5  * Copyright (c) 2004,2005 Johannes E. Schindelin
       
     6  *
       
     7  * Permission is hereby granted, free of charge, to any person obtaining a copy
       
     8  * of this software and associated documentation files (the "Software"), to deal
       
     9  * in the Software without restriction, including without limitation the rights
       
    10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       
    11  * copies of the Software, and to permit persons to whom the Software is
       
    12  * furnished to do so, subject to the following conditions:
       
    13  *
       
    14  * The above copyright notice and this permission notice shall be included in
       
    15  * all copies or substantial portions of the Software.
       
    16  *
       
    17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
    18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       
    19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
       
    20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       
    21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
       
    22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
       
    23  * THE SOFTWARE.
       
    24  */
       
    25 #include <sys/stat.h>
       
    26 #include <dirent.h>
       
    27 #include <assert.h>
       
    28 #include "qemu-common.h"
       
    29 #include "block_int.h"
       
    30 
       
    31 #ifndef S_IWGRP
       
    32 #define S_IWGRP 0
       
    33 #endif
       
    34 #ifndef S_IWOTH
       
    35 #define S_IWOTH 0
       
    36 #endif
       
    37 
       
    38 /* TODO: add ":bootsector=blabla.img:" */
       
    39 /* LATER TODO: add automatic boot sector generation from
       
    40     BOOTEASY.ASM and Ranish Partition Manager
       
    41     Note that DOS assumes the system files to be the first files in the
       
    42     file system (test if the boot sector still relies on that fact)! */
       
    43 /* MAYBE TODO: write block-visofs.c */
       
    44 /* TODO: call try_commit() only after a timeout */
       
    45 
       
    46 /* #define DEBUG */
       
    47 
       
    48 #ifdef DEBUG
       
    49 
       
    50 #define DLOG(a) a
       
    51 
       
    52 #undef stderr
       
    53 #define stderr STDERR
       
    54 FILE* stderr = NULL;
       
    55 
       
    56 static void checkpoint(void);
       
    57 
       
    58 #ifdef __MINGW32__
       
    59 void nonono(const char* file, int line, const char* msg) {
       
    60     fprintf(stderr, "Nonono! %s:%d %s\n", file, line, msg);
       
    61     exit(-5);
       
    62 }
       
    63 #undef assert
       
    64 #define assert(a) do {if (!(a)) nonono(__FILE__, __LINE__, #a);}while(0)
       
    65 #endif
       
    66 
       
    67 #else
       
    68 
       
    69 #define DLOG(a)
       
    70 
       
    71 #endif
       
    72 
       
    73 /* dynamic array functions */
       
    74 typedef struct array_t {
       
    75     char* pointer;
       
    76     unsigned int size,next,item_size;
       
    77 } array_t;
       
    78 
       
    79 static inline void array_init(array_t* array,unsigned int item_size)
       
    80 {
       
    81     array->pointer=0;
       
    82     array->size=0;
       
    83     array->next=0;
       
    84     array->item_size=item_size;
       
    85 }
       
    86 
       
    87 static inline void array_free(array_t* array)
       
    88 {
       
    89     if(array->pointer)
       
    90         free(array->pointer);
       
    91     array->size=array->next=0;
       
    92 }
       
    93 
       
    94 /* does not automatically grow */
       
    95 static inline void* array_get(array_t* array,unsigned int index) {
       
    96     assert(index < array->next);
       
    97     return array->pointer + index * array->item_size;
       
    98 }
       
    99 
       
   100 static inline int array_ensure_allocated(array_t* array, int index)
       
   101 {
       
   102     if((index + 1) * array->item_size > array->size) {
       
   103 	int new_size = (index + 32) * array->item_size;
       
   104 	array->pointer = qemu_realloc(array->pointer, new_size);
       
   105 	if (!array->pointer)
       
   106 	    return -1;
       
   107 	array->size = new_size;
       
   108 	array->next = index + 1;
       
   109     }
       
   110 
       
   111     return 0;
       
   112 }
       
   113 
       
   114 static inline void* array_get_next(array_t* array) {
       
   115     unsigned int next = array->next;
       
   116     void* result;
       
   117 
       
   118     if (array_ensure_allocated(array, next) < 0)
       
   119 	return NULL;
       
   120 
       
   121     array->next = next + 1;
       
   122     result = array_get(array, next);
       
   123 
       
   124     return result;
       
   125 }
       
   126 
       
   127 static inline void* array_insert(array_t* array,unsigned int index,unsigned int count) {
       
   128     if((array->next+count)*array->item_size>array->size) {
       
   129 	int increment=count*array->item_size;
       
   130 	array->pointer=qemu_realloc(array->pointer,array->size+increment);
       
   131 	if(!array->pointer)
       
   132 	    return 0;
       
   133 	array->size+=increment;
       
   134     }
       
   135     memmove(array->pointer+(index+count)*array->item_size,
       
   136 		array->pointer+index*array->item_size,
       
   137 		(array->next-index)*array->item_size);
       
   138     array->next+=count;
       
   139     return array->pointer+index*array->item_size;
       
   140 }
       
   141 
       
   142 /* this performs a "roll", so that the element which was at index_from becomes
       
   143  * index_to, but the order of all other elements is preserved. */
       
   144 static inline int array_roll(array_t* array,int index_to,int index_from,int count)
       
   145 {
       
   146     char* buf;
       
   147     char* from;
       
   148     char* to;
       
   149     int is;
       
   150 
       
   151     if(!array ||
       
   152 	    index_to<0 || index_to>=array->next ||
       
   153 	    index_from<0 || index_from>=array->next)
       
   154 	return -1;
       
   155 
       
   156     if(index_to==index_from)
       
   157 	return 0;
       
   158 
       
   159     is=array->item_size;
       
   160     from=array->pointer+index_from*is;
       
   161     to=array->pointer+index_to*is;
       
   162     buf=malloc(is*count);
       
   163     memcpy(buf,from,is*count);
       
   164 
       
   165     if(index_to<index_from)
       
   166 	memmove(to+is*count,to,from-to);
       
   167     else
       
   168 	memmove(from,from+is*count,to-from);
       
   169 
       
   170     memcpy(to,buf,is*count);
       
   171 
       
   172     free(buf);
       
   173 
       
   174     return 0;
       
   175 }
       
   176 
       
   177 static inline int array_remove_slice(array_t* array,int index, int count)
       
   178 {
       
   179     assert(index >=0);
       
   180     assert(count > 0);
       
   181     assert(index + count <= array->next);
       
   182     if(array_roll(array,array->next-1,index,count))
       
   183 	return -1;
       
   184     array->next -= count;
       
   185     return 0;
       
   186 }
       
   187 
       
   188 static int array_remove(array_t* array,int index)
       
   189 {
       
   190     return array_remove_slice(array, index, 1);
       
   191 }
       
   192 
       
   193 /* return the index for a given member */
       
   194 static int array_index(array_t* array, void* pointer)
       
   195 {
       
   196     size_t offset = (char*)pointer - array->pointer;
       
   197     assert((offset % array->item_size) == 0);
       
   198     assert(offset/array->item_size < array->next);
       
   199     return offset/array->item_size;
       
   200 }
       
   201 
       
   202 /* These structures are used to fake a disk and the VFAT filesystem.
       
   203  * For this reason we need to use __attribute__((packed)). */
       
   204 
       
   205 typedef struct bootsector_t {
       
   206     uint8_t jump[3];
       
   207     uint8_t name[8];
       
   208     uint16_t sector_size;
       
   209     uint8_t sectors_per_cluster;
       
   210     uint16_t reserved_sectors;
       
   211     uint8_t number_of_fats;
       
   212     uint16_t root_entries;
       
   213     uint16_t total_sectors16;
       
   214     uint8_t media_type;
       
   215     uint16_t sectors_per_fat;
       
   216     uint16_t sectors_per_track;
       
   217     uint16_t number_of_heads;
       
   218     uint32_t hidden_sectors;
       
   219     uint32_t total_sectors;
       
   220     union {
       
   221         struct {
       
   222 	    uint8_t drive_number;
       
   223 	    uint8_t current_head;
       
   224 	    uint8_t signature;
       
   225 	    uint32_t id;
       
   226 	    uint8_t volume_label[11];
       
   227 	} __attribute__((packed)) fat16;
       
   228 	struct {
       
   229 	    uint32_t sectors_per_fat;
       
   230 	    uint16_t flags;
       
   231 	    uint8_t major,minor;
       
   232 	    uint32_t first_cluster_of_root_directory;
       
   233 	    uint16_t info_sector;
       
   234 	    uint16_t backup_boot_sector;
       
   235 	    uint16_t ignored;
       
   236 	} __attribute__((packed)) fat32;
       
   237     } u;
       
   238     uint8_t fat_type[8];
       
   239     uint8_t ignored[0x1c0];
       
   240     uint8_t magic[2];
       
   241 } __attribute__((packed)) bootsector_t;
       
   242 
       
   243 typedef struct {
       
   244     uint8_t head;
       
   245     uint8_t sector;
       
   246     uint8_t cylinder;
       
   247 } mbr_chs_t;
       
   248 
       
   249 typedef struct partition_t {
       
   250     uint8_t attributes; /* 0x80 = bootable */
       
   251     mbr_chs_t start_CHS;
       
   252     uint8_t   fs_type; /* 0x1 = FAT12, 0x6 = FAT16, 0xe = FAT16_LBA, 0xb = FAT32, 0xc = FAT32_LBA */
       
   253     mbr_chs_t end_CHS;
       
   254     uint32_t start_sector_long;
       
   255     uint32_t length_sector_long;
       
   256 } __attribute__((packed)) partition_t;
       
   257 
       
   258 typedef struct mbr_t {
       
   259     uint8_t ignored[0x1b8];
       
   260     uint32_t nt_id;
       
   261     uint8_t ignored2[2];
       
   262     partition_t partition[4];
       
   263     uint8_t magic[2];
       
   264 } __attribute__((packed)) mbr_t;
       
   265 
       
   266 typedef struct direntry_t {
       
   267     uint8_t name[8];
       
   268     uint8_t extension[3];
       
   269     uint8_t attributes;
       
   270     uint8_t reserved[2];
       
   271     uint16_t ctime;
       
   272     uint16_t cdate;
       
   273     uint16_t adate;
       
   274     uint16_t begin_hi;
       
   275     uint16_t mtime;
       
   276     uint16_t mdate;
       
   277     uint16_t begin;
       
   278     uint32_t size;
       
   279 } __attribute__((packed)) direntry_t;
       
   280 
       
   281 /* this structure are used to transparently access the files */
       
   282 
       
   283 typedef struct mapping_t {
       
   284     /* begin is the first cluster, end is the last+1 */
       
   285     uint32_t begin,end;
       
   286     /* as s->directory is growable, no pointer may be used here */
       
   287     unsigned int dir_index;
       
   288     /* the clusters of a file may be in any order; this points to the first */
       
   289     int first_mapping_index;
       
   290     union {
       
   291 	/* offset is
       
   292 	 * - the offset in the file (in clusters) for a file, or
       
   293 	 * - the next cluster of the directory for a directory, and
       
   294 	 * - the address of the buffer for a faked entry
       
   295 	 */
       
   296 	struct {
       
   297 	    uint32_t offset;
       
   298 	} file;
       
   299 	struct {
       
   300 	    int parent_mapping_index;
       
   301 	    int first_dir_index;
       
   302 	} dir;
       
   303     } info;
       
   304     /* path contains the full path, i.e. it always starts with s->path */
       
   305     char* path;
       
   306 
       
   307     enum { MODE_UNDEFINED = 0, MODE_NORMAL = 1, MODE_MODIFIED = 2,
       
   308 	MODE_DIRECTORY = 4, MODE_FAKED = 8,
       
   309 	MODE_DELETED = 16, MODE_RENAMED = 32 } mode;
       
   310     int read_only;
       
   311 } mapping_t;
       
   312 
       
   313 #ifdef DEBUG
       
   314 static void print_direntry(const struct direntry_t*);
       
   315 static void print_mapping(const struct mapping_t* mapping);
       
   316 #endif
       
   317 
       
   318 /* here begins the real VVFAT driver */
       
   319 
       
   320 typedef struct BDRVVVFATState {
       
   321     BlockDriverState* bs; /* pointer to parent */
       
   322     unsigned int first_sectors_number; /* 1 for a single partition, 0x40 for a disk with partition table */
       
   323     unsigned char first_sectors[0x40*0x200];
       
   324 
       
   325     int fat_type; /* 16 or 32 */
       
   326     array_t fat,directory,mapping;
       
   327 
       
   328     unsigned int cluster_size;
       
   329     unsigned int sectors_per_cluster;
       
   330     unsigned int sectors_per_fat;
       
   331     unsigned int sectors_of_root_directory;
       
   332     uint32_t last_cluster_of_root_directory;
       
   333     unsigned int faked_sectors; /* how many sectors are faked before file data */
       
   334     uint32_t sector_count; /* total number of sectors of the partition */
       
   335     uint32_t cluster_count; /* total number of clusters of this partition */
       
   336     uint32_t max_fat_value;
       
   337 
       
   338     int current_fd;
       
   339     mapping_t* current_mapping;
       
   340     unsigned char* cluster; /* points to current cluster */
       
   341     unsigned char* cluster_buffer; /* points to a buffer to hold temp data */
       
   342     unsigned int current_cluster;
       
   343 
       
   344     /* write support */
       
   345     BlockDriverState* write_target;
       
   346     char* qcow_filename;
       
   347     BlockDriverState* qcow;
       
   348     void* fat2;
       
   349     char* used_clusters;
       
   350     array_t commits;
       
   351     const char* path;
       
   352     int downcase_short_names;
       
   353 } BDRVVVFATState;
       
   354 
       
   355 /* take the sector position spos and convert it to Cylinder/Head/Sector position
       
   356  * if the position is outside the specified geometry, fill maximum value for CHS
       
   357  * and return 1 to signal overflow.
       
   358  */
       
   359 static int sector2CHS(BlockDriverState* bs, mbr_chs_t * chs, int spos){
       
   360     int head,sector;
       
   361     sector   = spos % (bs->secs);  spos/= bs->secs;
       
   362     head     = spos % (bs->heads); spos/= bs->heads;
       
   363     if(spos >= bs->cyls){
       
   364         /* Overflow,
       
   365         it happens if 32bit sector positions are used, while CHS is only 24bit.
       
   366         Windows/Dos is said to take 1023/255/63 as nonrepresentable CHS */
       
   367         chs->head     = 0xFF;
       
   368         chs->sector   = 0xFF;
       
   369         chs->cylinder = 0xFF;
       
   370         return 1;
       
   371     }
       
   372     chs->head     = (uint8_t)head;
       
   373     chs->sector   = (uint8_t)( (sector+1) | ((spos>>8)<<6) );
       
   374     chs->cylinder = (uint8_t)spos;
       
   375     return 0;
       
   376 }
       
   377 
       
   378 static void init_mbr(BDRVVVFATState* s)
       
   379 {
       
   380     /* TODO: if the files mbr.img and bootsect.img exist, use them */
       
   381     mbr_t* real_mbr=(mbr_t*)s->first_sectors;
       
   382     partition_t* partition=&(real_mbr->partition[0]);
       
   383     int lba;
       
   384 
       
   385     memset(s->first_sectors,0,512);
       
   386 
       
   387     /* Win NT Disk Signature */
       
   388     real_mbr->nt_id= cpu_to_le32(0xbe1afdfa);
       
   389 
       
   390     partition->attributes=0x80; /* bootable */
       
   391 
       
   392     /* LBA is used when partition is outside the CHS geometry */
       
   393     lba = sector2CHS(s->bs, &partition->start_CHS, s->first_sectors_number-1);
       
   394     lba|= sector2CHS(s->bs, &partition->end_CHS,   s->sector_count);
       
   395 
       
   396     /*LBA partitions are identified only by start/length_sector_long not by CHS*/
       
   397     partition->start_sector_long =cpu_to_le32(s->first_sectors_number-1);
       
   398     partition->length_sector_long=cpu_to_le32(s->sector_count - s->first_sectors_number+1);
       
   399 
       
   400     /* FAT12/FAT16/FAT32 */
       
   401     /* DOS uses different types when partition is LBA,
       
   402        probably to prevent older versions from using CHS on them */
       
   403     partition->fs_type= s->fat_type==12 ? 0x1:
       
   404                         s->fat_type==16 ? (lba?0xe:0x06):
       
   405                          /*fat_tyoe==32*/ (lba?0xc:0x0b);
       
   406 
       
   407     real_mbr->magic[0]=0x55; real_mbr->magic[1]=0xaa;
       
   408 }
       
   409 
       
   410 /* direntry functions */
       
   411 
       
   412 /* dest is assumed to hold 258 bytes, and pads with 0xffff up to next multiple of 26 */
       
   413 static inline int short2long_name(char* dest,const char* src)
       
   414 {
       
   415     int i;
       
   416     int len;
       
   417     for(i=0;i<129 && src[i];i++) {
       
   418         dest[2*i]=src[i];
       
   419 	dest[2*i+1]=0;
       
   420     }
       
   421     len=2*i;
       
   422     dest[2*i]=dest[2*i+1]=0;
       
   423     for(i=2*i+2;(i%26);i++)
       
   424 	dest[i]=0xff;
       
   425     return len;
       
   426 }
       
   427 
       
   428 static inline direntry_t* create_long_filename(BDRVVVFATState* s,const char* filename)
       
   429 {
       
   430     char buffer[258];
       
   431     int length=short2long_name(buffer,filename),
       
   432         number_of_entries=(length+25)/26,i;
       
   433     direntry_t* entry;
       
   434 
       
   435     for(i=0;i<number_of_entries;i++) {
       
   436 	entry=array_get_next(&(s->directory));
       
   437 	entry->attributes=0xf;
       
   438 	entry->reserved[0]=0;
       
   439 	entry->begin=0;
       
   440 	entry->name[0]=(number_of_entries-i)|(i==0?0x40:0);
       
   441     }
       
   442     for(i=0;i<26*number_of_entries;i++) {
       
   443 	int offset=(i%26);
       
   444 	if(offset<10) offset=1+offset;
       
   445 	else if(offset<22) offset=14+offset-10;
       
   446 	else offset=28+offset-22;
       
   447 	entry=array_get(&(s->directory),s->directory.next-1-(i/26));
       
   448 	entry->name[offset]=buffer[i];
       
   449     }
       
   450     return array_get(&(s->directory),s->directory.next-number_of_entries);
       
   451 }
       
   452 
       
   453 static char is_free(const direntry_t* direntry)
       
   454 {
       
   455     return direntry->name[0]==0xe5 || direntry->name[0]==0x00;
       
   456 }
       
   457 
       
   458 static char is_volume_label(const direntry_t* direntry)
       
   459 {
       
   460     return direntry->attributes == 0x28;
       
   461 }
       
   462 
       
   463 static char is_long_name(const direntry_t* direntry)
       
   464 {
       
   465     return direntry->attributes == 0xf;
       
   466 }
       
   467 
       
   468 static char is_short_name(const direntry_t* direntry)
       
   469 {
       
   470     return !is_volume_label(direntry) && !is_long_name(direntry)
       
   471 	&& !is_free(direntry);
       
   472 }
       
   473 
       
   474 static char is_directory(const direntry_t* direntry)
       
   475 {
       
   476     return direntry->attributes & 0x10 && direntry->name[0] != 0xe5;
       
   477 }
       
   478 
       
   479 static inline char is_dot(const direntry_t* direntry)
       
   480 {
       
   481     return is_short_name(direntry) && direntry->name[0] == '.';
       
   482 }
       
   483 
       
   484 static char is_file(const direntry_t* direntry)
       
   485 {
       
   486     return is_short_name(direntry) && !is_directory(direntry);
       
   487 }
       
   488 
       
   489 static inline uint32_t begin_of_direntry(const direntry_t* direntry)
       
   490 {
       
   491     return le16_to_cpu(direntry->begin)|(le16_to_cpu(direntry->begin_hi)<<16);
       
   492 }
       
   493 
       
   494 static inline uint32_t filesize_of_direntry(const direntry_t* direntry)
       
   495 {
       
   496     return le32_to_cpu(direntry->size);
       
   497 }
       
   498 
       
   499 static void set_begin_of_direntry(direntry_t* direntry, uint32_t begin)
       
   500 {
       
   501     direntry->begin = cpu_to_le16(begin & 0xffff);
       
   502     direntry->begin_hi = cpu_to_le16((begin >> 16) & 0xffff);
       
   503 }
       
   504 
       
   505 /* fat functions */
       
   506 
       
   507 static inline uint8_t fat_chksum(const direntry_t* entry)
       
   508 {
       
   509     uint8_t chksum=0;
       
   510     int i;
       
   511 
       
   512     for(i=0;i<11;i++)
       
   513 	chksum=(((chksum&0xfe)>>1)|((chksum&0x01)?0x80:0))
       
   514 	    +(unsigned char)entry->name[i];
       
   515 
       
   516     return chksum;
       
   517 }
       
   518 
       
   519 /* if return_time==0, this returns the fat_date, else the fat_time */
       
   520 static uint16_t fat_datetime(time_t time,int return_time) {
       
   521     struct tm* t;
       
   522 #ifdef _WIN32
       
   523     t=localtime(&time); /* this is not thread safe */
       
   524 #else
       
   525     struct tm t1;
       
   526     t=&t1;
       
   527     localtime_r(&time,t);
       
   528 #endif
       
   529     if(return_time)
       
   530 	return cpu_to_le16((t->tm_sec/2)|(t->tm_min<<5)|(t->tm_hour<<11));
       
   531     return cpu_to_le16((t->tm_mday)|((t->tm_mon+1)<<5)|((t->tm_year-80)<<9));
       
   532 }
       
   533 
       
   534 static inline void fat_set(BDRVVVFATState* s,unsigned int cluster,uint32_t value)
       
   535 {
       
   536     if(s->fat_type==32) {
       
   537 	uint32_t* entry=array_get(&(s->fat),cluster);
       
   538 	*entry=cpu_to_le32(value);
       
   539     } else if(s->fat_type==16) {
       
   540 	uint16_t* entry=array_get(&(s->fat),cluster);
       
   541 	*entry=cpu_to_le16(value&0xffff);
       
   542     } else {
       
   543 	int offset = (cluster*3/2);
       
   544 	unsigned char* p = array_get(&(s->fat), offset);
       
   545         switch (cluster&1) {
       
   546 	case 0:
       
   547 		p[0] = value&0xff;
       
   548 		p[1] = (p[1]&0xf0) | ((value>>8)&0xf);
       
   549 		break;
       
   550 	case 1:
       
   551 		p[0] = (p[0]&0xf) | ((value&0xf)<<4);
       
   552 		p[1] = (value>>4);
       
   553 		break;
       
   554 	}
       
   555     }
       
   556 }
       
   557 
       
   558 static inline uint32_t fat_get(BDRVVVFATState* s,unsigned int cluster)
       
   559 {
       
   560     if(s->fat_type==32) {
       
   561 	uint32_t* entry=array_get(&(s->fat),cluster);
       
   562 	return le32_to_cpu(*entry);
       
   563     } else if(s->fat_type==16) {
       
   564 	uint16_t* entry=array_get(&(s->fat),cluster);
       
   565 	return le16_to_cpu(*entry);
       
   566     } else {
       
   567 	const uint8_t* x=(uint8_t*)(s->fat.pointer)+cluster*3/2;
       
   568 	return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
       
   569     }
       
   570 }
       
   571 
       
   572 static inline int fat_eof(BDRVVVFATState* s,uint32_t fat_entry)
       
   573 {
       
   574     if(fat_entry>s->max_fat_value-8)
       
   575 	return -1;
       
   576     return 0;
       
   577 }
       
   578 
       
   579 static inline void init_fat(BDRVVVFATState* s)
       
   580 {
       
   581     if (s->fat_type == 12) {
       
   582 	array_init(&(s->fat),1);
       
   583 	array_ensure_allocated(&(s->fat),
       
   584 		s->sectors_per_fat * 0x200 * 3 / 2 - 1);
       
   585     } else {
       
   586 	array_init(&(s->fat),(s->fat_type==32?4:2));
       
   587 	array_ensure_allocated(&(s->fat),
       
   588 		s->sectors_per_fat * 0x200 / s->fat.item_size - 1);
       
   589     }
       
   590     memset(s->fat.pointer,0,s->fat.size);
       
   591 
       
   592     switch(s->fat_type) {
       
   593 	case 12: s->max_fat_value=0xfff; break;
       
   594 	case 16: s->max_fat_value=0xffff; break;
       
   595 	case 32: s->max_fat_value=0x0fffffff; break;
       
   596 	default: s->max_fat_value=0; /* error... */
       
   597     }
       
   598 
       
   599 }
       
   600 
       
   601 /* TODO: in create_short_filename, 0xe5->0x05 is not yet handled! */
       
   602 /* TODO: in parse_short_filename, 0x05->0xe5 is not yet handled! */
       
   603 static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,
       
   604 	unsigned int directory_start, const char* filename, int is_dot)
       
   605 {
       
   606     int i,j,long_index=s->directory.next;
       
   607     direntry_t* entry=0;
       
   608     direntry_t* entry_long=0;
       
   609 
       
   610     if(is_dot) {
       
   611 	entry=array_get_next(&(s->directory));
       
   612 	memset(entry->name,0x20,11);
       
   613 	memcpy(entry->name,filename,strlen(filename));
       
   614 	return entry;
       
   615     }
       
   616 
       
   617     entry_long=create_long_filename(s,filename);
       
   618 
       
   619     i = strlen(filename);
       
   620     for(j = i - 1; j>0  && filename[j]!='.';j--);
       
   621     if (j > 0)
       
   622 	i = (j > 8 ? 8 : j);
       
   623     else if (i > 8)
       
   624 	i = 8;
       
   625 
       
   626     entry=array_get_next(&(s->directory));
       
   627     memset(entry->name,0x20,11);
       
   628     memcpy(entry->name, filename, i);
       
   629 
       
   630     if(j > 0)
       
   631 	for (i = 0; i < 3 && filename[j+1+i]; i++)
       
   632 	    entry->extension[i] = filename[j+1+i];
       
   633 
       
   634     /* upcase & remove unwanted characters */
       
   635     for(i=10;i>=0;i--) {
       
   636 	if(i==10 || i==7) for(;i>0 && entry->name[i]==' ';i--);
       
   637 	if(entry->name[i]<=' ' || entry->name[i]>0x7f
       
   638 		|| strchr(".*?<>|\":/\\[];,+='",entry->name[i]))
       
   639 	    entry->name[i]='_';
       
   640         else if(entry->name[i]>='a' && entry->name[i]<='z')
       
   641             entry->name[i]+='A'-'a';
       
   642     }
       
   643 
       
   644     /* mangle duplicates */
       
   645     while(1) {
       
   646 	direntry_t* entry1=array_get(&(s->directory),directory_start);
       
   647 	int j;
       
   648 
       
   649 	for(;entry1<entry;entry1++)
       
   650 	    if(!is_long_name(entry1) && !memcmp(entry1->name,entry->name,11))
       
   651 		break; /* found dupe */
       
   652 	if(entry1==entry) /* no dupe found */
       
   653 	    break;
       
   654 
       
   655 	/* use all 8 characters of name */
       
   656 	if(entry->name[7]==' ') {
       
   657 	    int j;
       
   658 	    for(j=6;j>0 && entry->name[j]==' ';j--)
       
   659 		entry->name[j]='~';
       
   660 	}
       
   661 
       
   662 	/* increment number */
       
   663 	for(j=7;j>0 && entry->name[j]=='9';j--)
       
   664 	    entry->name[j]='0';
       
   665 	if(j>0) {
       
   666 	    if(entry->name[j]<'0' || entry->name[j]>'9')
       
   667 	        entry->name[j]='0';
       
   668 	    else
       
   669 	        entry->name[j]++;
       
   670 	}
       
   671     }
       
   672 
       
   673     /* calculate checksum; propagate to long name */
       
   674     if(entry_long) {
       
   675         uint8_t chksum=fat_chksum(entry);
       
   676 
       
   677 	/* calculate anew, because realloc could have taken place */
       
   678 	entry_long=array_get(&(s->directory),long_index);
       
   679 	while(entry_long<entry && is_long_name(entry_long)) {
       
   680 	    entry_long->reserved[1]=chksum;
       
   681 	    entry_long++;
       
   682 	}
       
   683     }
       
   684 
       
   685     return entry;
       
   686 }
       
   687 
       
   688 /*
       
   689  * Read a directory. (the index of the corresponding mapping must be passed).
       
   690  */
       
   691 static int read_directory(BDRVVVFATState* s, int mapping_index)
       
   692 {
       
   693     mapping_t* mapping = array_get(&(s->mapping), mapping_index);
       
   694     direntry_t* direntry;
       
   695     const char* dirname = mapping->path;
       
   696     int first_cluster = mapping->begin;
       
   697     int parent_index = mapping->info.dir.parent_mapping_index;
       
   698     mapping_t* parent_mapping = (mapping_t*)
       
   699 	(parent_index >= 0 ? array_get(&(s->mapping), parent_index) : 0);
       
   700     int first_cluster_of_parent = parent_mapping ? parent_mapping->begin : -1;
       
   701 
       
   702     DIR* dir=opendir(dirname);
       
   703     struct dirent* entry;
       
   704     int i;
       
   705 
       
   706     assert(mapping->mode & MODE_DIRECTORY);
       
   707 
       
   708     if(!dir) {
       
   709 	mapping->end = mapping->begin;
       
   710 	return -1;
       
   711     }
       
   712 
       
   713     i = mapping->info.dir.first_dir_index =
       
   714 	    first_cluster == 0 ? 0 : s->directory.next;
       
   715 
       
   716     /* actually read the directory, and allocate the mappings */
       
   717     while((entry=readdir(dir))) {
       
   718 	unsigned int length=strlen(dirname)+2+strlen(entry->d_name);
       
   719         char* buffer;
       
   720 	direntry_t* direntry;
       
   721         struct stat st;
       
   722 	int is_dot=!strcmp(entry->d_name,".");
       
   723 	int is_dotdot=!strcmp(entry->d_name,"..");
       
   724 
       
   725 	if(first_cluster == 0 && (is_dotdot || is_dot))
       
   726 	    continue;
       
   727 
       
   728 	buffer=(char*)malloc(length);
       
   729 	assert(buffer);
       
   730 	snprintf(buffer,length,"%s/%s",dirname,entry->d_name);
       
   731 
       
   732 	if(stat(buffer,&st)<0) {
       
   733 	    free(buffer);
       
   734             continue;
       
   735 	}
       
   736 
       
   737 	/* create directory entry for this file */
       
   738 	direntry=create_short_and_long_name(s, i, entry->d_name,
       
   739 		is_dot || is_dotdot);
       
   740 	direntry->attributes=(S_ISDIR(st.st_mode)?0x10:0x20);
       
   741 	direntry->reserved[0]=direntry->reserved[1]=0;
       
   742 	direntry->ctime=fat_datetime(st.st_ctime,1);
       
   743 	direntry->cdate=fat_datetime(st.st_ctime,0);
       
   744 	direntry->adate=fat_datetime(st.st_atime,0);
       
   745 	direntry->begin_hi=0;
       
   746 	direntry->mtime=fat_datetime(st.st_mtime,1);
       
   747 	direntry->mdate=fat_datetime(st.st_mtime,0);
       
   748 	if(is_dotdot)
       
   749 	    set_begin_of_direntry(direntry, first_cluster_of_parent);
       
   750 	else if(is_dot)
       
   751 	    set_begin_of_direntry(direntry, first_cluster);
       
   752 	else
       
   753 	    direntry->begin=0; /* do that later */
       
   754         if (st.st_size > 0x7fffffff) {
       
   755 	    fprintf(stderr, "File %s is larger than 2GB\n", buffer);
       
   756 	    free(buffer);
       
   757 	    return -2;
       
   758         }
       
   759 	direntry->size=cpu_to_le32(S_ISDIR(st.st_mode)?0:st.st_size);
       
   760 
       
   761 	/* create mapping for this file */
       
   762 	if(!is_dot && !is_dotdot && (S_ISDIR(st.st_mode) || st.st_size)) {
       
   763 	    s->current_mapping=(mapping_t*)array_get_next(&(s->mapping));
       
   764 	    s->current_mapping->begin=0;
       
   765 	    s->current_mapping->end=st.st_size;
       
   766 	    /*
       
   767 	     * we get the direntry of the most recent direntry, which
       
   768 	     * contains the short name and all the relevant information.
       
   769 	     */
       
   770 	    s->current_mapping->dir_index=s->directory.next-1;
       
   771 	    s->current_mapping->first_mapping_index = -1;
       
   772 	    if (S_ISDIR(st.st_mode)) {
       
   773 		s->current_mapping->mode = MODE_DIRECTORY;
       
   774 		s->current_mapping->info.dir.parent_mapping_index =
       
   775 		    mapping_index;
       
   776 	    } else {
       
   777 		s->current_mapping->mode = MODE_UNDEFINED;
       
   778 		s->current_mapping->info.file.offset = 0;
       
   779 	    }
       
   780 	    s->current_mapping->path=buffer;
       
   781 	    s->current_mapping->read_only =
       
   782 		(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0;
       
   783 	}
       
   784     }
       
   785     closedir(dir);
       
   786 
       
   787     /* fill with zeroes up to the end of the cluster */
       
   788     while(s->directory.next%(0x10*s->sectors_per_cluster)) {
       
   789 	direntry_t* direntry=array_get_next(&(s->directory));
       
   790 	memset(direntry,0,sizeof(direntry_t));
       
   791     }
       
   792 
       
   793 /* TODO: if there are more entries, bootsector has to be adjusted! */
       
   794 #define ROOT_ENTRIES (0x02 * 0x10 * s->sectors_per_cluster)
       
   795     if (mapping_index == 0 && s->directory.next < ROOT_ENTRIES) {
       
   796 	/* root directory */
       
   797 	int cur = s->directory.next;
       
   798 	array_ensure_allocated(&(s->directory), ROOT_ENTRIES - 1);
       
   799 	memset(array_get(&(s->directory), cur), 0,
       
   800 		(ROOT_ENTRIES - cur) * sizeof(direntry_t));
       
   801     }
       
   802 
       
   803      /* reget the mapping, since s->mapping was possibly realloc()ed */
       
   804     mapping = (mapping_t*)array_get(&(s->mapping), mapping_index);
       
   805     first_cluster += (s->directory.next - mapping->info.dir.first_dir_index)
       
   806 	* 0x20 / s->cluster_size;
       
   807     mapping->end = first_cluster;
       
   808 
       
   809     direntry = (direntry_t*)array_get(&(s->directory), mapping->dir_index);
       
   810     set_begin_of_direntry(direntry, mapping->begin);
       
   811 
       
   812     return 0;
       
   813 }
       
   814 
       
   815 static inline uint32_t sector2cluster(BDRVVVFATState* s,off_t sector_num)
       
   816 {
       
   817     return (sector_num-s->faked_sectors)/s->sectors_per_cluster;
       
   818 }
       
   819 
       
   820 static inline off_t cluster2sector(BDRVVVFATState* s, uint32_t cluster_num)
       
   821 {
       
   822     return s->faked_sectors + s->sectors_per_cluster * cluster_num;
       
   823 }
       
   824 
       
   825 static inline uint32_t sector_offset_in_cluster(BDRVVVFATState* s,off_t sector_num)
       
   826 {
       
   827     return (sector_num-s->first_sectors_number-2*s->sectors_per_fat)%s->sectors_per_cluster;
       
   828 }
       
   829 
       
   830 #ifdef DBG
       
   831 static direntry_t* get_direntry_for_mapping(BDRVVVFATState* s,mapping_t* mapping)
       
   832 {
       
   833     if(mapping->mode==MODE_UNDEFINED)
       
   834 	return 0;
       
   835     return (direntry_t*)(s->directory.pointer+sizeof(direntry_t)*mapping->dir_index);
       
   836 }
       
   837 #endif
       
   838 
       
   839 static int init_directories(BDRVVVFATState* s,
       
   840 	const char* dirname)
       
   841 {
       
   842     bootsector_t* bootsector;
       
   843     mapping_t* mapping;
       
   844     unsigned int i;
       
   845     unsigned int cluster;
       
   846 
       
   847     memset(&(s->first_sectors[0]),0,0x40*0x200);
       
   848 
       
   849     s->cluster_size=s->sectors_per_cluster*0x200;
       
   850     s->cluster_buffer=malloc(s->cluster_size);
       
   851     assert(s->cluster_buffer);
       
   852 
       
   853     /*
       
   854      * The formula: sc = spf+1+spf*spc*(512*8/fat_type),
       
   855      * where sc is sector_count,
       
   856      * spf is sectors_per_fat,
       
   857      * spc is sectors_per_clusters, and
       
   858      * fat_type = 12, 16 or 32.
       
   859      */
       
   860     i = 1+s->sectors_per_cluster*0x200*8/s->fat_type;
       
   861     s->sectors_per_fat=(s->sector_count+i)/i; /* round up */
       
   862 
       
   863     array_init(&(s->mapping),sizeof(mapping_t));
       
   864     array_init(&(s->directory),sizeof(direntry_t));
       
   865 
       
   866     /* add volume label */
       
   867     {
       
   868 	direntry_t* entry=array_get_next(&(s->directory));
       
   869 	entry->attributes=0x28; /* archive | volume label */
       
   870 	snprintf((char*)entry->name,11,"QEMU VVFAT");
       
   871     }
       
   872 
       
   873     /* Now build FAT, and write back information into directory */
       
   874     init_fat(s);
       
   875 
       
   876     s->faked_sectors=s->first_sectors_number+s->sectors_per_fat*2;
       
   877     s->cluster_count=sector2cluster(s, s->sector_count);
       
   878 
       
   879     mapping = array_get_next(&(s->mapping));
       
   880     mapping->begin = 0;
       
   881     mapping->dir_index = 0;
       
   882     mapping->info.dir.parent_mapping_index = -1;
       
   883     mapping->first_mapping_index = -1;
       
   884     mapping->path = strdup(dirname);
       
   885     i = strlen(mapping->path);
       
   886     if (i > 0 && mapping->path[i - 1] == '/')
       
   887 	mapping->path[i - 1] = '\0';
       
   888     mapping->mode = MODE_DIRECTORY;
       
   889     mapping->read_only = 0;
       
   890     s->path = mapping->path;
       
   891 
       
   892     for (i = 0, cluster = 0; i < s->mapping.next; i++) {
       
   893 	/* MS-DOS expects the FAT to be 0 for the root directory
       
   894 	 * (except for the media byte). */
       
   895 	/* LATER TODO: still true for FAT32? */
       
   896 	int fix_fat = (i != 0);
       
   897 	mapping = array_get(&(s->mapping), i);
       
   898 
       
   899         if (mapping->mode & MODE_DIRECTORY) {
       
   900 	    mapping->begin = cluster;
       
   901 	    if(read_directory(s, i)) {
       
   902 		fprintf(stderr, "Could not read directory %s\n",
       
   903 			mapping->path);
       
   904 		return -1;
       
   905 	    }
       
   906 	    mapping = array_get(&(s->mapping), i);
       
   907 	} else {
       
   908 	    assert(mapping->mode == MODE_UNDEFINED);
       
   909 	    mapping->mode=MODE_NORMAL;
       
   910 	    mapping->begin = cluster;
       
   911 	    if (mapping->end > 0) {
       
   912 		direntry_t* direntry = array_get(&(s->directory),
       
   913 			mapping->dir_index);
       
   914 
       
   915 		mapping->end = cluster + 1 + (mapping->end-1)/s->cluster_size;
       
   916 		set_begin_of_direntry(direntry, mapping->begin);
       
   917 	    } else {
       
   918 		mapping->end = cluster + 1;
       
   919 		fix_fat = 0;
       
   920 	    }
       
   921 	}
       
   922 
       
   923 	assert(mapping->begin < mapping->end);
       
   924 
       
   925 	/* next free cluster */
       
   926 	cluster = mapping->end;
       
   927 
       
   928 	if(cluster > s->cluster_count) {
       
   929 	    fprintf(stderr,"Directory does not fit in FAT%d (capacity %s)\n",
       
   930 		    s->fat_type,
       
   931 		    s->fat_type == 12 ? s->sector_count == 2880 ? "1.44 MB"
       
   932 								: "2.88 MB"
       
   933 				      : "504MB");
       
   934 	    return -EINVAL;
       
   935 	}
       
   936 
       
   937 	/* fix fat for entry */
       
   938 	if (fix_fat) {
       
   939 	    int j;
       
   940 	    for(j = mapping->begin; j < mapping->end - 1; j++)
       
   941 		fat_set(s, j, j+1);
       
   942 	    fat_set(s, mapping->end - 1, s->max_fat_value);
       
   943 	}
       
   944     }
       
   945 
       
   946     mapping = array_get(&(s->mapping), 0);
       
   947     s->sectors_of_root_directory = mapping->end * s->sectors_per_cluster;
       
   948     s->last_cluster_of_root_directory = mapping->end;
       
   949 
       
   950     /* the FAT signature */
       
   951     fat_set(s,0,s->max_fat_value);
       
   952     fat_set(s,1,s->max_fat_value);
       
   953 
       
   954     s->current_mapping = NULL;
       
   955 
       
   956     bootsector=(bootsector_t*)(s->first_sectors+(s->first_sectors_number-1)*0x200);
       
   957     bootsector->jump[0]=0xeb;
       
   958     bootsector->jump[1]=0x3e;
       
   959     bootsector->jump[2]=0x90;
       
   960     memcpy(bootsector->name,"QEMU    ",8);
       
   961     bootsector->sector_size=cpu_to_le16(0x200);
       
   962     bootsector->sectors_per_cluster=s->sectors_per_cluster;
       
   963     bootsector->reserved_sectors=cpu_to_le16(1);
       
   964     bootsector->number_of_fats=0x2; /* number of FATs */
       
   965     bootsector->root_entries=cpu_to_le16(s->sectors_of_root_directory*0x10);
       
   966     bootsector->total_sectors16=s->sector_count>0xffff?0:cpu_to_le16(s->sector_count);
       
   967     bootsector->media_type=(s->fat_type!=12?0xf8:s->sector_count==5760?0xf9:0xf8); /* media descriptor */
       
   968     s->fat.pointer[0] = bootsector->media_type;
       
   969     bootsector->sectors_per_fat=cpu_to_le16(s->sectors_per_fat);
       
   970     bootsector->sectors_per_track=cpu_to_le16(s->bs->secs);
       
   971     bootsector->number_of_heads=cpu_to_le16(s->bs->heads);
       
   972     bootsector->hidden_sectors=cpu_to_le32(s->first_sectors_number==1?0:0x3f);
       
   973     bootsector->total_sectors=cpu_to_le32(s->sector_count>0xffff?s->sector_count:0);
       
   974 
       
   975     /* LATER TODO: if FAT32, this is wrong */
       
   976     bootsector->u.fat16.drive_number=s->fat_type==12?0:0x80; /* assume this is hda (TODO) */
       
   977     bootsector->u.fat16.current_head=0;
       
   978     bootsector->u.fat16.signature=0x29;
       
   979     bootsector->u.fat16.id=cpu_to_le32(0xfabe1afd);
       
   980 
       
   981     memcpy(bootsector->u.fat16.volume_label,"QEMU VVFAT ",11);
       
   982     memcpy(bootsector->fat_type,(s->fat_type==12?"FAT12   ":s->fat_type==16?"FAT16   ":"FAT32   "),8);
       
   983     bootsector->magic[0]=0x55; bootsector->magic[1]=0xaa;
       
   984 
       
   985     return 0;
       
   986 }
       
   987 
       
   988 #ifdef DEBUG
       
   989 static BDRVVVFATState *vvv = NULL;
       
   990 #endif
       
   991 
       
   992 static int enable_write_target(BDRVVVFATState *s);
       
   993 static int is_consistent(BDRVVVFATState *s);
       
   994 
       
   995 static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
       
   996 {
       
   997     BDRVVVFATState *s = bs->opaque;
       
   998     int floppy = 0;
       
   999     int i;
       
  1000 
       
  1001 #ifdef DEBUG
       
  1002     vvv = s;
       
  1003 #endif
       
  1004 
       
  1005 DLOG(if (stderr == NULL) {
       
  1006     stderr = fopen("vvfat.log", "a");
       
  1007     setbuf(stderr, NULL);
       
  1008 })
       
  1009 
       
  1010     s->bs = bs;
       
  1011 
       
  1012     s->fat_type=16;
       
  1013     /* LATER TODO: if FAT32, adjust */
       
  1014     s->sectors_per_cluster=0x10;
       
  1015     /* 504MB disk*/
       
  1016     bs->cyls=1024; bs->heads=16; bs->secs=63;
       
  1017 
       
  1018     s->current_cluster=0xffffffff;
       
  1019 
       
  1020     s->first_sectors_number=0x40;
       
  1021     /* read only is the default for safety */
       
  1022     bs->read_only = 1;
       
  1023     s->qcow = s->write_target = NULL;
       
  1024     s->qcow_filename = NULL;
       
  1025     s->fat2 = NULL;
       
  1026     s->downcase_short_names = 1;
       
  1027 
       
  1028     if (!strstart(dirname, "fat:", NULL))
       
  1029 	return -1;
       
  1030 
       
  1031     if (strstr(dirname, ":floppy:")) {
       
  1032 	floppy = 1;
       
  1033 	s->fat_type = 12;
       
  1034 	s->first_sectors_number = 1;
       
  1035 	s->sectors_per_cluster=2;
       
  1036 	bs->cyls = 80; bs->heads = 2; bs->secs = 36;
       
  1037     }
       
  1038 
       
  1039     s->sector_count=bs->cyls*bs->heads*bs->secs;
       
  1040 
       
  1041     if (strstr(dirname, ":32:")) {
       
  1042 	fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. You are welcome to do so!\n");
       
  1043 	s->fat_type = 32;
       
  1044     } else if (strstr(dirname, ":16:")) {
       
  1045 	s->fat_type = 16;
       
  1046     } else if (strstr(dirname, ":12:")) {
       
  1047 	s->fat_type = 12;
       
  1048 	s->sector_count=2880;
       
  1049     }
       
  1050 
       
  1051     if (strstr(dirname, ":rw:")) {
       
  1052 	if (enable_write_target(s))
       
  1053 	    return -1;
       
  1054 	bs->read_only = 0;
       
  1055     }
       
  1056 
       
  1057     i = strrchr(dirname, ':') - dirname;
       
  1058     assert(i >= 3);
       
  1059     if (dirname[i-2] == ':' && qemu_isalpha(dirname[i-1]))
       
  1060 	/* workaround for DOS drive names */
       
  1061 	dirname += i-1;
       
  1062     else
       
  1063 	dirname += i+1;
       
  1064 
       
  1065     bs->total_sectors=bs->cyls*bs->heads*bs->secs;
       
  1066 
       
  1067     if(init_directories(s, dirname))
       
  1068 	return -1;
       
  1069 
       
  1070     s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
       
  1071 
       
  1072     if(s->first_sectors_number==0x40)
       
  1073 	init_mbr(s);
       
  1074 
       
  1075     /* for some reason or other, MS-DOS does not like to know about CHS... */
       
  1076     if (floppy)
       
  1077 	bs->heads = bs->cyls = bs->secs = 0;
       
  1078 
       
  1079     //    assert(is_consistent(s));
       
  1080     return 0;
       
  1081 }
       
  1082 
       
  1083 static inline void vvfat_close_current_file(BDRVVVFATState *s)
       
  1084 {
       
  1085     if(s->current_mapping) {
       
  1086 	s->current_mapping = NULL;
       
  1087 	if (s->current_fd) {
       
  1088 		close(s->current_fd);
       
  1089 		s->current_fd = 0;
       
  1090 	}
       
  1091     }
       
  1092     s->current_cluster = -1;
       
  1093 }
       
  1094 
       
  1095 /* mappings between index1 and index2-1 are supposed to be ordered
       
  1096  * return value is the index of the last mapping for which end>cluster_num
       
  1097  */
       
  1098 static inline int find_mapping_for_cluster_aux(BDRVVVFATState* s,int cluster_num,int index1,int index2)
       
  1099 {
       
  1100     int index3=index1+1;
       
  1101     while(1) {
       
  1102 	mapping_t* mapping;
       
  1103 	index3=(index1+index2)/2;
       
  1104 	mapping=array_get(&(s->mapping),index3);
       
  1105 	assert(mapping->begin < mapping->end);
       
  1106 	if(mapping->begin>=cluster_num) {
       
  1107 	    assert(index2!=index3 || index2==0);
       
  1108 	    if(index2==index3)
       
  1109 		return index1;
       
  1110 	    index2=index3;
       
  1111 	} else {
       
  1112 	    if(index1==index3)
       
  1113 		return mapping->end<=cluster_num ? index2 : index1;
       
  1114 	    index1=index3;
       
  1115 	}
       
  1116 	assert(index1<=index2);
       
  1117 	DLOG(mapping=array_get(&(s->mapping),index1);
       
  1118 	assert(mapping->begin<=cluster_num);
       
  1119 	assert(index2 >= s->mapping.next ||
       
  1120 		((mapping = array_get(&(s->mapping),index2)) &&
       
  1121 		mapping->end>cluster_num)));
       
  1122     }
       
  1123 }
       
  1124 
       
  1125 static inline mapping_t* find_mapping_for_cluster(BDRVVVFATState* s,int cluster_num)
       
  1126 {
       
  1127     int index=find_mapping_for_cluster_aux(s,cluster_num,0,s->mapping.next);
       
  1128     mapping_t* mapping;
       
  1129     if(index>=s->mapping.next)
       
  1130 	return 0;
       
  1131     mapping=array_get(&(s->mapping),index);
       
  1132     if(mapping->begin>cluster_num)
       
  1133 	return 0;
       
  1134     assert(mapping->begin<=cluster_num && mapping->end>cluster_num);
       
  1135     return mapping;
       
  1136 }
       
  1137 
       
  1138 /*
       
  1139  * This function simply compares path == mapping->path. Since the mappings
       
  1140  * are sorted by cluster, this is expensive: O(n).
       
  1141  */
       
  1142 static inline mapping_t* find_mapping_for_path(BDRVVVFATState* s,
       
  1143 	const char* path)
       
  1144 {
       
  1145     int i;
       
  1146 
       
  1147     for (i = 0; i < s->mapping.next; i++) {
       
  1148 	mapping_t* mapping = array_get(&(s->mapping), i);
       
  1149 	if (mapping->first_mapping_index < 0 &&
       
  1150 		!strcmp(path, mapping->path))
       
  1151 	    return mapping;
       
  1152     }
       
  1153 
       
  1154     return NULL;
       
  1155 }
       
  1156 
       
  1157 static int open_file(BDRVVVFATState* s,mapping_t* mapping)
       
  1158 {
       
  1159     if(!mapping)
       
  1160 	return -1;
       
  1161     if(!s->current_mapping ||
       
  1162 	    strcmp(s->current_mapping->path,mapping->path)) {
       
  1163 	/* open file */
       
  1164 	int fd = open(mapping->path, O_RDONLY | O_BINARY | O_LARGEFILE);
       
  1165 	if(fd<0)
       
  1166 	    return -1;
       
  1167 	vvfat_close_current_file(s);
       
  1168 	s->current_fd = fd;
       
  1169 	s->current_mapping = mapping;
       
  1170     }
       
  1171     return 0;
       
  1172 }
       
  1173 
       
  1174 static inline int read_cluster(BDRVVVFATState *s,int cluster_num)
       
  1175 {
       
  1176     if(s->current_cluster != cluster_num) {
       
  1177 	int result=0;
       
  1178 	off_t offset;
       
  1179 	assert(!s->current_mapping || s->current_fd || (s->current_mapping->mode & MODE_DIRECTORY));
       
  1180 	if(!s->current_mapping
       
  1181 		|| s->current_mapping->begin>cluster_num
       
  1182 		|| s->current_mapping->end<=cluster_num) {
       
  1183 	    /* binary search of mappings for file */
       
  1184 	    mapping_t* mapping=find_mapping_for_cluster(s,cluster_num);
       
  1185 
       
  1186 	    assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
       
  1187 
       
  1188 	    if (mapping && mapping->mode & MODE_DIRECTORY) {
       
  1189 		vvfat_close_current_file(s);
       
  1190 		s->current_mapping = mapping;
       
  1191 read_cluster_directory:
       
  1192 		offset = s->cluster_size*(cluster_num-s->current_mapping->begin);
       
  1193 		s->cluster = (unsigned char*)s->directory.pointer+offset
       
  1194 			+ 0x20*s->current_mapping->info.dir.first_dir_index;
       
  1195 		assert(((s->cluster-(unsigned char*)s->directory.pointer)%s->cluster_size)==0);
       
  1196 		assert((char*)s->cluster+s->cluster_size <= s->directory.pointer+s->directory.next*s->directory.item_size);
       
  1197 		s->current_cluster = cluster_num;
       
  1198 		return 0;
       
  1199 	    }
       
  1200 
       
  1201 	    if(open_file(s,mapping))
       
  1202 		return -2;
       
  1203 	} else if (s->current_mapping->mode & MODE_DIRECTORY)
       
  1204 	    goto read_cluster_directory;
       
  1205 
       
  1206 	assert(s->current_fd);
       
  1207 
       
  1208 	offset=s->cluster_size*(cluster_num-s->current_mapping->begin)+s->current_mapping->info.file.offset;
       
  1209 	if(lseek(s->current_fd, offset, SEEK_SET)!=offset)
       
  1210 	    return -3;
       
  1211 	s->cluster=s->cluster_buffer;
       
  1212 	result=read(s->current_fd,s->cluster,s->cluster_size);
       
  1213 	if(result<0) {
       
  1214 	    s->current_cluster = -1;
       
  1215 	    return -1;
       
  1216 	}
       
  1217 	s->current_cluster = cluster_num;
       
  1218     }
       
  1219     return 0;
       
  1220 }
       
  1221 
       
  1222 #ifdef DEBUG
       
  1223 static void hexdump(const void* address, uint32_t len)
       
  1224 {
       
  1225     const unsigned char* p = address;
       
  1226     int i, j;
       
  1227 
       
  1228     for (i = 0; i < len; i += 16) {
       
  1229 	for (j = 0; j < 16 && i + j < len; j++)
       
  1230 	    fprintf(stderr, "%02x ", p[i + j]);
       
  1231 	for (; j < 16; j++)
       
  1232 	    fprintf(stderr, "   ");
       
  1233 	fprintf(stderr, " ");
       
  1234 	for (j = 0; j < 16 && i + j < len; j++)
       
  1235 	    fprintf(stderr, "%c", (p[i + j] < ' ' || p[i + j] > 0x7f) ? '.' : p[i + j]);
       
  1236 	fprintf(stderr, "\n");
       
  1237     }
       
  1238 }
       
  1239 
       
  1240 static void print_direntry(const direntry_t* direntry)
       
  1241 {
       
  1242     int j = 0;
       
  1243     char buffer[1024];
       
  1244 
       
  1245     fprintf(stderr, "direntry 0x%x: ", (int)direntry);
       
  1246     if(!direntry)
       
  1247 	return;
       
  1248     if(is_long_name(direntry)) {
       
  1249 	unsigned char* c=(unsigned char*)direntry;
       
  1250 	int i;
       
  1251 	for(i=1;i<11 && c[i] && c[i]!=0xff;i+=2)
       
  1252 #define ADD_CHAR(c) {buffer[j] = (c); if (buffer[j] < ' ') buffer[j] = 0xb0; j++;}
       
  1253 	    ADD_CHAR(c[i]);
       
  1254 	for(i=14;i<26 && c[i] && c[i]!=0xff;i+=2)
       
  1255 	    ADD_CHAR(c[i]);
       
  1256 	for(i=28;i<32 && c[i] && c[i]!=0xff;i+=2)
       
  1257 	    ADD_CHAR(c[i]);
       
  1258 	buffer[j] = 0;
       
  1259 	fprintf(stderr, "%s\n", buffer);
       
  1260     } else {
       
  1261 	int i;
       
  1262 	for(i=0;i<11;i++)
       
  1263 	    ADD_CHAR(direntry->name[i]);
       
  1264 	buffer[j] = 0;
       
  1265 	fprintf(stderr,"%s attributes=0x%02x begin=%d size=%d\n",
       
  1266 		buffer,
       
  1267 		direntry->attributes,
       
  1268 		begin_of_direntry(direntry),le32_to_cpu(direntry->size));
       
  1269     }
       
  1270 }
       
  1271 
       
  1272 static void print_mapping(const mapping_t* mapping)
       
  1273 {
       
  1274     fprintf(stderr, "mapping (0x%x): begin, end = %d, %d, dir_index = %d, first_mapping_index = %d, name = %s, mode = 0x%x, " , (int)mapping, mapping->begin, mapping->end, mapping->dir_index, mapping->first_mapping_index, mapping->path, mapping->mode);
       
  1275     if (mapping->mode & MODE_DIRECTORY)
       
  1276 	fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
       
  1277     else
       
  1278 	fprintf(stderr, "offset = %d\n", mapping->info.file.offset);
       
  1279 }
       
  1280 #endif
       
  1281 
       
  1282 static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
       
  1283                     uint8_t *buf, int nb_sectors)
       
  1284 {
       
  1285     BDRVVVFATState *s = bs->opaque;
       
  1286     int i;
       
  1287 
       
  1288     for(i=0;i<nb_sectors;i++,sector_num++) {
       
  1289 	if (sector_num >= s->sector_count)
       
  1290 	   return -1;
       
  1291 	if (s->qcow) {
       
  1292 	    int n;
       
  1293 	    if (s->qcow->drv->bdrv_is_allocated(s->qcow,
       
  1294 			sector_num, nb_sectors-i, &n)) {
       
  1295 DLOG(fprintf(stderr, "sectors %d+%d allocated\n", (int)sector_num, n));
       
  1296 		if (s->qcow->drv->bdrv_read(s->qcow, sector_num, buf+i*0x200, n))
       
  1297 		    return -1;
       
  1298 		i += n - 1;
       
  1299 		sector_num += n - 1;
       
  1300 		continue;
       
  1301 	    }
       
  1302 DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num));
       
  1303 	}
       
  1304 	if(sector_num<s->faked_sectors) {
       
  1305 	    if(sector_num<s->first_sectors_number)
       
  1306 		memcpy(buf+i*0x200,&(s->first_sectors[sector_num*0x200]),0x200);
       
  1307 	    else if(sector_num-s->first_sectors_number<s->sectors_per_fat)
       
  1308 		memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number)*0x200]),0x200);
       
  1309 	    else if(sector_num-s->first_sectors_number-s->sectors_per_fat<s->sectors_per_fat)
       
  1310 		memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number-s->sectors_per_fat)*0x200]),0x200);
       
  1311 	} else {
       
  1312 	    uint32_t sector=sector_num-s->faked_sectors,
       
  1313 	    sector_offset_in_cluster=(sector%s->sectors_per_cluster),
       
  1314 	    cluster_num=sector/s->sectors_per_cluster;
       
  1315 	    if(read_cluster(s, cluster_num) != 0) {
       
  1316 		/* LATER TODO: strict: return -1; */
       
  1317 		memset(buf+i*0x200,0,0x200);
       
  1318 		continue;
       
  1319 	    }
       
  1320 	    memcpy(buf+i*0x200,s->cluster+sector_offset_in_cluster*0x200,0x200);
       
  1321 	}
       
  1322     }
       
  1323     return 0;
       
  1324 }
       
  1325 
       
  1326 /* LATER TODO: statify all functions */
       
  1327 
       
  1328 /*
       
  1329  * Idea of the write support (use snapshot):
       
  1330  *
       
  1331  * 1. check if all data is consistent, recording renames, modifications,
       
  1332  *    new files and directories (in s->commits).
       
  1333  *
       
  1334  * 2. if the data is not consistent, stop committing
       
  1335  *
       
  1336  * 3. handle renames, and create new files and directories (do not yet
       
  1337  *    write their contents)
       
  1338  *
       
  1339  * 4. walk the directories, fixing the mapping and direntries, and marking
       
  1340  *    the handled mappings as not deleted
       
  1341  *
       
  1342  * 5. commit the contents of the files
       
  1343  *
       
  1344  * 6. handle deleted files and directories
       
  1345  *
       
  1346  */
       
  1347 
       
  1348 typedef struct commit_t {
       
  1349     char* path;
       
  1350     union {
       
  1351 	struct { uint32_t cluster; } rename;
       
  1352 	struct { int dir_index; uint32_t modified_offset; } writeout;
       
  1353 	struct { uint32_t first_cluster; } new_file;
       
  1354 	struct { uint32_t cluster; } mkdir;
       
  1355     } param;
       
  1356     /* DELETEs and RMDIRs are handled differently: see handle_deletes() */
       
  1357     enum {
       
  1358 	ACTION_RENAME, ACTION_WRITEOUT, ACTION_NEW_FILE, ACTION_MKDIR
       
  1359     } action;
       
  1360 } commit_t;
       
  1361 
       
  1362 static void clear_commits(BDRVVVFATState* s)
       
  1363 {
       
  1364     int i;
       
  1365 DLOG(fprintf(stderr, "clear_commits (%d commits)\n", s->commits.next));
       
  1366     for (i = 0; i < s->commits.next; i++) {
       
  1367 	commit_t* commit = array_get(&(s->commits), i);
       
  1368 	assert(commit->path || commit->action == ACTION_WRITEOUT);
       
  1369 	if (commit->action != ACTION_WRITEOUT) {
       
  1370 	    assert(commit->path);
       
  1371 	    free(commit->path);
       
  1372 	} else
       
  1373 	    assert(commit->path == NULL);
       
  1374     }
       
  1375     s->commits.next = 0;
       
  1376 }
       
  1377 
       
  1378 static void schedule_rename(BDRVVVFATState* s,
       
  1379 	uint32_t cluster, char* new_path)
       
  1380 {
       
  1381     commit_t* commit = array_get_next(&(s->commits));
       
  1382     commit->path = new_path;
       
  1383     commit->param.rename.cluster = cluster;
       
  1384     commit->action = ACTION_RENAME;
       
  1385 }
       
  1386 
       
  1387 static void schedule_writeout(BDRVVVFATState* s,
       
  1388 	int dir_index, uint32_t modified_offset)
       
  1389 {
       
  1390     commit_t* commit = array_get_next(&(s->commits));
       
  1391     commit->path = NULL;
       
  1392     commit->param.writeout.dir_index = dir_index;
       
  1393     commit->param.writeout.modified_offset = modified_offset;
       
  1394     commit->action = ACTION_WRITEOUT;
       
  1395 }
       
  1396 
       
  1397 static void schedule_new_file(BDRVVVFATState* s,
       
  1398 	char* path, uint32_t first_cluster)
       
  1399 {
       
  1400     commit_t* commit = array_get_next(&(s->commits));
       
  1401     commit->path = path;
       
  1402     commit->param.new_file.first_cluster = first_cluster;
       
  1403     commit->action = ACTION_NEW_FILE;
       
  1404 }
       
  1405 
       
  1406 static void schedule_mkdir(BDRVVVFATState* s, uint32_t cluster, char* path)
       
  1407 {
       
  1408     commit_t* commit = array_get_next(&(s->commits));
       
  1409     commit->path = path;
       
  1410     commit->param.mkdir.cluster = cluster;
       
  1411     commit->action = ACTION_MKDIR;
       
  1412 }
       
  1413 
       
  1414 typedef struct {
       
  1415     /*
       
  1416      * Since the sequence number is at most 0x3f, and the filename
       
  1417      * length is at most 13 times the sequence number, the maximal
       
  1418      * filename length is 0x3f * 13 bytes.
       
  1419      */
       
  1420     unsigned char name[0x3f * 13 + 1];
       
  1421     int checksum, len;
       
  1422     int sequence_number;
       
  1423 } long_file_name;
       
  1424 
       
  1425 static void lfn_init(long_file_name* lfn)
       
  1426 {
       
  1427    lfn->sequence_number = lfn->len = 0;
       
  1428    lfn->checksum = 0x100;
       
  1429 }
       
  1430 
       
  1431 /* return 0 if parsed successfully, > 0 if no long name, < 0 if error */
       
  1432 static int parse_long_name(long_file_name* lfn,
       
  1433 	const direntry_t* direntry)
       
  1434 {
       
  1435     int i, j, offset;
       
  1436     const unsigned char* pointer = (const unsigned char*)direntry;
       
  1437 
       
  1438     if (!is_long_name(direntry))
       
  1439 	return 1;
       
  1440 
       
  1441     if (pointer[0] & 0x40) {
       
  1442 	lfn->sequence_number = pointer[0] & 0x3f;
       
  1443 	lfn->checksum = pointer[13];
       
  1444 	lfn->name[0] = 0;
       
  1445 	lfn->name[lfn->sequence_number * 13] = 0;
       
  1446     } else if ((pointer[0] & 0x3f) != --lfn->sequence_number)
       
  1447 	return -1;
       
  1448     else if (pointer[13] != lfn->checksum)
       
  1449 	return -2;
       
  1450     else if (pointer[12] || pointer[26] || pointer[27])
       
  1451 	return -3;
       
  1452 
       
  1453     offset = 13 * (lfn->sequence_number - 1);
       
  1454     for (i = 0, j = 1; i < 13; i++, j+=2) {
       
  1455 	if (j == 11)
       
  1456 	    j = 14;
       
  1457 	else if (j == 26)
       
  1458 	    j = 28;
       
  1459 
       
  1460 	if (pointer[j+1] == 0)
       
  1461 	    lfn->name[offset + i] = pointer[j];
       
  1462 	else if (pointer[j+1] != 0xff || (pointer[0] & 0x40) == 0)
       
  1463 	    return -4;
       
  1464 	else
       
  1465 	    lfn->name[offset + i] = 0;
       
  1466     }
       
  1467 
       
  1468     if (pointer[0] & 0x40)
       
  1469 	lfn->len = offset + strlen((char*)lfn->name + offset);
       
  1470 
       
  1471     return 0;
       
  1472 }
       
  1473 
       
  1474 /* returns 0 if successful, >0 if no short_name, and <0 on error */
       
  1475 static int parse_short_name(BDRVVVFATState* s,
       
  1476 	long_file_name* lfn, direntry_t* direntry)
       
  1477 {
       
  1478     int i, j;
       
  1479 
       
  1480     if (!is_short_name(direntry))
       
  1481 	return 1;
       
  1482 
       
  1483     for (j = 7; j >= 0 && direntry->name[j] == ' '; j--);
       
  1484     for (i = 0; i <= j; i++) {
       
  1485 	if (direntry->name[i] <= ' ' || direntry->name[i] > 0x7f)
       
  1486 	    return -1;
       
  1487 	else if (s->downcase_short_names)
       
  1488 	    lfn->name[i] = qemu_tolower(direntry->name[i]);
       
  1489 	else
       
  1490 	    lfn->name[i] = direntry->name[i];
       
  1491     }
       
  1492 
       
  1493     for (j = 2; j >= 0 && direntry->extension[j] == ' '; j--);
       
  1494     if (j >= 0) {
       
  1495 	lfn->name[i++] = '.';
       
  1496 	lfn->name[i + j + 1] = '\0';
       
  1497 	for (;j >= 0; j--) {
       
  1498 	    if (direntry->extension[j] <= ' ' || direntry->extension[j] > 0x7f)
       
  1499 		return -2;
       
  1500 	    else if (s->downcase_short_names)
       
  1501 		lfn->name[i + j] = qemu_tolower(direntry->extension[j]);
       
  1502 	    else
       
  1503 		lfn->name[i + j] = direntry->extension[j];
       
  1504 	}
       
  1505     } else
       
  1506 	lfn->name[i + j + 1] = '\0';
       
  1507 
       
  1508     lfn->len = strlen((char*)lfn->name);
       
  1509 
       
  1510     return 0;
       
  1511 }
       
  1512 
       
  1513 static inline uint32_t modified_fat_get(BDRVVVFATState* s,
       
  1514 	unsigned int cluster)
       
  1515 {
       
  1516     if (cluster < s->last_cluster_of_root_directory) {
       
  1517 	if (cluster + 1 == s->last_cluster_of_root_directory)
       
  1518 	    return s->max_fat_value;
       
  1519 	else
       
  1520 	    return cluster + 1;
       
  1521     }
       
  1522 
       
  1523     if (s->fat_type==32) {
       
  1524         uint32_t* entry=((uint32_t*)s->fat2)+cluster;
       
  1525         return le32_to_cpu(*entry);
       
  1526     } else if (s->fat_type==16) {
       
  1527         uint16_t* entry=((uint16_t*)s->fat2)+cluster;
       
  1528         return le16_to_cpu(*entry);
       
  1529     } else {
       
  1530         const uint8_t* x=s->fat2+cluster*3/2;
       
  1531         return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
       
  1532     }
       
  1533 }
       
  1534 
       
  1535 static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num)
       
  1536 {
       
  1537     int was_modified = 0;
       
  1538     int i, dummy;
       
  1539 
       
  1540     if (s->qcow == NULL)
       
  1541 	return 0;
       
  1542 
       
  1543     for (i = 0; !was_modified && i < s->sectors_per_cluster; i++)
       
  1544 	was_modified = s->qcow->drv->bdrv_is_allocated(s->qcow,
       
  1545 		cluster2sector(s, cluster_num) + i, 1, &dummy);
       
  1546 
       
  1547     return was_modified;
       
  1548 }
       
  1549 
       
  1550 static const char* get_basename(const char* path)
       
  1551 {
       
  1552     char* basename = strrchr(path, '/');
       
  1553     if (basename == NULL)
       
  1554 	return path;
       
  1555     else
       
  1556 	return basename + 1; /* strip '/' */
       
  1557 }
       
  1558 
       
  1559 /*
       
  1560  * The array s->used_clusters holds the states of the clusters. If it is
       
  1561  * part of a file, it has bit 2 set, in case of a directory, bit 1. If it
       
  1562  * was modified, bit 3 is set.
       
  1563  * If any cluster is allocated, but not part of a file or directory, this
       
  1564  * driver refuses to commit.
       
  1565  */
       
  1566 typedef enum {
       
  1567      USED_DIRECTORY = 1, USED_FILE = 2, USED_ANY = 3, USED_ALLOCATED = 4
       
  1568 } used_t;
       
  1569 
       
  1570 /*
       
  1571  * get_cluster_count_for_direntry() not only determines how many clusters
       
  1572  * are occupied by direntry, but also if it was renamed or modified.
       
  1573  *
       
  1574  * A file is thought to be renamed *only* if there already was a file with
       
  1575  * exactly the same first cluster, but a different name.
       
  1576  *
       
  1577  * Further, the files/directories handled by this function are
       
  1578  * assumed to be *not* deleted (and *only* those).
       
  1579  */
       
  1580 static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
       
  1581 	direntry_t* direntry, const char* path)
       
  1582 {
       
  1583     /*
       
  1584      * This is a little bit tricky:
       
  1585      * IF the guest OS just inserts a cluster into the file chain,
       
  1586      * and leaves the rest alone, (i.e. the original file had clusters
       
  1587      * 15 -> 16, but now has 15 -> 32 -> 16), then the following happens:
       
  1588      *
       
  1589      * - do_commit will write the cluster into the file at the given
       
  1590      *   offset, but
       
  1591      *
       
  1592      * - the cluster which is overwritten should be moved to a later
       
  1593      *   position in the file.
       
  1594      *
       
  1595      * I am not aware that any OS does something as braindead, but this
       
  1596      * situation could happen anyway when not committing for a long time.
       
  1597      * Just to be sure that this does not bite us, detect it, and copy the
       
  1598      * contents of the clusters to-be-overwritten into the qcow.
       
  1599      */
       
  1600     int copy_it = 0;
       
  1601     int was_modified = 0;
       
  1602     int32_t ret = 0;
       
  1603 
       
  1604     uint32_t cluster_num = begin_of_direntry(direntry);
       
  1605     uint32_t offset = 0;
       
  1606     int first_mapping_index = -1;
       
  1607     mapping_t* mapping = NULL;
       
  1608     const char* basename2 = NULL;
       
  1609 
       
  1610     vvfat_close_current_file(s);
       
  1611 
       
  1612     /* the root directory */
       
  1613     if (cluster_num == 0)
       
  1614 	return 0;
       
  1615 
       
  1616     /* write support */
       
  1617     if (s->qcow) {
       
  1618 	basename2 = get_basename(path);
       
  1619 
       
  1620 	mapping = find_mapping_for_cluster(s, cluster_num);
       
  1621 
       
  1622 	if (mapping) {
       
  1623 	    const char* basename;
       
  1624 
       
  1625 	    assert(mapping->mode & MODE_DELETED);
       
  1626 	    mapping->mode &= ~MODE_DELETED;
       
  1627 
       
  1628 	    basename = get_basename(mapping->path);
       
  1629 
       
  1630 	    assert(mapping->mode & MODE_NORMAL);
       
  1631 
       
  1632 	    /* rename */
       
  1633 	    if (strcmp(basename, basename2))
       
  1634 		schedule_rename(s, cluster_num, strdup(path));
       
  1635 	} else if (is_file(direntry))
       
  1636 	    /* new file */
       
  1637 	    schedule_new_file(s, strdup(path), cluster_num);
       
  1638 	else {
       
  1639 	    assert(0);
       
  1640 	    return 0;
       
  1641 	}
       
  1642     }
       
  1643 
       
  1644     while(1) {
       
  1645 	if (s->qcow) {
       
  1646 	    if (!copy_it && cluster_was_modified(s, cluster_num)) {
       
  1647 		if (mapping == NULL ||
       
  1648 			mapping->begin > cluster_num ||
       
  1649 			mapping->end <= cluster_num)
       
  1650 		mapping = find_mapping_for_cluster(s, cluster_num);
       
  1651 
       
  1652 
       
  1653 		if (mapping &&
       
  1654 			(mapping->mode & MODE_DIRECTORY) == 0) {
       
  1655 
       
  1656 		    /* was modified in qcow */
       
  1657 		    if (offset != mapping->info.file.offset + s->cluster_size
       
  1658 			    * (cluster_num - mapping->begin)) {
       
  1659 			/* offset of this cluster in file chain has changed */
       
  1660 			assert(0);
       
  1661 			copy_it = 1;
       
  1662 		    } else if (offset == 0) {
       
  1663 			const char* basename = get_basename(mapping->path);
       
  1664 
       
  1665 			if (strcmp(basename, basename2))
       
  1666 			    copy_it = 1;
       
  1667 			first_mapping_index = array_index(&(s->mapping), mapping);
       
  1668 		    }
       
  1669 
       
  1670 		    if (mapping->first_mapping_index != first_mapping_index
       
  1671 			    && mapping->info.file.offset > 0) {
       
  1672 			assert(0);
       
  1673 			copy_it = 1;
       
  1674 		    }
       
  1675 
       
  1676 		    /* need to write out? */
       
  1677 		    if (!was_modified && is_file(direntry)) {
       
  1678 			was_modified = 1;
       
  1679 			schedule_writeout(s, mapping->dir_index, offset);
       
  1680 		    }
       
  1681 		}
       
  1682 	    }
       
  1683 
       
  1684 	    if (copy_it) {
       
  1685 		int i, dummy;
       
  1686 		/*
       
  1687 		 * This is horribly inefficient, but that is okay, since
       
  1688 		 * it is rarely executed, if at all.
       
  1689 		 */
       
  1690 		int64_t offset = cluster2sector(s, cluster_num);
       
  1691 
       
  1692 		vvfat_close_current_file(s);
       
  1693 		for (i = 0; i < s->sectors_per_cluster; i++)
       
  1694 		    if (!s->qcow->drv->bdrv_is_allocated(s->qcow,
       
  1695 				offset + i, 1, &dummy)) {
       
  1696 			if (vvfat_read(s->bs,
       
  1697 				    offset, s->cluster_buffer, 1))
       
  1698 			    return -1;
       
  1699 			if (s->qcow->drv->bdrv_write(s->qcow,
       
  1700 				    offset, s->cluster_buffer, 1))
       
  1701 			    return -2;
       
  1702 		    }
       
  1703 	    }
       
  1704 	}
       
  1705 
       
  1706 	ret++;
       
  1707 	if (s->used_clusters[cluster_num] & USED_ANY)
       
  1708 	    return 0;
       
  1709 	s->used_clusters[cluster_num] = USED_FILE;
       
  1710 
       
  1711 	cluster_num = modified_fat_get(s, cluster_num);
       
  1712 
       
  1713 	if (fat_eof(s, cluster_num))
       
  1714 	    return ret;
       
  1715 	else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
       
  1716 	    return -1;
       
  1717 
       
  1718 	offset += s->cluster_size;
       
  1719     }
       
  1720 }
       
  1721 
       
  1722 /*
       
  1723  * This function looks at the modified data (qcow).
       
  1724  * It returns 0 upon inconsistency or error, and the number of clusters
       
  1725  * used by the directory, its subdirectories and their files.
       
  1726  */
       
  1727 static int check_directory_consistency(BDRVVVFATState *s,
       
  1728 	int cluster_num, const char* path)
       
  1729 {
       
  1730     int ret = 0;
       
  1731     unsigned char* cluster = malloc(s->cluster_size);
       
  1732     direntry_t* direntries = (direntry_t*)cluster;
       
  1733     mapping_t* mapping = find_mapping_for_cluster(s, cluster_num);
       
  1734 
       
  1735     long_file_name lfn;
       
  1736     int path_len = strlen(path);
       
  1737     char path2[PATH_MAX];
       
  1738 
       
  1739     assert(path_len < PATH_MAX); /* len was tested before! */
       
  1740     pstrcpy(path2, sizeof(path2), path);
       
  1741     path2[path_len] = '/';
       
  1742     path2[path_len + 1] = '\0';
       
  1743 
       
  1744     if (mapping) {
       
  1745 	const char* basename = get_basename(mapping->path);
       
  1746 	const char* basename2 = get_basename(path);
       
  1747 
       
  1748 	assert(mapping->mode & MODE_DIRECTORY);
       
  1749 
       
  1750 	assert(mapping->mode & MODE_DELETED);
       
  1751 	mapping->mode &= ~MODE_DELETED;
       
  1752 
       
  1753 	if (strcmp(basename, basename2))
       
  1754 	    schedule_rename(s, cluster_num, strdup(path));
       
  1755     } else
       
  1756 	/* new directory */
       
  1757 	schedule_mkdir(s, cluster_num, strdup(path));
       
  1758 
       
  1759     lfn_init(&lfn);
       
  1760     do {
       
  1761 	int i;
       
  1762 	int subret = 0;
       
  1763 
       
  1764 	ret++;
       
  1765 
       
  1766 	if (s->used_clusters[cluster_num] & USED_ANY) {
       
  1767 	    fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
       
  1768 	    return 0;
       
  1769 	}
       
  1770 	s->used_clusters[cluster_num] = USED_DIRECTORY;
       
  1771 
       
  1772 DLOG(fprintf(stderr, "read cluster %d (sector %d)\n", (int)cluster_num, (int)cluster2sector(s, cluster_num)));
       
  1773 	subret = vvfat_read(s->bs, cluster2sector(s, cluster_num), cluster,
       
  1774 		s->sectors_per_cluster);
       
  1775 	if (subret) {
       
  1776 	    fprintf(stderr, "Error fetching direntries\n");
       
  1777 	fail:
       
  1778 	    free(cluster);
       
  1779 	    return 0;
       
  1780 	}
       
  1781 
       
  1782 	for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
       
  1783 	    int cluster_count;
       
  1784 
       
  1785 DLOG(fprintf(stderr, "check direntry %d: \n", i); print_direntry(direntries + i));
       
  1786 	    if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
       
  1787 		    is_free(direntries + i))
       
  1788 		continue;
       
  1789 
       
  1790 	    subret = parse_long_name(&lfn, direntries + i);
       
  1791 	    if (subret < 0) {
       
  1792 		fprintf(stderr, "Error in long name\n");
       
  1793 		goto fail;
       
  1794 	    }
       
  1795 	    if (subret == 0 || is_free(direntries + i))
       
  1796 		continue;
       
  1797 
       
  1798 	    if (fat_chksum(direntries+i) != lfn.checksum) {
       
  1799 		subret = parse_short_name(s, &lfn, direntries + i);
       
  1800 		if (subret < 0) {
       
  1801 		    fprintf(stderr, "Error in short name (%d)\n", subret);
       
  1802 		    goto fail;
       
  1803 		}
       
  1804 		if (subret > 0 || !strcmp((char*)lfn.name, ".")
       
  1805 			|| !strcmp((char*)lfn.name, ".."))
       
  1806 		    continue;
       
  1807 	    }
       
  1808 	    lfn.checksum = 0x100; /* cannot use long name twice */
       
  1809 
       
  1810 	    if (path_len + 1 + lfn.len >= PATH_MAX) {
       
  1811 		fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
       
  1812 		goto fail;
       
  1813 	    }
       
  1814             pstrcpy(path2 + path_len + 1, sizeof(path2) - path_len - 1,
       
  1815                     (char*)lfn.name);
       
  1816 
       
  1817 	    if (is_directory(direntries + i)) {
       
  1818 		if (begin_of_direntry(direntries + i) == 0) {
       
  1819 		    DLOG(fprintf(stderr, "invalid begin for directory: %s\n", path2); print_direntry(direntries + i));
       
  1820 		    goto fail;
       
  1821 		}
       
  1822 		cluster_count = check_directory_consistency(s,
       
  1823 			begin_of_direntry(direntries + i), path2);
       
  1824 		if (cluster_count == 0) {
       
  1825 		    DLOG(fprintf(stderr, "problem in directory %s:\n", path2); print_direntry(direntries + i));
       
  1826 		    goto fail;
       
  1827 		}
       
  1828 	    } else if (is_file(direntries + i)) {
       
  1829 		/* check file size with FAT */
       
  1830 		cluster_count = get_cluster_count_for_direntry(s, direntries + i, path2);
       
  1831 		if (cluster_count !=
       
  1832 			(le32_to_cpu(direntries[i].size) + s->cluster_size
       
  1833 			 - 1) / s->cluster_size) {
       
  1834 		    DLOG(fprintf(stderr, "Cluster count mismatch\n"));
       
  1835 		    goto fail;
       
  1836 		}
       
  1837 	    } else
       
  1838 		assert(0); /* cluster_count = 0; */
       
  1839 
       
  1840 	    ret += cluster_count;
       
  1841 	}
       
  1842 
       
  1843 	cluster_num = modified_fat_get(s, cluster_num);
       
  1844     } while(!fat_eof(s, cluster_num));
       
  1845 
       
  1846     free(cluster);
       
  1847     return ret;
       
  1848 }
       
  1849 
       
  1850 /* returns 1 on success */
       
  1851 static int is_consistent(BDRVVVFATState* s)
       
  1852 {
       
  1853     int i, check;
       
  1854     int used_clusters_count = 0;
       
  1855 
       
  1856 DLOG(checkpoint());
       
  1857     /*
       
  1858      * - get modified FAT
       
  1859      * - compare the two FATs (TODO)
       
  1860      * - get buffer for marking used clusters
       
  1861      * - recurse direntries from root (using bs->bdrv_read to make
       
  1862      *    sure to get the new data)
       
  1863      *   - check that the FAT agrees with the size
       
  1864      *   - count the number of clusters occupied by this directory and
       
  1865      *     its files
       
  1866      * - check that the cumulative used cluster count agrees with the
       
  1867      *   FAT
       
  1868      * - if all is fine, return number of used clusters
       
  1869      */
       
  1870     if (s->fat2 == NULL) {
       
  1871 	int size = 0x200 * s->sectors_per_fat;
       
  1872 	s->fat2 = malloc(size);
       
  1873 	memcpy(s->fat2, s->fat.pointer, size);
       
  1874     }
       
  1875     check = vvfat_read(s->bs,
       
  1876 	    s->first_sectors_number, s->fat2, s->sectors_per_fat);
       
  1877     if (check) {
       
  1878 	fprintf(stderr, "Could not copy fat\n");
       
  1879 	return 0;
       
  1880     }
       
  1881     assert (s->used_clusters);
       
  1882     for (i = 0; i < sector2cluster(s, s->sector_count); i++)
       
  1883 	s->used_clusters[i] &= ~USED_ANY;
       
  1884 
       
  1885     clear_commits(s);
       
  1886 
       
  1887     /* mark every mapped file/directory as deleted.
       
  1888      * (check_directory_consistency() will unmark those still present). */
       
  1889     if (s->qcow)
       
  1890 	for (i = 0; i < s->mapping.next; i++) {
       
  1891 	    mapping_t* mapping = array_get(&(s->mapping), i);
       
  1892 	    if (mapping->first_mapping_index < 0)
       
  1893 		mapping->mode |= MODE_DELETED;
       
  1894 	}
       
  1895 
       
  1896     used_clusters_count = check_directory_consistency(s, 0, s->path);
       
  1897     if (used_clusters_count <= 0) {
       
  1898 	DLOG(fprintf(stderr, "problem in directory\n"));
       
  1899 	return 0;
       
  1900     }
       
  1901 
       
  1902     check = s->last_cluster_of_root_directory;
       
  1903     for (i = check; i < sector2cluster(s, s->sector_count); i++) {
       
  1904 	if (modified_fat_get(s, i)) {
       
  1905 	    if(!s->used_clusters[i]) {
       
  1906 		DLOG(fprintf(stderr, "FAT was modified (%d), but cluster is not used?\n", i));
       
  1907 		return 0;
       
  1908 	    }
       
  1909 	    check++;
       
  1910 	}
       
  1911 
       
  1912 	if (s->used_clusters[i] == USED_ALLOCATED) {
       
  1913 	    /* allocated, but not used... */
       
  1914 	    DLOG(fprintf(stderr, "unused, modified cluster: %d\n", i));
       
  1915 	    return 0;
       
  1916 	}
       
  1917     }
       
  1918 
       
  1919     if (check != used_clusters_count)
       
  1920 	return 0;
       
  1921 
       
  1922     return used_clusters_count;
       
  1923 }
       
  1924 
       
  1925 static inline void adjust_mapping_indices(BDRVVVFATState* s,
       
  1926 	int offset, int adjust)
       
  1927 {
       
  1928     int i;
       
  1929 
       
  1930     for (i = 0; i < s->mapping.next; i++) {
       
  1931 	mapping_t* mapping = array_get(&(s->mapping), i);
       
  1932 
       
  1933 #define ADJUST_MAPPING_INDEX(name) \
       
  1934 	if (mapping->name >= offset) \
       
  1935 	    mapping->name += adjust
       
  1936 
       
  1937 	ADJUST_MAPPING_INDEX(first_mapping_index);
       
  1938 	if (mapping->mode & MODE_DIRECTORY)
       
  1939 	    ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
       
  1940     }
       
  1941 }
       
  1942 
       
  1943 /* insert or update mapping */
       
  1944 static mapping_t* insert_mapping(BDRVVVFATState* s,
       
  1945 	uint32_t begin, uint32_t end)
       
  1946 {
       
  1947     /*
       
  1948      * - find mapping where mapping->begin >= begin,
       
  1949      * - if mapping->begin > begin: insert
       
  1950      *   - adjust all references to mappings!
       
  1951      * - else: adjust
       
  1952      * - replace name
       
  1953      */
       
  1954     int index = find_mapping_for_cluster_aux(s, begin, 0, s->mapping.next);
       
  1955     mapping_t* mapping = NULL;
       
  1956     mapping_t* first_mapping = array_get(&(s->mapping), 0);
       
  1957 
       
  1958     if (index < s->mapping.next && (mapping = array_get(&(s->mapping), index))
       
  1959 	    && mapping->begin < begin) {
       
  1960 	mapping->end = begin;
       
  1961 	index++;
       
  1962 	mapping = array_get(&(s->mapping), index);
       
  1963     }
       
  1964     if (index >= s->mapping.next || mapping->begin > begin) {
       
  1965 	mapping = array_insert(&(s->mapping), index, 1);
       
  1966 	mapping->path = NULL;
       
  1967 	adjust_mapping_indices(s, index, +1);
       
  1968     }
       
  1969 
       
  1970     mapping->begin = begin;
       
  1971     mapping->end = end;
       
  1972 
       
  1973 DLOG(mapping_t* next_mapping;
       
  1974 assert(index + 1 >= s->mapping.next ||
       
  1975 ((next_mapping = array_get(&(s->mapping), index + 1)) &&
       
  1976  next_mapping->begin >= end)));
       
  1977 
       
  1978     if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
       
  1979 	s->current_mapping = array_get(&(s->mapping),
       
  1980 		s->current_mapping - first_mapping);
       
  1981 
       
  1982     return mapping;
       
  1983 }
       
  1984 
       
  1985 static int remove_mapping(BDRVVVFATState* s, int mapping_index)
       
  1986 {
       
  1987     mapping_t* mapping = array_get(&(s->mapping), mapping_index);
       
  1988     mapping_t* first_mapping = array_get(&(s->mapping), 0);
       
  1989 
       
  1990     /* free mapping */
       
  1991     if (mapping->first_mapping_index < 0)
       
  1992 	free(mapping->path);
       
  1993 
       
  1994     /* remove from s->mapping */
       
  1995     array_remove(&(s->mapping), mapping_index);
       
  1996 
       
  1997     /* adjust all references to mappings */
       
  1998     adjust_mapping_indices(s, mapping_index, -1);
       
  1999 
       
  2000     if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
       
  2001 	s->current_mapping = array_get(&(s->mapping),
       
  2002 		s->current_mapping - first_mapping);
       
  2003 
       
  2004     return 0;
       
  2005 }
       
  2006 
       
  2007 static void adjust_dirindices(BDRVVVFATState* s, int offset, int adjust)
       
  2008 {
       
  2009     int i;
       
  2010     for (i = 0; i < s->mapping.next; i++) {
       
  2011 	mapping_t* mapping = array_get(&(s->mapping), i);
       
  2012 	if (mapping->dir_index >= offset)
       
  2013 	    mapping->dir_index += adjust;
       
  2014 	if ((mapping->mode & MODE_DIRECTORY) &&
       
  2015 		mapping->info.dir.first_dir_index >= offset)
       
  2016 	    mapping->info.dir.first_dir_index += adjust;
       
  2017     }
       
  2018 }
       
  2019 
       
  2020 static direntry_t* insert_direntries(BDRVVVFATState* s,
       
  2021 	int dir_index, int count)
       
  2022 {
       
  2023     /*
       
  2024      * make room in s->directory,
       
  2025      * adjust_dirindices
       
  2026      */
       
  2027     direntry_t* result = array_insert(&(s->directory), dir_index, count);
       
  2028     if (result == NULL)
       
  2029 	return NULL;
       
  2030     adjust_dirindices(s, dir_index, count);
       
  2031     return result;
       
  2032 }
       
  2033 
       
  2034 static int remove_direntries(BDRVVVFATState* s, int dir_index, int count)
       
  2035 {
       
  2036     int ret = array_remove_slice(&(s->directory), dir_index, count);
       
  2037     if (ret)
       
  2038 	return ret;
       
  2039     adjust_dirindices(s, dir_index, -count);
       
  2040     return 0;
       
  2041 }
       
  2042 
       
  2043 /*
       
  2044  * Adapt the mappings of the cluster chain starting at first cluster
       
  2045  * (i.e. if a file starts at first_cluster, the chain is followed according
       
  2046  * to the modified fat, and the corresponding entries in s->mapping are
       
  2047  * adjusted)
       
  2048  */
       
  2049 static int commit_mappings(BDRVVVFATState* s,
       
  2050 	uint32_t first_cluster, int dir_index)
       
  2051 {
       
  2052     mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
       
  2053     direntry_t* direntry = array_get(&(s->directory), dir_index);
       
  2054     uint32_t cluster = first_cluster;
       
  2055 
       
  2056     vvfat_close_current_file(s);
       
  2057 
       
  2058     assert(mapping);
       
  2059     assert(mapping->begin == first_cluster);
       
  2060     mapping->first_mapping_index = -1;
       
  2061     mapping->dir_index = dir_index;
       
  2062     mapping->mode = (dir_index <= 0 || is_directory(direntry)) ?
       
  2063 	MODE_DIRECTORY : MODE_NORMAL;
       
  2064 
       
  2065     while (!fat_eof(s, cluster)) {
       
  2066 	uint32_t c, c1;
       
  2067 
       
  2068 	for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
       
  2069 		c = c1, c1 = modified_fat_get(s, c1));
       
  2070 
       
  2071 	c++;
       
  2072 	if (c > mapping->end) {
       
  2073 	    int index = array_index(&(s->mapping), mapping);
       
  2074 	    int i, max_i = s->mapping.next - index;
       
  2075 	    for (i = 1; i < max_i && mapping[i].begin < c; i++);
       
  2076 	    while (--i > 0)
       
  2077 		remove_mapping(s, index + 1);
       
  2078 	}
       
  2079 	assert(mapping == array_get(&(s->mapping), s->mapping.next - 1)
       
  2080 		|| mapping[1].begin >= c);
       
  2081 	mapping->end = c;
       
  2082 
       
  2083 	if (!fat_eof(s, c1)) {
       
  2084 	    int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next);
       
  2085 	    mapping_t* next_mapping = i >= s->mapping.next ? NULL :
       
  2086 		array_get(&(s->mapping), i);
       
  2087 
       
  2088 	    if (next_mapping == NULL || next_mapping->begin > c1) {
       
  2089 		int i1 = array_index(&(s->mapping), mapping);
       
  2090 
       
  2091 		next_mapping = insert_mapping(s, c1, c1+1);
       
  2092 
       
  2093 		if (c1 < c)
       
  2094 		    i1++;
       
  2095 		mapping = array_get(&(s->mapping), i1);
       
  2096 	    }
       
  2097 
       
  2098 	    next_mapping->dir_index = mapping->dir_index;
       
  2099 	    next_mapping->first_mapping_index =
       
  2100 		mapping->first_mapping_index < 0 ?
       
  2101 		array_index(&(s->mapping), mapping) :
       
  2102 		mapping->first_mapping_index;
       
  2103 	    next_mapping->path = mapping->path;
       
  2104 	    next_mapping->mode = mapping->mode;
       
  2105 	    next_mapping->read_only = mapping->read_only;
       
  2106 	    if (mapping->mode & MODE_DIRECTORY) {
       
  2107 		next_mapping->info.dir.parent_mapping_index =
       
  2108 			mapping->info.dir.parent_mapping_index;
       
  2109 		next_mapping->info.dir.first_dir_index =
       
  2110 			mapping->info.dir.first_dir_index +
       
  2111 			0x10 * s->sectors_per_cluster *
       
  2112 			(mapping->end - mapping->begin);
       
  2113 	    } else
       
  2114 		next_mapping->info.file.offset = mapping->info.file.offset +
       
  2115 			mapping->end - mapping->begin;
       
  2116 
       
  2117 	    mapping = next_mapping;
       
  2118 	}
       
  2119 
       
  2120 	cluster = c1;
       
  2121     }
       
  2122 
       
  2123     return 0;
       
  2124 }
       
  2125 
       
  2126 static int commit_direntries(BDRVVVFATState* s,
       
  2127 	int dir_index, int parent_mapping_index)
       
  2128 {
       
  2129     direntry_t* direntry = array_get(&(s->directory), dir_index);
       
  2130     uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
       
  2131     mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
       
  2132 
       
  2133     int factor = 0x10 * s->sectors_per_cluster;
       
  2134     int old_cluster_count, new_cluster_count;
       
  2135     int current_dir_index = mapping->info.dir.first_dir_index;
       
  2136     int first_dir_index = current_dir_index;
       
  2137     int ret, i;
       
  2138     uint32_t c;
       
  2139 
       
  2140 DLOG(fprintf(stderr, "commit_direntries for %s, parent_mapping_index %d\n", mapping->path, parent_mapping_index));
       
  2141 
       
  2142     assert(direntry);
       
  2143     assert(mapping);
       
  2144     assert(mapping->begin == first_cluster);
       
  2145     assert(mapping->info.dir.first_dir_index < s->directory.next);
       
  2146     assert(mapping->mode & MODE_DIRECTORY);
       
  2147     assert(dir_index == 0 || is_directory(direntry));
       
  2148 
       
  2149     mapping->info.dir.parent_mapping_index = parent_mapping_index;
       
  2150 
       
  2151     if (first_cluster == 0) {
       
  2152 	old_cluster_count = new_cluster_count =
       
  2153 	    s->last_cluster_of_root_directory;
       
  2154     } else {
       
  2155 	for (old_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
       
  2156 		c = fat_get(s, c))
       
  2157 	    old_cluster_count++;
       
  2158 
       
  2159 	for (new_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
       
  2160 		c = modified_fat_get(s, c))
       
  2161 	    new_cluster_count++;
       
  2162     }
       
  2163 
       
  2164     if (new_cluster_count > old_cluster_count) {
       
  2165 	if (insert_direntries(s,
       
  2166 		current_dir_index + factor * old_cluster_count,
       
  2167 		factor * (new_cluster_count - old_cluster_count)) == NULL)
       
  2168 	    return -1;
       
  2169     } else if (new_cluster_count < old_cluster_count)
       
  2170 	remove_direntries(s,
       
  2171 		current_dir_index + factor * new_cluster_count,
       
  2172 		factor * (old_cluster_count - new_cluster_count));
       
  2173 
       
  2174     for (c = first_cluster; !fat_eof(s, c); c = modified_fat_get(s, c)) {
       
  2175 	void* direntry = array_get(&(s->directory), current_dir_index);
       
  2176 	int ret = vvfat_read(s->bs, cluster2sector(s, c), direntry,
       
  2177 		s->sectors_per_cluster);
       
  2178 	if (ret)
       
  2179 	    return ret;
       
  2180 	assert(!strncmp(s->directory.pointer, "QEMU", 4));
       
  2181 	current_dir_index += factor;
       
  2182     }
       
  2183 
       
  2184     ret = commit_mappings(s, first_cluster, dir_index);
       
  2185     if (ret)
       
  2186 	return ret;
       
  2187 
       
  2188     /* recurse */
       
  2189     for (i = 0; i < factor * new_cluster_count; i++) {
       
  2190 	direntry = array_get(&(s->directory), first_dir_index + i);
       
  2191 	if (is_directory(direntry) && !is_dot(direntry)) {
       
  2192 	    mapping = find_mapping_for_cluster(s, first_cluster);
       
  2193 	    assert(mapping->mode & MODE_DIRECTORY);
       
  2194 	    ret = commit_direntries(s, first_dir_index + i,
       
  2195 		array_index(&(s->mapping), mapping));
       
  2196 	    if (ret)
       
  2197 		return ret;
       
  2198 	}
       
  2199     }
       
  2200 
       
  2201     return 0;
       
  2202 }
       
  2203 
       
  2204 /* commit one file (adjust contents, adjust mapping),
       
  2205    return first_mapping_index */
       
  2206 static int commit_one_file(BDRVVVFATState* s,
       
  2207 	int dir_index, uint32_t offset)
       
  2208 {
       
  2209     direntry_t* direntry = array_get(&(s->directory), dir_index);
       
  2210     uint32_t c = begin_of_direntry(direntry);
       
  2211     uint32_t first_cluster = c;
       
  2212     mapping_t* mapping = find_mapping_for_cluster(s, c);
       
  2213     uint32_t size = filesize_of_direntry(direntry);
       
  2214     char* cluster = malloc(s->cluster_size);
       
  2215     uint32_t i;
       
  2216     int fd = 0;
       
  2217 
       
  2218     assert(offset < size);
       
  2219     assert((offset % s->cluster_size) == 0);
       
  2220 
       
  2221     for (i = s->cluster_size; i < offset; i += s->cluster_size)
       
  2222 	c = modified_fat_get(s, c);
       
  2223 
       
  2224     fd = open(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666);
       
  2225     if (fd < 0) {
       
  2226 	fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path,
       
  2227 		strerror(errno), errno);
       
  2228 	return fd;
       
  2229     }
       
  2230     if (offset > 0)
       
  2231 	if (lseek(fd, offset, SEEK_SET) != offset)
       
  2232 	    return -3;
       
  2233 
       
  2234     while (offset < size) {
       
  2235 	uint32_t c1;
       
  2236 	int rest_size = (size - offset > s->cluster_size ?
       
  2237 		s->cluster_size : size - offset);
       
  2238 	int ret;
       
  2239 
       
  2240 	c1 = modified_fat_get(s, c);
       
  2241 
       
  2242 	assert((size - offset == 0 && fat_eof(s, c)) ||
       
  2243 		(size > offset && c >=2 && !fat_eof(s, c)));
       
  2244 
       
  2245 	ret = vvfat_read(s->bs, cluster2sector(s, c),
       
  2246 	    (uint8_t*)cluster, (rest_size + 0x1ff) / 0x200);
       
  2247 
       
  2248 	if (ret < 0)
       
  2249 	    return ret;
       
  2250 
       
  2251 	if (write(fd, cluster, rest_size) < 0)
       
  2252 	    return -2;
       
  2253 
       
  2254 	offset += rest_size;
       
  2255 	c = c1;
       
  2256     }
       
  2257 
       
  2258     ftruncate(fd, size);
       
  2259     close(fd);
       
  2260 
       
  2261     return commit_mappings(s, first_cluster, dir_index);
       
  2262 }
       
  2263 
       
  2264 #ifdef DEBUG
       
  2265 /* test, if all mappings point to valid direntries */
       
  2266 static void check1(BDRVVVFATState* s)
       
  2267 {
       
  2268     int i;
       
  2269     for (i = 0; i < s->mapping.next; i++) {
       
  2270 	mapping_t* mapping = array_get(&(s->mapping), i);
       
  2271 	if (mapping->mode & MODE_DELETED) {
       
  2272 	    fprintf(stderr, "deleted\n");
       
  2273 	    continue;
       
  2274 	}
       
  2275 	assert(mapping->dir_index >= 0);
       
  2276 	assert(mapping->dir_index < s->directory.next);
       
  2277 	direntry_t* direntry = array_get(&(s->directory), mapping->dir_index);
       
  2278 	assert(mapping->begin == begin_of_direntry(direntry) || mapping->first_mapping_index >= 0);
       
  2279 	if (mapping->mode & MODE_DIRECTORY) {
       
  2280 	    assert(mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster * (mapping->end - mapping->begin) <= s->directory.next);
       
  2281 	    assert((mapping->info.dir.first_dir_index % (0x10 * s->sectors_per_cluster)) == 0);
       
  2282 	}
       
  2283     }
       
  2284 }
       
  2285 
       
  2286 /* test, if all direntries have mappings */
       
  2287 static void check2(BDRVVVFATState* s)
       
  2288 {
       
  2289     int i;
       
  2290     int first_mapping = -1;
       
  2291 
       
  2292     for (i = 0; i < s->directory.next; i++) {
       
  2293 	direntry_t* direntry = array_get(&(s->directory), i);
       
  2294 
       
  2295 	if (is_short_name(direntry) && begin_of_direntry(direntry)) {
       
  2296 	    mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
       
  2297 	    assert(mapping);
       
  2298 	    assert(mapping->dir_index == i || is_dot(direntry));
       
  2299 	    assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry));
       
  2300 	}
       
  2301 
       
  2302 	if ((i % (0x10 * s->sectors_per_cluster)) == 0) {
       
  2303 	    /* cluster start */
       
  2304 	    int j, count = 0;
       
  2305 
       
  2306 	    for (j = 0; j < s->mapping.next; j++) {
       
  2307 		mapping_t* mapping = array_get(&(s->mapping), j);
       
  2308 		if (mapping->mode & MODE_DELETED)
       
  2309 		    continue;
       
  2310 		if (mapping->mode & MODE_DIRECTORY) {
       
  2311 		    if (mapping->info.dir.first_dir_index <= i && mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster > i) {
       
  2312 			assert(++count == 1);
       
  2313 			if (mapping->first_mapping_index == -1)
       
  2314 			    first_mapping = array_index(&(s->mapping), mapping);
       
  2315 			else
       
  2316 			    assert(first_mapping == mapping->first_mapping_index);
       
  2317 			if (mapping->info.dir.parent_mapping_index < 0)
       
  2318 			    assert(j == 0);
       
  2319 			else {
       
  2320 			    mapping_t* parent = array_get(&(s->mapping), mapping->info.dir.parent_mapping_index);
       
  2321 			    assert(parent->mode & MODE_DIRECTORY);
       
  2322 			    assert(parent->info.dir.first_dir_index < mapping->info.dir.first_dir_index);
       
  2323 			}
       
  2324 		    }
       
  2325 		}
       
  2326 	    }
       
  2327 	    if (count == 0)
       
  2328 		first_mapping = -1;
       
  2329 	}
       
  2330     }
       
  2331 }
       
  2332 #endif
       
  2333 
       
  2334 static int handle_renames_and_mkdirs(BDRVVVFATState* s)
       
  2335 {
       
  2336     int i;
       
  2337 
       
  2338 #ifdef DEBUG
       
  2339     fprintf(stderr, "handle_renames\n");
       
  2340     for (i = 0; i < s->commits.next; i++) {
       
  2341 	commit_t* commit = array_get(&(s->commits), i);
       
  2342 	fprintf(stderr, "%d, %s (%d, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action);
       
  2343     }
       
  2344 #endif
       
  2345 
       
  2346     for (i = 0; i < s->commits.next;) {
       
  2347 	commit_t* commit = array_get(&(s->commits), i);
       
  2348 	if (commit->action == ACTION_RENAME) {
       
  2349 	    mapping_t* mapping = find_mapping_for_cluster(s,
       
  2350 		    commit->param.rename.cluster);
       
  2351 	    char* old_path = mapping->path;
       
  2352 
       
  2353 	    assert(commit->path);
       
  2354 	    mapping->path = commit->path;
       
  2355 	    if (rename(old_path, mapping->path))
       
  2356 		return -2;
       
  2357 
       
  2358 	    if (mapping->mode & MODE_DIRECTORY) {
       
  2359 		int l1 = strlen(mapping->path);
       
  2360 		int l2 = strlen(old_path);
       
  2361 		int diff = l1 - l2;
       
  2362 		direntry_t* direntry = array_get(&(s->directory),
       
  2363 			mapping->info.dir.first_dir_index);
       
  2364 		uint32_t c = mapping->begin;
       
  2365 		int i = 0;
       
  2366 
       
  2367 		/* recurse */
       
  2368 		while (!fat_eof(s, c)) {
       
  2369 		    do {
       
  2370 			direntry_t* d = direntry + i;
       
  2371 
       
  2372 			if (is_file(d) || (is_directory(d) && !is_dot(d))) {
       
  2373 			    mapping_t* m = find_mapping_for_cluster(s,
       
  2374 				    begin_of_direntry(d));
       
  2375 			    int l = strlen(m->path);
       
  2376 			    char* new_path = malloc(l + diff + 1);
       
  2377 
       
  2378 			    assert(!strncmp(m->path, mapping->path, l2));
       
  2379 
       
  2380                             pstrcpy(new_path, l + diff + 1, mapping->path);
       
  2381                             pstrcpy(new_path + l1, l + diff + 1 - l1,
       
  2382                                     m->path + l2);
       
  2383 
       
  2384 			    schedule_rename(s, m->begin, new_path);
       
  2385 			}
       
  2386 			i++;
       
  2387 		    } while((i % (0x10 * s->sectors_per_cluster)) != 0);
       
  2388 		    c = fat_get(s, c);
       
  2389 		}
       
  2390 	    }
       
  2391 
       
  2392 	    free(old_path);
       
  2393 	    array_remove(&(s->commits), i);
       
  2394 	    continue;
       
  2395 	} else if (commit->action == ACTION_MKDIR) {
       
  2396 	    mapping_t* mapping;
       
  2397 	    int j, parent_path_len;
       
  2398 
       
  2399 #ifdef __MINGW32__
       
  2400             if (mkdir(commit->path))
       
  2401                 return -5;
       
  2402 #else
       
  2403             if (mkdir(commit->path, 0755))
       
  2404                 return -5;
       
  2405 #endif
       
  2406 
       
  2407 	    mapping = insert_mapping(s, commit->param.mkdir.cluster,
       
  2408 		    commit->param.mkdir.cluster + 1);
       
  2409 	    if (mapping == NULL)
       
  2410 		return -6;
       
  2411 
       
  2412 	    mapping->mode = MODE_DIRECTORY;
       
  2413 	    mapping->read_only = 0;
       
  2414 	    mapping->path = commit->path;
       
  2415 	    j = s->directory.next;
       
  2416 	    assert(j);
       
  2417 	    insert_direntries(s, s->directory.next,
       
  2418 		    0x10 * s->sectors_per_cluster);
       
  2419 	    mapping->info.dir.first_dir_index = j;
       
  2420 
       
  2421 	    parent_path_len = strlen(commit->path)
       
  2422 		- strlen(get_basename(commit->path)) - 1;
       
  2423 	    for (j = 0; j < s->mapping.next; j++) {
       
  2424 		mapping_t* m = array_get(&(s->mapping), j);
       
  2425 		if (m->first_mapping_index < 0 && m != mapping &&
       
  2426 			!strncmp(m->path, mapping->path, parent_path_len) &&
       
  2427 			strlen(m->path) == parent_path_len)
       
  2428 		    break;
       
  2429 	    }
       
  2430 	    assert(j < s->mapping.next);
       
  2431 	    mapping->info.dir.parent_mapping_index = j;
       
  2432 
       
  2433 	    array_remove(&(s->commits), i);
       
  2434 	    continue;
       
  2435 	}
       
  2436 
       
  2437 	i++;
       
  2438     }
       
  2439     return 0;
       
  2440 }
       
  2441 
       
  2442 /*
       
  2443  * TODO: make sure that the short name is not matching *another* file
       
  2444  */
       
  2445 static int handle_commits(BDRVVVFATState* s)
       
  2446 {
       
  2447     int i, fail = 0;
       
  2448 
       
  2449     vvfat_close_current_file(s);
       
  2450 
       
  2451     for (i = 0; !fail && i < s->commits.next; i++) {
       
  2452 	commit_t* commit = array_get(&(s->commits), i);
       
  2453 	switch(commit->action) {
       
  2454 	case ACTION_RENAME: case ACTION_MKDIR:
       
  2455 	    assert(0);
       
  2456 	    fail = -2;
       
  2457 	    break;
       
  2458 	case ACTION_WRITEOUT: {
       
  2459 	    direntry_t* entry = array_get(&(s->directory),
       
  2460 		    commit->param.writeout.dir_index);
       
  2461 	    uint32_t begin = begin_of_direntry(entry);
       
  2462 	    mapping_t* mapping = find_mapping_for_cluster(s, begin);
       
  2463 
       
  2464 	    assert(mapping);
       
  2465 	    assert(mapping->begin == begin);
       
  2466 	    assert(commit->path == NULL);
       
  2467 
       
  2468 	    if (commit_one_file(s, commit->param.writeout.dir_index,
       
  2469 			commit->param.writeout.modified_offset))
       
  2470 		fail = -3;
       
  2471 
       
  2472 	    break;
       
  2473 	}
       
  2474 	case ACTION_NEW_FILE: {
       
  2475 	    int begin = commit->param.new_file.first_cluster;
       
  2476 	    mapping_t* mapping = find_mapping_for_cluster(s, begin);
       
  2477 	    direntry_t* entry;
       
  2478 	    int i;
       
  2479 
       
  2480 	    /* find direntry */
       
  2481 	    for (i = 0; i < s->directory.next; i++) {
       
  2482 		entry = array_get(&(s->directory), i);
       
  2483 		if (is_file(entry) && begin_of_direntry(entry) == begin)
       
  2484 		    break;
       
  2485 	    }
       
  2486 
       
  2487 	    if (i >= s->directory.next) {
       
  2488 		fail = -6;
       
  2489 		continue;
       
  2490 	    }
       
  2491 
       
  2492 	    /* make sure there exists an initial mapping */
       
  2493 	    if (mapping && mapping->begin != begin) {
       
  2494 		mapping->end = begin;
       
  2495 		mapping = NULL;
       
  2496 	    }
       
  2497 	    if (mapping == NULL) {
       
  2498 		mapping = insert_mapping(s, begin, begin+1);
       
  2499 	    }
       
  2500 	    /* most members will be fixed in commit_mappings() */
       
  2501 	    assert(commit->path);
       
  2502 	    mapping->path = commit->path;
       
  2503 	    mapping->read_only = 0;
       
  2504 	    mapping->mode = MODE_NORMAL;
       
  2505 	    mapping->info.file.offset = 0;
       
  2506 
       
  2507 	    if (commit_one_file(s, i, 0))
       
  2508 		fail = -7;
       
  2509 
       
  2510 	    break;
       
  2511 	}
       
  2512 	default:
       
  2513 	    assert(0);
       
  2514 	}
       
  2515     }
       
  2516     if (i > 0 && array_remove_slice(&(s->commits), 0, i))
       
  2517 	return -1;
       
  2518     return fail;
       
  2519 }
       
  2520 
       
  2521 static int handle_deletes(BDRVVVFATState* s)
       
  2522 {
       
  2523     int i, deferred = 1, deleted = 1;
       
  2524 
       
  2525     /* delete files corresponding to mappings marked as deleted */
       
  2526     /* handle DELETEs and unused mappings (modified_fat_get(s, mapping->begin) == 0) */
       
  2527     while (deferred && deleted) {
       
  2528 	deferred = 0;
       
  2529 	deleted = 0;
       
  2530 
       
  2531 	for (i = 1; i < s->mapping.next; i++) {
       
  2532 	    mapping_t* mapping = array_get(&(s->mapping), i);
       
  2533 	    if (mapping->mode & MODE_DELETED) {
       
  2534 		direntry_t* entry = array_get(&(s->directory),
       
  2535 			mapping->dir_index);
       
  2536 
       
  2537 		if (is_free(entry)) {
       
  2538 		    /* remove file/directory */
       
  2539 		    if (mapping->mode & MODE_DIRECTORY) {
       
  2540 			int j, next_dir_index = s->directory.next,
       
  2541 			first_dir_index = mapping->info.dir.first_dir_index;
       
  2542 
       
  2543 			if (rmdir(mapping->path) < 0) {
       
  2544 			    if (errno == ENOTEMPTY) {
       
  2545 				deferred++;
       
  2546 				continue;
       
  2547 			    } else
       
  2548 				return -5;
       
  2549 			}
       
  2550 
       
  2551 			for (j = 1; j < s->mapping.next; j++) {
       
  2552 			    mapping_t* m = array_get(&(s->mapping), j);
       
  2553 			    if (m->mode & MODE_DIRECTORY &&
       
  2554 				    m->info.dir.first_dir_index >
       
  2555 				    first_dir_index &&
       
  2556 				    m->info.dir.first_dir_index <
       
  2557 				    next_dir_index)
       
  2558 				next_dir_index =
       
  2559 				    m->info.dir.first_dir_index;
       
  2560 			}
       
  2561 			remove_direntries(s, first_dir_index,
       
  2562 				next_dir_index - first_dir_index);
       
  2563 
       
  2564 			deleted++;
       
  2565 		    }
       
  2566 		} else {
       
  2567 		    if (unlink(mapping->path))
       
  2568 			return -4;
       
  2569 		    deleted++;
       
  2570 		}
       
  2571 		DLOG(fprintf(stderr, "DELETE (%d)\n", i); print_mapping(mapping); print_direntry(entry));
       
  2572 		remove_mapping(s, i);
       
  2573 	    }
       
  2574 	}
       
  2575     }
       
  2576 
       
  2577     return 0;
       
  2578 }
       
  2579 
       
  2580 /*
       
  2581  * synchronize mapping with new state:
       
  2582  *
       
  2583  * - copy FAT (with bdrv_read)
       
  2584  * - mark all filenames corresponding to mappings as deleted
       
  2585  * - recurse direntries from root (using bs->bdrv_read)
       
  2586  * - delete files corresponding to mappings marked as deleted
       
  2587  */
       
  2588 static int do_commit(BDRVVVFATState* s)
       
  2589 {
       
  2590     int ret = 0;
       
  2591 
       
  2592     /* the real meat are the commits. Nothing to do? Move along! */
       
  2593     if (s->commits.next == 0)
       
  2594 	return 0;
       
  2595 
       
  2596     vvfat_close_current_file(s);
       
  2597 
       
  2598     ret = handle_renames_and_mkdirs(s);
       
  2599     if (ret) {
       
  2600 	fprintf(stderr, "Error handling renames (%d)\n", ret);
       
  2601 	assert(0);
       
  2602 	return ret;
       
  2603     }
       
  2604 
       
  2605     /* copy FAT (with bdrv_read) */
       
  2606     memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
       
  2607 
       
  2608     /* recurse direntries from root (using bs->bdrv_read) */
       
  2609     ret = commit_direntries(s, 0, -1);
       
  2610     if (ret) {
       
  2611 	fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
       
  2612 	assert(0);
       
  2613 	return ret;
       
  2614     }
       
  2615 
       
  2616     ret = handle_commits(s);
       
  2617     if (ret) {
       
  2618 	fprintf(stderr, "Error handling commits (%d)\n", ret);
       
  2619 	assert(0);
       
  2620 	return ret;
       
  2621     }
       
  2622 
       
  2623     ret = handle_deletes(s);
       
  2624     if (ret) {
       
  2625 	fprintf(stderr, "Error deleting\n");
       
  2626         assert(0);
       
  2627 	return ret;
       
  2628     }
       
  2629 
       
  2630     s->qcow->drv->bdrv_make_empty(s->qcow);
       
  2631 
       
  2632     memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
       
  2633 
       
  2634 DLOG(checkpoint());
       
  2635     return 0;
       
  2636 }
       
  2637 
       
  2638 static int try_commit(BDRVVVFATState* s)
       
  2639 {
       
  2640     vvfat_close_current_file(s);
       
  2641 DLOG(checkpoint());
       
  2642     if(!is_consistent(s))
       
  2643 	return -1;
       
  2644     return do_commit(s);
       
  2645 }
       
  2646 
       
  2647 static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
       
  2648                     const uint8_t *buf, int nb_sectors)
       
  2649 {
       
  2650     BDRVVVFATState *s = bs->opaque;
       
  2651     int i, ret;
       
  2652 
       
  2653 DLOG(checkpoint());
       
  2654 
       
  2655     vvfat_close_current_file(s);
       
  2656 
       
  2657     /*
       
  2658      * Some sanity checks:
       
  2659      * - do not allow writing to the boot sector
       
  2660      * - do not allow to write non-ASCII filenames
       
  2661      */
       
  2662 
       
  2663     if (sector_num < s->first_sectors_number)
       
  2664 	return -1;
       
  2665 
       
  2666     for (i = sector2cluster(s, sector_num);
       
  2667 	    i <= sector2cluster(s, sector_num + nb_sectors - 1);) {
       
  2668 	mapping_t* mapping = find_mapping_for_cluster(s, i);
       
  2669 	if (mapping) {
       
  2670 	    if (mapping->read_only) {
       
  2671 		fprintf(stderr, "Tried to write to write-protected file %s\n",
       
  2672 			mapping->path);
       
  2673 		return -1;
       
  2674 	    }
       
  2675 
       
  2676 	    if (mapping->mode & MODE_DIRECTORY) {
       
  2677 		int begin = cluster2sector(s, i);
       
  2678 		int end = begin + s->sectors_per_cluster, k;
       
  2679 		int dir_index;
       
  2680 		const direntry_t* direntries;
       
  2681 		long_file_name lfn;
       
  2682 
       
  2683 		lfn_init(&lfn);
       
  2684 
       
  2685 		if (begin < sector_num)
       
  2686 		    begin = sector_num;
       
  2687 		if (end > sector_num + nb_sectors)
       
  2688 		    end = sector_num + nb_sectors;
       
  2689 		dir_index  = mapping->dir_index +
       
  2690 		    0x10 * (begin - mapping->begin * s->sectors_per_cluster);
       
  2691 		direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
       
  2692 
       
  2693 		for (k = 0; k < (end - begin) * 0x10; k++) {
       
  2694 		    /* do not allow non-ASCII filenames */
       
  2695 		    if (parse_long_name(&lfn, direntries + k) < 0) {
       
  2696 			fprintf(stderr, "Warning: non-ASCII filename\n");
       
  2697 			return -1;
       
  2698 		    }
       
  2699 		    /* no access to the direntry of a read-only file */
       
  2700 		    else if (is_short_name(direntries+k) &&
       
  2701 			    (direntries[k].attributes & 1)) {
       
  2702 			if (memcmp(direntries + k,
       
  2703 				    array_get(&(s->directory), dir_index + k),
       
  2704 				    sizeof(direntry_t))) {
       
  2705 			    fprintf(stderr, "Warning: tried to write to write-protected file\n");
       
  2706 			    return -1;
       
  2707 			}
       
  2708 		    }
       
  2709 		}
       
  2710 	    }
       
  2711 	    i = mapping->end;
       
  2712 	} else
       
  2713 	    i++;
       
  2714     }
       
  2715 
       
  2716     /*
       
  2717      * Use qcow backend. Commit later.
       
  2718      */
       
  2719 DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
       
  2720     ret = s->qcow->drv->bdrv_write(s->qcow, sector_num, buf, nb_sectors);
       
  2721     if (ret < 0) {
       
  2722 	fprintf(stderr, "Error writing to qcow backend\n");
       
  2723 	return ret;
       
  2724     }
       
  2725 
       
  2726     for (i = sector2cluster(s, sector_num);
       
  2727 	    i <= sector2cluster(s, sector_num + nb_sectors - 1); i++)
       
  2728 	if (i >= 0)
       
  2729 	    s->used_clusters[i] |= USED_ALLOCATED;
       
  2730 
       
  2731 DLOG(checkpoint());
       
  2732     /* TODO: add timeout */
       
  2733     try_commit(s);
       
  2734 
       
  2735 DLOG(checkpoint());
       
  2736     return 0;
       
  2737 }
       
  2738 
       
  2739 static int vvfat_is_allocated(BlockDriverState *bs,
       
  2740 	int64_t sector_num, int nb_sectors, int* n)
       
  2741 {
       
  2742     BDRVVVFATState* s = bs->opaque;
       
  2743     *n = s->sector_count - sector_num;
       
  2744     if (*n > nb_sectors)
       
  2745 	*n = nb_sectors;
       
  2746     else if (*n < 0)
       
  2747 	return 0;
       
  2748     return 1;
       
  2749 }
       
  2750 
       
  2751 static int write_target_commit(BlockDriverState *bs, int64_t sector_num,
       
  2752 	const uint8_t* buffer, int nb_sectors) {
       
  2753     BDRVVVFATState* s = bs->opaque;
       
  2754     return try_commit(s);
       
  2755 }
       
  2756 
       
  2757 static void write_target_close(BlockDriverState *bs) {
       
  2758     BDRVVVFATState* s = bs->opaque;
       
  2759     bdrv_delete(s->qcow);
       
  2760     free(s->qcow_filename);
       
  2761 }
       
  2762 
       
  2763 static BlockDriver vvfat_write_target = {
       
  2764     "vvfat_write_target", 0, NULL, NULL, NULL,
       
  2765     write_target_commit,
       
  2766     write_target_close,
       
  2767     NULL, NULL, NULL
       
  2768 };
       
  2769 
       
  2770 static int enable_write_target(BDRVVVFATState *s)
       
  2771 {
       
  2772     int size = sector2cluster(s, s->sector_count);
       
  2773     s->used_clusters = calloc(size, 1);
       
  2774 
       
  2775     array_init(&(s->commits), sizeof(commit_t));
       
  2776 
       
  2777     s->qcow_filename = malloc(1024);
       
  2778     get_tmp_filename(s->qcow_filename, 1024);
       
  2779     if (bdrv_create(&bdrv_qcow,
       
  2780 		s->qcow_filename, s->sector_count, "fat:", 0) < 0)
       
  2781 	return -1;
       
  2782     s->qcow = bdrv_new("");
       
  2783     if (s->qcow == NULL || bdrv_open(s->qcow, s->qcow_filename, 0) < 0)
       
  2784 	return -1;
       
  2785 
       
  2786 #ifndef _WIN32
       
  2787     unlink(s->qcow_filename);
       
  2788 #endif
       
  2789 
       
  2790     s->bs->backing_hd = calloc(sizeof(BlockDriverState), 1);
       
  2791     s->bs->backing_hd->drv = &vvfat_write_target;
       
  2792     s->bs->backing_hd->opaque = s;
       
  2793 
       
  2794     return 0;
       
  2795 }
       
  2796 
       
  2797 static void vvfat_close(BlockDriverState *bs)
       
  2798 {
       
  2799     BDRVVVFATState *s = bs->opaque;
       
  2800 
       
  2801     vvfat_close_current_file(s);
       
  2802     array_free(&(s->fat));
       
  2803     array_free(&(s->directory));
       
  2804     array_free(&(s->mapping));
       
  2805     if(s->cluster_buffer)
       
  2806         free(s->cluster_buffer);
       
  2807 }
       
  2808 
       
  2809 BlockDriver bdrv_vvfat = {
       
  2810     "vvfat",
       
  2811     sizeof(BDRVVVFATState),
       
  2812     NULL, /* no probe for protocols */
       
  2813     vvfat_open,
       
  2814     vvfat_read,
       
  2815     vvfat_write,
       
  2816     vvfat_close,
       
  2817     NULL, /* ??? Not sure if we can do any meaningful flushing.  */
       
  2818     NULL,
       
  2819     vvfat_is_allocated,
       
  2820     .protocol_name = "fat",
       
  2821 };
       
  2822 
       
  2823 #ifdef DEBUG
       
  2824 static void checkpoint(void) {
       
  2825     assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2);
       
  2826     check1(vvv);
       
  2827     check2(vvv);
       
  2828     assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY));
       
  2829 #if 0
       
  2830     if (((direntry_t*)vvv->directory.pointer)[1].attributes != 0xf)
       
  2831 	fprintf(stderr, "Nonono!\n");
       
  2832     mapping_t* mapping;
       
  2833     direntry_t* direntry;
       
  2834     assert(vvv->mapping.size >= vvv->mapping.item_size * vvv->mapping.next);
       
  2835     assert(vvv->directory.size >= vvv->directory.item_size * vvv->directory.next);
       
  2836     if (vvv->mapping.next<47)
       
  2837 	return;
       
  2838     assert((mapping = array_get(&(vvv->mapping), 47)));
       
  2839     assert(mapping->dir_index < vvv->directory.next);
       
  2840     direntry = array_get(&(vvv->directory), mapping->dir_index);
       
  2841     assert(!memcmp(direntry->name, "USB     H  ", 11) || direntry->name[0]==0);
       
  2842 #endif
       
  2843     return;
       
  2844     /* avoid compiler warnings: */
       
  2845     hexdump(NULL, 100);
       
  2846     remove_mapping(vvv, NULL);
       
  2847     print_mapping(NULL);
       
  2848     print_direntry(NULL);
       
  2849 }
       
  2850 #endif