0.8.0-alt1
[qemu] / 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             assert(mapping->mode & MODE_DELETED);
1582             mapping->mode &= ~MODE_DELETED;
1583
1584             const char* basename = get_basename(mapping->path);
1585
1586             assert(mapping->mode & MODE_NORMAL);
1587
1588             /* rename */
1589             if (strcmp(basename, basename2))
1590                 schedule_rename(s, cluster_num, strdup(path));
1591         } else if (is_file(direntry))
1592             /* new file */
1593             schedule_new_file(s, strdup(path), cluster_num);
1594         else {
1595             assert(0);
1596             return 0;
1597         }
1598     }
1599
1600     while(1) {
1601         if (s->qcow) {
1602             if (!copy_it && cluster_was_modified(s, cluster_num)) {
1603                 if (mapping == NULL ||
1604                         mapping->begin > cluster_num ||
1605                         mapping->end <= cluster_num)
1606                 mapping = find_mapping_for_cluster(s, cluster_num);
1607
1608
1609                 if (mapping &&
1610                         (mapping->mode & MODE_DIRECTORY) == 0) {
1611
1612                     /* was modified in qcow */
1613                     if (offset != mapping->info.file.offset + s->cluster_size
1614                             * (cluster_num - mapping->begin)) {
1615                         /* offset of this cluster in file chain has changed */
1616                         assert(0);
1617                         copy_it = 1;
1618                     } else if (offset == 0) {
1619                         const char* basename = get_basename(mapping->path);
1620
1621                         if (strcmp(basename, basename2))
1622                             copy_it = 1;
1623                         first_mapping_index = array_index(&(s->mapping), mapping);
1624                     }
1625
1626                     if (mapping->first_mapping_index != first_mapping_index
1627                             && mapping->info.file.offset > 0) {
1628                         assert(0);
1629                         copy_it = 1;
1630                     }
1631
1632                     /* need to write out? */
1633                     if (!was_modified && is_file(direntry)) {
1634                         was_modified = 1;
1635                         schedule_writeout(s, mapping->dir_index, offset);
1636                     }
1637                 }
1638             }
1639
1640             if (copy_it) {
1641                 int i, dummy;
1642                 /*
1643                  * This is horribly inefficient, but that is okay, since
1644                  * it is rarely executed, if at all.
1645                  */
1646                 int64_t offset = cluster2sector(s, cluster_num);
1647
1648                 vvfat_close_current_file(s);
1649                 for (i = 0; i < s->sectors_per_cluster; i++)
1650                     if (!s->qcow->drv->bdrv_is_allocated(s->qcow,
1651                                 offset + i, 1, &dummy)) {
1652                         if (vvfat_read(s->bs,
1653                                     offset, s->cluster_buffer, 1))
1654                             return -1;
1655                         if (s->qcow->drv->bdrv_write(s->qcow,
1656                                     offset, s->cluster_buffer, 1))
1657                             return -2;
1658                     }
1659             }
1660         }
1661
1662         ret++;
1663         if (s->used_clusters[cluster_num] & USED_ANY)
1664             return 0;
1665         s->used_clusters[cluster_num] = USED_FILE;
1666
1667         cluster_num = modified_fat_get(s, cluster_num);
1668
1669         if (fat_eof(s, cluster_num))
1670             return ret;
1671         else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
1672             return -1;
1673
1674         offset += s->cluster_size;
1675     }
1676 }
1677
1678 /*
1679  * This function looks at the modified data (qcow). 
1680  * It returns 0 upon inconsistency or error, and the number of clusters
1681  * used by the directory, its subdirectories and their files.
1682  */
1683 static int check_directory_consistency(BDRVVVFATState *s,
1684         int cluster_num, const char* path)
1685 {
1686     int ret = 0;
1687     unsigned char* cluster = malloc(s->cluster_size);
1688     direntry_t* direntries = (direntry_t*)cluster;
1689     mapping_t* mapping = find_mapping_for_cluster(s, cluster_num);
1690
1691     long_file_name lfn;
1692     int path_len = strlen(path);
1693     char path2[PATH_MAX];
1694
1695     assert(path_len < PATH_MAX); /* len was tested before! */
1696     strcpy(path2, path);
1697     path2[path_len] = '/';
1698     path2[path_len + 1] = '\0';
1699
1700     if (mapping) {
1701         const char* basename = get_basename(mapping->path);
1702         const char* basename2 = get_basename(path);
1703
1704         assert(mapping->mode & MODE_DIRECTORY);
1705
1706         assert(mapping->mode & MODE_DELETED);
1707         mapping->mode &= ~MODE_DELETED;
1708
1709         if (strcmp(basename, basename2))
1710             schedule_rename(s, cluster_num, strdup(path));
1711     } else
1712         /* new directory */
1713         schedule_mkdir(s, cluster_num, strdup(path));
1714                 
1715     lfn_init(&lfn);
1716     do {
1717         int i;
1718         int subret = 0;
1719
1720         ret++;
1721
1722         if (s->used_clusters[cluster_num] & USED_ANY) {
1723             fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
1724             return 0;
1725         }
1726         s->used_clusters[cluster_num] = USED_DIRECTORY;
1727
1728 DLOG(fprintf(stderr, "read cluster %d (sector %d)\n", (int)cluster_num, (int)cluster2sector(s, cluster_num)));
1729         subret = vvfat_read(s->bs, cluster2sector(s, cluster_num), cluster,
1730                 s->sectors_per_cluster);
1731         if (subret) {
1732             fprintf(stderr, "Error fetching direntries\n");
1733         fail:
1734             free(cluster);
1735             return 0;
1736         }
1737
1738         for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
1739             int cluster_count;
1740
1741 DLOG(fprintf(stderr, "check direntry %d: \n", i); print_direntry(direntries + i));
1742             if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
1743                     is_free(direntries + i))
1744                 continue;
1745
1746             subret = parse_long_name(&lfn, direntries + i);
1747             if (subret < 0) {
1748                 fprintf(stderr, "Error in long name\n");
1749                 goto fail;
1750             }
1751             if (subret == 0 || is_free(direntries + i))
1752                 continue;
1753
1754             if (fat_chksum(direntries+i) != lfn.checksum) {
1755                 subret = parse_short_name(s, &lfn, direntries + i);
1756                 if (subret < 0) {
1757                     fprintf(stderr, "Error in short name (%d)\n", subret);
1758                     goto fail;
1759                 }
1760                 if (subret > 0 || !strcmp(lfn.name, ".")
1761                         || !strcmp(lfn.name, ".."))
1762                     continue;
1763             }
1764             lfn.checksum = 0x100; /* cannot use long name twice */
1765
1766             if (path_len + 1 + lfn.len >= PATH_MAX) {
1767                 fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
1768                 goto fail;
1769             }
1770             strcpy(path2 + path_len + 1, lfn.name);
1771
1772             if (is_directory(direntries + i)) {
1773                 if (begin_of_direntry(direntries + i) == 0) {
1774                     DLOG(fprintf(stderr, "invalid begin for directory: %s\n", path2); print_direntry(direntries + i));
1775                     goto fail;
1776                 }
1777                 cluster_count = check_directory_consistency(s,
1778                         begin_of_direntry(direntries + i), path2);
1779                 if (cluster_count == 0) {
1780                     DLOG(fprintf(stderr, "problem in directory %s:\n", path2); print_direntry(direntries + i));
1781                     goto fail;
1782                 }
1783             } else if (is_file(direntries + i)) {
1784                 /* check file size with FAT */
1785                 cluster_count = get_cluster_count_for_direntry(s, direntries + i, path2);
1786                 if (cluster_count !=
1787                         (le32_to_cpu(direntries[i].size) + s->cluster_size
1788                          - 1) / s->cluster_size) {
1789                     DLOG(fprintf(stderr, "Cluster count mismatch\n"));
1790                     goto fail;
1791                 }
1792             } else
1793                 assert(0); /* cluster_count = 0; */
1794
1795             ret += cluster_count;
1796         }
1797
1798         cluster_num = modified_fat_get(s, cluster_num);
1799     } while(!fat_eof(s, cluster_num));
1800
1801     free(cluster);
1802     return ret;
1803 }
1804
1805 /* returns 1 on success */
1806 static int is_consistent(BDRVVVFATState* s)
1807 {
1808     int i, check;
1809     int used_clusters_count = 0;
1810
1811 DLOG(checkpoint());
1812     /*
1813      * - get modified FAT
1814      * - compare the two FATs (TODO)
1815      * - get buffer for marking used clusters
1816      * - recurse direntries from root (using bs->bdrv_read to make
1817      *    sure to get the new data)
1818      *   - check that the FAT agrees with the size
1819      *   - count the number of clusters occupied by this directory and
1820      *     its files
1821      * - check that the cumulative used cluster count agrees with the
1822      *   FAT
1823      * - if all is fine, return number of used clusters
1824      */
1825     if (s->fat2 == NULL) {
1826         int size = 0x200 * s->sectors_per_fat;
1827         s->fat2 = malloc(size);
1828         memcpy(s->fat2, s->fat.pointer, size);
1829     }
1830     check = vvfat_read(s->bs,
1831             s->first_sectors_number, s->fat2, s->sectors_per_fat);
1832     if (check) {
1833         fprintf(stderr, "Could not copy fat\n");
1834         return 0;
1835     }
1836     assert (s->used_clusters);
1837     for (i = 0; i < sector2cluster(s, s->sector_count); i++)
1838         s->used_clusters[i] &= ~USED_ANY;
1839
1840     clear_commits(s);
1841
1842     /* mark every mapped file/directory as deleted.
1843      * (check_directory_consistency() will unmark those still present). */
1844     if (s->qcow)
1845         for (i = 0; i < s->mapping.next; i++) {
1846             mapping_t* mapping = array_get(&(s->mapping), i);
1847             if (mapping->first_mapping_index < 0)
1848                 mapping->mode |= MODE_DELETED;
1849         }
1850
1851     used_clusters_count = check_directory_consistency(s, 0, s->path);
1852     if (used_clusters_count <= 0) {
1853         DLOG(fprintf(stderr, "problem in directory\n"));
1854         return 0;
1855     }
1856
1857     check = s->last_cluster_of_root_directory;
1858     for (i = check; i < sector2cluster(s, s->sector_count); i++) {
1859         if (modified_fat_get(s, i)) {
1860             if(!s->used_clusters[i]) {
1861                 DLOG(fprintf(stderr, "FAT was modified (%d), but cluster is not used?\n", i));
1862                 return 0;
1863             }
1864             check++;
1865         }
1866
1867         if (s->used_clusters[i] == USED_ALLOCATED) {
1868             /* allocated, but not used... */
1869             DLOG(fprintf(stderr, "unused, modified cluster: %d\n", i));
1870             return 0;
1871         }
1872     }
1873
1874     if (check != used_clusters_count)
1875         return 0;
1876
1877     return used_clusters_count;
1878 }
1879
1880 static inline void adjust_mapping_indices(BDRVVVFATState* s,
1881         int offset, int adjust)
1882 {
1883     int i;
1884
1885     for (i = 0; i < s->mapping.next; i++) {
1886         mapping_t* mapping = array_get(&(s->mapping), i);
1887
1888 #define ADJUST_MAPPING_INDEX(name) \
1889         if (mapping->name >= offset) \
1890             mapping->name += adjust
1891
1892         ADJUST_MAPPING_INDEX(first_mapping_index);
1893         if (mapping->mode & MODE_DIRECTORY)
1894             ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
1895     }
1896 }
1897
1898 /* insert or update mapping */
1899 static mapping_t* insert_mapping(BDRVVVFATState* s,
1900         uint32_t begin, uint32_t end)
1901 {
1902     /*
1903      * - find mapping where mapping->begin >= begin,
1904      * - if mapping->begin > begin: insert
1905      *   - adjust all references to mappings!
1906      * - else: adjust
1907      * - replace name
1908      */
1909     int index = find_mapping_for_cluster_aux(s, begin, 0, s->mapping.next);
1910     mapping_t* mapping = NULL;
1911     mapping_t* first_mapping = array_get(&(s->mapping), 0);
1912
1913     if (index < s->mapping.next && (mapping = array_get(&(s->mapping), index))
1914             && mapping->begin < begin) {
1915         mapping->end = begin;
1916         index++;
1917         mapping = array_get(&(s->mapping), index);
1918     }
1919     if (index >= s->mapping.next || mapping->begin > begin) {
1920         mapping = array_insert(&(s->mapping), index, 1);
1921         mapping->path = NULL;
1922         adjust_mapping_indices(s, index, +1);
1923     }
1924
1925     mapping->begin = begin;
1926     mapping->end = end;
1927
1928 DLOG(mapping_t* next_mapping;
1929 assert(index + 1 >= s->mapping.next ||
1930 ((next_mapping = array_get(&(s->mapping), index + 1)) &&
1931  next_mapping->begin >= end)));
1932
1933     if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1934         s->current_mapping = array_get(&(s->mapping),
1935                 s->current_mapping - first_mapping);
1936
1937     return mapping;
1938 }
1939
1940 static int remove_mapping(BDRVVVFATState* s, int mapping_index)
1941 {
1942     mapping_t* mapping = array_get(&(s->mapping), mapping_index);
1943     mapping_t* first_mapping = array_get(&(s->mapping), 0);
1944
1945     /* free mapping */
1946     if (mapping->first_mapping_index < 0)
1947         free(mapping->path);
1948
1949     /* remove from s->mapping */
1950     array_remove(&(s->mapping), mapping_index);
1951
1952     /* adjust all references to mappings */
1953     adjust_mapping_indices(s, mapping_index, -1);
1954
1955     if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1956         s->current_mapping = array_get(&(s->mapping),
1957                 s->current_mapping - first_mapping);
1958
1959     return 0;
1960 }
1961
1962 static void adjust_dirindices(BDRVVVFATState* s, int offset, int adjust)
1963 {
1964     int i;
1965     for (i = 0; i < s->mapping.next; i++) {
1966         mapping_t* mapping = array_get(&(s->mapping), i);
1967         if (mapping->dir_index >= offset)
1968             mapping->dir_index += adjust;
1969         if ((mapping->mode & MODE_DIRECTORY) &&
1970                 mapping->info.dir.first_dir_index >= offset)
1971             mapping->info.dir.first_dir_index += adjust;
1972     }
1973 }
1974
1975 static direntry_t* insert_direntries(BDRVVVFATState* s,
1976         int dir_index, int count)
1977 {
1978     /*
1979      * make room in s->directory,
1980      * adjust_dirindices
1981      */
1982     direntry_t* result = array_insert(&(s->directory), dir_index, count);
1983     if (result == NULL)
1984         return NULL;
1985     adjust_dirindices(s, dir_index, count);
1986     return result;
1987 }
1988
1989 static int remove_direntries(BDRVVVFATState* s, int dir_index, int count)
1990 {
1991     int ret = array_remove_slice(&(s->directory), dir_index, count);
1992     if (ret)
1993         return ret;
1994     adjust_dirindices(s, dir_index, -count);
1995     return 0;
1996 }
1997
1998 /*
1999  * Adapt the mappings of the cluster chain starting at first cluster
2000  * (i.e. if a file starts at first_cluster, the chain is followed according
2001  * to the modified fat, and the corresponding entries in s->mapping are
2002  * adjusted)
2003  */
2004 static int commit_mappings(BDRVVVFATState* s,
2005         uint32_t first_cluster, int dir_index)
2006 {
2007     mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2008     direntry_t* direntry = array_get(&(s->directory), dir_index);
2009     uint32_t cluster = first_cluster;
2010
2011     vvfat_close_current_file(s);
2012
2013     assert(mapping);
2014     assert(mapping->begin == first_cluster);
2015     mapping->first_mapping_index = -1;
2016     mapping->dir_index = dir_index;
2017     mapping->mode = (dir_index <= 0 || is_directory(direntry)) ?
2018         MODE_DIRECTORY : MODE_NORMAL;
2019
2020     while (!fat_eof(s, cluster)) {
2021         uint32_t c, c1;
2022
2023         for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
2024                 c = c1, c1 = modified_fat_get(s, c1));
2025
2026         c++;
2027         if (c > mapping->end) {
2028             int index = array_index(&(s->mapping), mapping);
2029             int i, max_i = s->mapping.next - index;
2030             for (i = 1; i < max_i && mapping[i].begin < c; i++);
2031             while (--i > 0)
2032                 remove_mapping(s, index + 1);
2033         }
2034         assert(mapping == array_get(&(s->mapping), s->mapping.next - 1)
2035                 || mapping[1].begin >= c);
2036         mapping->end = c;
2037
2038         if (!fat_eof(s, c1)) {
2039             int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next);
2040             mapping_t* next_mapping = i >= s->mapping.next ? NULL :
2041                 array_get(&(s->mapping), i);
2042
2043             if (next_mapping == NULL || next_mapping->begin > c1) {
2044                 int i1 = array_index(&(s->mapping), mapping);
2045
2046                 next_mapping = insert_mapping(s, c1, c1+1);
2047
2048                 if (c1 < c)
2049                     i1++;
2050                 mapping = array_get(&(s->mapping), i1);
2051             }
2052
2053             next_mapping->dir_index = mapping->dir_index;
2054             next_mapping->first_mapping_index = 
2055                 mapping->first_mapping_index < 0 ?
2056                 array_index(&(s->mapping), mapping) :
2057                 mapping->first_mapping_index;
2058             next_mapping->path = mapping->path;
2059             next_mapping->mode = mapping->mode;
2060             next_mapping->read_only = mapping->read_only;
2061             if (mapping->mode & MODE_DIRECTORY) {
2062                 next_mapping->info.dir.parent_mapping_index =
2063                         mapping->info.dir.parent_mapping_index;
2064                 next_mapping->info.dir.first_dir_index =
2065                         mapping->info.dir.first_dir_index +
2066                         0x10 * s->sectors_per_cluster *
2067                         (mapping->end - mapping->begin);
2068             } else
2069                 next_mapping->info.file.offset = mapping->info.file.offset +
2070                         mapping->end - mapping->begin;
2071
2072             mapping = next_mapping;
2073         }
2074                 
2075         cluster = c1;
2076     }
2077
2078     return 0;
2079 }
2080
2081 static int commit_direntries(BDRVVVFATState* s,
2082         int dir_index, int parent_mapping_index)
2083 {
2084     direntry_t* direntry = array_get(&(s->directory), dir_index);
2085     uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
2086     mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2087
2088     int factor = 0x10 * s->sectors_per_cluster;
2089     int old_cluster_count, new_cluster_count;
2090     int current_dir_index = mapping->info.dir.first_dir_index;
2091     int first_dir_index = current_dir_index;
2092     int ret, i;
2093     uint32_t c;
2094
2095 DLOG(fprintf(stderr, "commit_direntries for %s, parent_mapping_index %d\n", mapping->path, parent_mapping_index));
2096
2097     assert(direntry);
2098     assert(mapping);
2099     assert(mapping->begin == first_cluster);
2100     assert(mapping->info.dir.first_dir_index < s->directory.next);
2101     assert(mapping->mode & MODE_DIRECTORY);
2102     assert(dir_index == 0 || is_directory(direntry));
2103
2104     mapping->info.dir.parent_mapping_index = parent_mapping_index;
2105
2106     if (first_cluster == 0) {
2107         old_cluster_count = new_cluster_count =
2108             s->last_cluster_of_root_directory;
2109     } else {
2110         for (old_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2111                 c = fat_get(s, c))
2112             old_cluster_count++;
2113
2114         for (new_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2115                 c = modified_fat_get(s, c))
2116             new_cluster_count++;
2117     }
2118
2119     if (new_cluster_count > old_cluster_count) {
2120         if (insert_direntries(s,
2121                 current_dir_index + factor * old_cluster_count,
2122                 factor * (new_cluster_count - old_cluster_count)) == NULL)
2123             return -1;
2124     } else if (new_cluster_count < old_cluster_count)
2125         remove_direntries(s,
2126                 current_dir_index + factor * new_cluster_count,
2127                 factor * (old_cluster_count - new_cluster_count));
2128
2129     for (c = first_cluster; !fat_eof(s, c); c = modified_fat_get(s, c)) {
2130         void* direntry = array_get(&(s->directory), current_dir_index);
2131         int ret = vvfat_read(s->bs, cluster2sector(s, c), direntry,
2132                 s->sectors_per_cluster);
2133         if (ret)
2134             return ret;
2135         assert(!strncmp(s->directory.pointer, "QEMU", 4));
2136         current_dir_index += factor;
2137     }
2138
2139     ret = commit_mappings(s, first_cluster, dir_index);
2140     if (ret)
2141         return ret;
2142
2143     /* recurse */
2144     for (i = 0; i < factor * new_cluster_count; i++) {
2145         direntry = array_get(&(s->directory), first_dir_index + i);
2146         if (is_directory(direntry) && !is_dot(direntry)) {
2147             mapping = find_mapping_for_cluster(s, first_cluster);
2148             assert(mapping->mode & MODE_DIRECTORY);
2149             ret = commit_direntries(s, first_dir_index + i,
2150                 array_index(&(s->mapping), mapping));
2151             if (ret)
2152                 return ret;
2153         }
2154     }
2155
2156     return 0;
2157 }
2158
2159 /* commit one file (adjust contents, adjust mapping),
2160    return first_mapping_index */
2161 static int commit_one_file(BDRVVVFATState* s,
2162         int dir_index, uint32_t offset)
2163 {
2164     direntry_t* direntry = array_get(&(s->directory), dir_index);
2165     uint32_t c = begin_of_direntry(direntry);
2166     uint32_t first_cluster = c;
2167     mapping_t* mapping = find_mapping_for_cluster(s, c);
2168     uint32_t size = filesize_of_direntry(direntry);
2169     char* cluster = malloc(s->cluster_size);
2170     uint32_t i;
2171     int fd = 0;
2172
2173     assert(offset < size);
2174     assert((offset % s->cluster_size) == 0);
2175
2176     for (i = s->cluster_size; i < offset; i += s->cluster_size)
2177         c = modified_fat_get(s, c);
2178
2179     fd = open(mapping->path, O_RDWR | O_CREAT, 0666);
2180     if (fd < 0) {
2181         fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path,
2182                 strerror(errno), errno);
2183         return fd;
2184     }
2185     if (offset > 0)
2186         if (lseek(fd, offset, SEEK_SET) != offset)
2187             return -3;
2188
2189     while (offset < size) {
2190         uint32_t c1;
2191         int rest_size = (size - offset > s->cluster_size ?
2192                 s->cluster_size : size - offset);
2193         int ret;
2194
2195         c1 = modified_fat_get(s, c);
2196
2197         assert((size - offset == 0 && fat_eof(s, c)) ||
2198                 (size > offset && c >=2 && !fat_eof(s, c)));
2199         assert(size >= 0);
2200
2201         ret = vvfat_read(s->bs, cluster2sector(s, c),
2202             cluster, (rest_size + 0x1ff) / 0x200);
2203
2204         if (ret < 0)
2205             return ret;
2206
2207         if (write(fd, cluster, rest_size) < 0)
2208             return -2;
2209
2210         offset += rest_size;
2211         c = c1;
2212     }
2213
2214     ftruncate(fd, size);
2215     close(fd);
2216
2217     return commit_mappings(s, first_cluster, dir_index);
2218 }
2219
2220 #ifdef DEBUG
2221 /* test, if all mappings point to valid direntries */
2222 static void check1(BDRVVVFATState* s)
2223 {
2224     int i;
2225     for (i = 0; i < s->mapping.next; i++) {
2226         mapping_t* mapping = array_get(&(s->mapping), i);
2227         if (mapping->mode & MODE_DELETED) {
2228             fprintf(stderr, "deleted\n");
2229             continue;
2230         }
2231         assert(mapping->dir_index >= 0);
2232         assert(mapping->dir_index < s->directory.next);
2233         direntry_t* direntry = array_get(&(s->directory), mapping->dir_index);
2234         assert(mapping->begin == begin_of_direntry(direntry) || mapping->first_mapping_index >= 0);
2235         if (mapping->mode & MODE_DIRECTORY) {
2236             assert(mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster * (mapping->end - mapping->begin) <= s->directory.next);
2237             assert((mapping->info.dir.first_dir_index % (0x10 * s->sectors_per_cluster)) == 0);
2238         }
2239     }
2240 }
2241
2242 /* test, if all direntries have mappings */
2243 static void check2(BDRVVVFATState* s)
2244 {
2245     int i;
2246     int first_mapping = -1;
2247
2248     for (i = 0; i < s->directory.next; i++) {
2249         direntry_t* direntry = array_get(&(s->directory), i);
2250
2251         if (is_short_name(direntry) && begin_of_direntry(direntry)) {
2252             mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
2253             assert(mapping);
2254             assert(mapping->dir_index == i || is_dot(direntry));
2255             assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry));
2256         }
2257
2258         if ((i % (0x10 * s->sectors_per_cluster)) == 0) {
2259             /* cluster start */
2260             int j, count = 0;
2261
2262             for (j = 0; j < s->mapping.next; j++) {
2263                 mapping_t* mapping = array_get(&(s->mapping), j);
2264                 if (mapping->mode & MODE_DELETED)
2265                     continue;
2266                 if (mapping->mode & MODE_DIRECTORY) {
2267                     if (mapping->info.dir.first_dir_index <= i && mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster > i) {
2268                         assert(++count == 1);
2269                         if (mapping->first_mapping_index == -1)
2270                             first_mapping = array_index(&(s->mapping), mapping);
2271                         else
2272                             assert(first_mapping == mapping->first_mapping_index);
2273                         if (mapping->info.dir.parent_mapping_index < 0)
2274                             assert(j == 0);
2275                         else {
2276                             mapping_t* parent = array_get(&(s->mapping), mapping->info.dir.parent_mapping_index);
2277                             assert(parent->mode & MODE_DIRECTORY);
2278                             assert(parent->info.dir.first_dir_index < mapping->info.dir.first_dir_index);
2279                         }
2280                     }
2281                 }
2282             }
2283             if (count == 0)
2284                 first_mapping = -1;
2285         }
2286     }
2287 }
2288 #endif
2289
2290 static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2291 {
2292     int i;
2293
2294 #ifdef DEBUG
2295     fprintf(stderr, "handle_renames\n");
2296     for (i = 0; i < s->commits.next; i++) {
2297         commit_t* commit = array_get(&(s->commits), i);
2298         fprintf(stderr, "%d, %s (%d, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action);
2299     }
2300 #endif
2301
2302     for (i = 0; i < s->commits.next;) {
2303         commit_t* commit = array_get(&(s->commits), i);
2304         if (commit->action == ACTION_RENAME) {
2305             mapping_t* mapping = find_mapping_for_cluster(s,
2306                     commit->param.rename.cluster);
2307             char* old_path = mapping->path;
2308
2309             assert(commit->path);
2310             mapping->path = commit->path;
2311             if (rename(old_path, mapping->path))
2312                 return -2;
2313
2314             if (mapping->mode & MODE_DIRECTORY) {
2315                 int l1 = strlen(mapping->path);
2316                 int l2 = strlen(old_path);
2317                 int diff = l1 - l2;
2318                 direntry_t* direntry = array_get(&(s->directory),
2319                         mapping->info.dir.first_dir_index);
2320                 uint32_t c = mapping->begin;
2321                 int i = 0;
2322
2323                 /* recurse */
2324                 while (!fat_eof(s, c)) {
2325                     do {
2326                         direntry_t* d = direntry + i;
2327
2328                         if (is_file(d) || (is_directory(d) && !is_dot(d))) {
2329                             mapping_t* m = find_mapping_for_cluster(s,
2330                                     begin_of_direntry(d));
2331                             int l = strlen(m->path);
2332                             char* new_path = malloc(l + diff + 1);
2333
2334                             assert(!strncmp(m->path, mapping->path, l2));
2335
2336                             strcpy(new_path, mapping->path);
2337                             strcpy(new_path + l1, m->path + l2);
2338
2339                             schedule_rename(s, m->begin, new_path);
2340                         }
2341                         i++;
2342                     } while((i % (0x10 * s->sectors_per_cluster)) != 0);
2343                     c = fat_get(s, c);
2344                 }
2345             }
2346
2347             free(old_path);
2348             array_remove(&(s->commits), i);
2349             continue;
2350         } else if (commit->action == ACTION_MKDIR) {
2351             mapping_t* mapping;
2352             int j, parent_path_len;
2353
2354 #ifdef __MINGW32__
2355             if (mkdir(commit->path))
2356                 return -5;
2357 #else
2358             if (mkdir(commit->path, 0755))
2359                 return -5;
2360 #endif
2361
2362             mapping = insert_mapping(s, commit->param.mkdir.cluster,
2363                     commit->param.mkdir.cluster + 1);
2364             if (mapping == NULL)
2365                 return -6;
2366
2367             mapping->mode = MODE_DIRECTORY;
2368             mapping->read_only = 0;
2369             mapping->path = commit->path;
2370             j = s->directory.next;
2371             assert(j);
2372             insert_direntries(s, s->directory.next,
2373                     0x10 * s->sectors_per_cluster);
2374             mapping->info.dir.first_dir_index = j;
2375
2376             parent_path_len = strlen(commit->path)
2377                 - strlen(get_basename(commit->path)) - 1;
2378             for (j = 0; j < s->mapping.next; j++) {
2379                 mapping_t* m = array_get(&(s->mapping), j);
2380                 if (m->first_mapping_index < 0 && m != mapping &&
2381                         !strncmp(m->path, mapping->path, parent_path_len) &&
2382                         strlen(m->path) == parent_path_len)
2383                     break;
2384             }
2385             assert(j < s->mapping.next);
2386             mapping->info.dir.parent_mapping_index = j;
2387
2388             array_remove(&(s->commits), i);
2389             continue;
2390         }
2391
2392         i++;
2393     }
2394     return 0;
2395 }
2396
2397 /*
2398  * TODO: make sure that the short name is not matching *another* file
2399  */
2400 static int handle_commits(BDRVVVFATState* s)
2401 {
2402     int i, fail = 0;
2403
2404     vvfat_close_current_file(s);
2405
2406     for (i = 0; !fail && i < s->commits.next; i++) {
2407         commit_t* commit = array_get(&(s->commits), i);
2408         switch(commit->action) {
2409         case ACTION_RENAME: case ACTION_MKDIR:
2410             assert(0);
2411             fail = -2;
2412             break;
2413         case ACTION_WRITEOUT: {
2414             direntry_t* entry = array_get(&(s->directory),
2415                     commit->param.writeout.dir_index);
2416             uint32_t begin = begin_of_direntry(entry);
2417             mapping_t* mapping = find_mapping_for_cluster(s, begin);
2418
2419             assert(mapping);
2420             assert(mapping->begin == begin);
2421             assert(commit->path == NULL);
2422
2423             if (commit_one_file(s, commit->param.writeout.dir_index,
2424                         commit->param.writeout.modified_offset))
2425                 fail = -3;
2426
2427             break;
2428         }
2429         case ACTION_NEW_FILE: {
2430             int begin = commit->param.new_file.first_cluster;
2431             mapping_t* mapping = find_mapping_for_cluster(s, begin);
2432             direntry_t* entry;
2433             int i;
2434
2435             /* find direntry */
2436             for (i = 0; i < s->directory.next; i++) {
2437                 entry = array_get(&(s->directory), i);
2438                 if (is_file(entry) && begin_of_direntry(entry) == begin)
2439                     break;
2440             }
2441
2442             if (i >= s->directory.next) {
2443                 fail = -6;
2444                 continue;
2445             }
2446
2447             /* make sure there exists an initial mapping */
2448             if (mapping && mapping->begin != begin) {
2449                 mapping->end = begin;
2450                 mapping = NULL;
2451             }
2452             if (mapping == NULL) {
2453                 mapping = insert_mapping(s, begin, begin+1);
2454             }
2455             /* most members will be fixed in commit_mappings() */
2456             assert(commit->path);
2457             mapping->path = commit->path;
2458             mapping->read_only = 0;
2459             mapping->mode = MODE_NORMAL;
2460             mapping->info.file.offset = 0;
2461
2462             if (commit_one_file(s, i, 0))
2463                 fail = -7;
2464
2465             break;
2466         }
2467         default:
2468             assert(0);
2469         }
2470     }
2471     if (i > 0 && array_remove_slice(&(s->commits), 0, i))
2472         return -1;
2473     return fail;
2474 }
2475
2476 static int handle_deletes(BDRVVVFATState* s)
2477 {
2478     int i, deferred = 1, deleted = 1;
2479
2480     /* delete files corresponding to mappings marked as deleted */
2481     /* handle DELETEs and unused mappings (modified_fat_get(s, mapping->begin) == 0) */
2482     while (deferred && deleted) {
2483         deferred = 0;
2484         deleted = 0;
2485
2486         for (i = 1; i < s->mapping.next; i++) {
2487             mapping_t* mapping = array_get(&(s->mapping), i);
2488             if (mapping->mode & MODE_DELETED) {
2489                 direntry_t* entry = array_get(&(s->directory),
2490                         mapping->dir_index);
2491
2492                 if (is_free(entry)) {
2493                     /* remove file/directory */
2494                     if (mapping->mode & MODE_DIRECTORY) {
2495                         int j, next_dir_index = s->directory.next,
2496                         first_dir_index = mapping->info.dir.first_dir_index;
2497
2498                         if (rmdir(mapping->path) < 0) {
2499                             if (errno == ENOTEMPTY) {
2500                                 deferred++;
2501                                 continue;
2502                             } else
2503                                 return -5;
2504                         }
2505
2506                         for (j = 1; j < s->mapping.next; j++) {
2507                             mapping_t* m = array_get(&(s->mapping), j);
2508                             if (m->mode & MODE_DIRECTORY &&
2509                                     m->info.dir.first_dir_index >
2510                                     first_dir_index &&
2511                                     m->info.dir.first_dir_index <
2512                                     next_dir_index)
2513                                 next_dir_index =
2514                                     m->info.dir.first_dir_index;
2515                         }
2516                         remove_direntries(s, first_dir_index,
2517                                 next_dir_index - first_dir_index);
2518
2519                         deleted++;
2520                     }
2521                 } else {
2522                     if (unlink(mapping->path))
2523                         return -4;
2524                     deleted++;
2525                 }
2526                 DLOG(fprintf(stderr, "DELETE (%d)\n", i); print_mapping(mapping); print_direntry(entry));
2527                 remove_mapping(s, i);
2528             }
2529         }
2530     }
2531
2532     return 0;
2533 }
2534
2535 /*
2536  * synchronize mapping with new state:
2537  *
2538  * - copy FAT (with bdrv_read)
2539  * - mark all filenames corresponding to mappings as deleted
2540  * - recurse direntries from root (using bs->bdrv_read)
2541  * - delete files corresponding to mappings marked as deleted
2542  */
2543 static int do_commit(BDRVVVFATState* s)
2544 {
2545     int ret = 0;
2546
2547     /* the real meat are the commits. Nothing to do? Move along! */
2548     if (s->commits.next == 0)
2549         return 0;
2550
2551     vvfat_close_current_file(s);
2552
2553     ret = handle_renames_and_mkdirs(s);
2554     if (ret) {
2555         fprintf(stderr, "Error handling renames (%d)\n", ret);
2556         assert(0);
2557         return ret;
2558     }
2559
2560     /* copy FAT (with bdrv_read) */ 
2561     memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
2562
2563     /* recurse direntries from root (using bs->bdrv_read) */
2564     ret = commit_direntries(s, 0, -1);
2565     if (ret) {
2566         fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
2567         assert(0);
2568         return ret;
2569     }
2570
2571     ret = handle_commits(s);
2572     if (ret) {
2573         fprintf(stderr, "Error handling commits (%d)\n", ret);
2574         assert(0);
2575         return ret;
2576     }
2577
2578     ret = handle_deletes(s);
2579     if (ret) {
2580         fprintf(stderr, "Error deleting\n");
2581         assert(0);
2582         return ret;
2583     }
2584
2585     s->qcow->drv->bdrv_make_empty(s->qcow);
2586
2587     memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
2588
2589 DLOG(checkpoint());
2590     return 0;
2591 }
2592
2593 static int try_commit(BDRVVVFATState* s)
2594 {
2595     vvfat_close_current_file(s);
2596 DLOG(checkpoint());
2597     if(!is_consistent(s))
2598         return -1;
2599     return do_commit(s);
2600 }
2601
2602 static int vvfat_write(BlockDriverState *bs, int64_t sector_num, 
2603                     const uint8_t *buf, int nb_sectors)
2604 {
2605     BDRVVVFATState *s = bs->opaque; 
2606     int i, ret;
2607
2608 DLOG(checkpoint());
2609
2610     vvfat_close_current_file(s);
2611
2612     /*
2613      * Some sanity checks:
2614      * - do not allow writing to the boot sector
2615      * - do not allow to write non-ASCII filenames
2616      */
2617
2618     if (sector_num < s->first_sectors_number)
2619         return -1;
2620
2621     for (i = sector2cluster(s, sector_num);
2622             i <= sector2cluster(s, sector_num + nb_sectors - 1);) {
2623         mapping_t* mapping = find_mapping_for_cluster(s, i);
2624         if (mapping) {
2625             if (mapping->read_only) {
2626                 fprintf(stderr, "Tried to write to write-protected file %s\n",
2627                         mapping->path);
2628                 return -1;
2629             }
2630
2631             if (mapping->mode & MODE_DIRECTORY) {
2632                 int begin = cluster2sector(s, i);
2633                 int end = begin + s->sectors_per_cluster, k;
2634                 int dir_index;
2635                 const direntry_t* direntries;
2636                 long_file_name lfn;
2637
2638                 lfn_init(&lfn);
2639
2640                 if (begin < sector_num)
2641                     begin = sector_num;
2642                 if (end > sector_num + nb_sectors)
2643                     end = sector_num + nb_sectors;
2644                 dir_index  = mapping->dir_index + 
2645                     0x10 * (begin - mapping->begin * s->sectors_per_cluster);
2646                 direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
2647
2648                 for (k = 0; k < (end - begin) * 0x10; k++) {
2649                     /* do not allow non-ASCII filenames */
2650                     if (parse_long_name(&lfn, direntries + k) < 0) {
2651                         fprintf(stderr, "Warning: non-ASCII filename\n");
2652                         return -1;
2653                     }
2654                     /* no access to the direntry of a read-only file */
2655                     else if (is_short_name(direntries+k) &&
2656                             (direntries[k].attributes & 1)) {
2657                         if (memcmp(direntries + k,
2658                                     array_get(&(s->directory), dir_index + k),
2659                                     sizeof(direntry_t))) {
2660                             fprintf(stderr, "Warning: tried to write to write-protected file\n");
2661                             return -1;
2662                         }
2663                     }
2664                 }
2665             }
2666             i = mapping->end;
2667         } else
2668             i++;
2669     }
2670
2671     /*
2672      * Use qcow backend. Commit later.
2673      */
2674 DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
2675     ret = s->qcow->drv->bdrv_write(s->qcow, sector_num, buf, nb_sectors);
2676     if (ret < 0) {
2677         fprintf(stderr, "Error writing to qcow backend\n");
2678         return ret;
2679     }
2680
2681     for (i = sector2cluster(s, sector_num);
2682             i <= sector2cluster(s, sector_num + nb_sectors - 1); i++)
2683         if (i >= 0)
2684             s->used_clusters[i] |= USED_ALLOCATED;
2685
2686 DLOG(checkpoint());
2687     /* TODO: add timeout */
2688     try_commit(s);
2689
2690 DLOG(checkpoint());
2691     return 0;
2692 }
2693
2694 static int vvfat_is_allocated(BlockDriverState *bs,
2695         int64_t sector_num, int nb_sectors, int* n)
2696 {
2697     BDRVVVFATState* s = bs->opaque;
2698     *n = s->sector_count - sector_num;
2699     if (*n > nb_sectors)
2700         *n = nb_sectors;
2701     else if (*n < 0)
2702         return 0;
2703     return 1;   
2704 }
2705
2706 static int write_target_commit(BlockDriverState *bs, int64_t sector_num,
2707         const uint8_t* buffer, int nb_sectors) {
2708     BDRVVVFATState* s = bs->opaque;
2709     return try_commit(s);
2710 }
2711
2712 static void write_target_close(BlockDriverState *bs) {
2713     BDRVVVFATState* s = bs->opaque;
2714     bdrv_delete(s->qcow);
2715     free(s->qcow_filename);
2716 }
2717
2718 static BlockDriver vvfat_write_target = {
2719     "vvfat_write_target", 0, NULL, NULL, NULL,
2720     write_target_commit,
2721     write_target_close,
2722     NULL, NULL, NULL
2723 };
2724
2725 static int enable_write_target(BDRVVVFATState *s)
2726 {
2727     int size = sector2cluster(s, s->sector_count);
2728     s->used_clusters = calloc(size, 1);
2729
2730     array_init(&(s->commits), sizeof(commit_t));
2731
2732     s->qcow_filename = malloc(1024);
2733     strcpy(s->qcow_filename, "/tmp/vl.XXXXXX");
2734     get_tmp_filename(s->qcow_filename, strlen(s->qcow_filename) + 1);
2735     if (bdrv_create(&bdrv_qcow,
2736                 s->qcow_filename, s->sector_count, "fat:", 0) < 0)
2737         return -1;
2738     s->qcow = bdrv_new("");
2739     if (s->qcow == NULL || bdrv_open(s->qcow, s->qcow_filename, 0) < 0)
2740         return -1;
2741
2742 #ifndef _WIN32
2743     unlink(s->qcow_filename);
2744 #endif
2745
2746     s->bs->backing_hd = calloc(sizeof(BlockDriverState), 1);
2747     s->bs->backing_hd->drv = &vvfat_write_target;
2748     s->bs->backing_hd->opaque = s;
2749
2750     return 0;
2751 }
2752
2753 static void vvfat_close(BlockDriverState *bs)
2754 {
2755     BDRVVVFATState *s = bs->opaque;
2756
2757     vvfat_close_current_file(s);
2758     array_free(&(s->fat));
2759     array_free(&(s->directory));
2760     array_free(&(s->mapping));
2761     if(s->cluster_buffer)
2762         free(s->cluster_buffer);
2763 }
2764
2765 BlockDriver bdrv_vvfat = {
2766     "vvfat",
2767     sizeof(BDRVVVFATState),
2768     vvfat_probe,
2769     vvfat_open,
2770     vvfat_read,
2771     vvfat_write,
2772     vvfat_close,
2773     NULL,
2774     vvfat_is_allocated
2775 };
2776
2777 #ifdef DEBUG
2778 static void checkpoint() {
2779     assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2);
2780     check1(vvv);
2781     check2(vvv);
2782     assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY));
2783 #if 0
2784     if (((direntry_t*)vvv->directory.pointer)[1].attributes != 0xf)
2785         fprintf(stderr, "Nonono!\n");
2786     mapping_t* mapping;
2787     direntry_t* direntry;
2788     assert(vvv->mapping.size >= vvv->mapping.item_size * vvv->mapping.next);
2789     assert(vvv->directory.size >= vvv->directory.item_size * vvv->directory.next);
2790     if (vvv->mapping.next<47)
2791         return;
2792     assert((mapping = array_get(&(vvv->mapping), 47)));
2793     assert(mapping->dir_index < vvv->directory.next);
2794     direntry = array_get(&(vvv->directory), mapping->dir_index);
2795     assert(!memcmp(direntry->name, "USB     H  ", 11) || direntry->name[0]==0);
2796 #endif
2797     return;
2798     /* avoid compiler warnings: */
2799     hexdump(NULL, 100);
2800     remove_mapping(vvv, NULL);
2801     print_mapping(NULL);
2802     print_direntry(NULL);
2803 }
2804 #endif
2805