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