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