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