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