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