]> Git Repo - qemu.git/blob - block/vvfat.c
hw/pl110.c: Add post-load hook to invalidate display
[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 int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
986 {
987     BDRVVVFATState *s = bs->opaque;
988     int i;
989
990 #ifdef DEBUG
991     vvv = s;
992 #endif
993
994 DLOG(if (stderr == NULL) {
995     stderr = fopen("vvfat.log", "a");
996     setbuf(stderr, NULL);
997 })
998
999     s->bs = bs;
1000
1001     /* LATER TODO: if FAT32, adjust */
1002     s->sectors_per_cluster=0x10;
1003
1004     s->current_cluster=0xffffffff;
1005
1006     s->first_sectors_number=0x40;
1007     /* read only is the default for safety */
1008     bs->read_only = 1;
1009     s->qcow = s->write_target = NULL;
1010     s->qcow_filename = NULL;
1011     s->fat2 = NULL;
1012     s->downcase_short_names = 1;
1013
1014     if (!strstart(dirname, "fat:", NULL))
1015         return -1;
1016
1017     if (strstr(dirname, ":32:")) {
1018         fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. You are welcome to do so!\n");
1019         s->fat_type = 32;
1020     } else if (strstr(dirname, ":16:")) {
1021         s->fat_type = 16;
1022     } else if (strstr(dirname, ":12:")) {
1023         s->fat_type = 12;
1024     }
1025
1026     if (strstr(dirname, ":floppy:")) {
1027         /* 1.44MB or 2.88MB floppy.  2.88MB can be FAT12 (default) or FAT16. */
1028         if (!s->fat_type) {
1029             s->fat_type = 12;
1030             bs->secs = 36;
1031             s->sectors_per_cluster=2;
1032         } else {
1033             bs->secs=(s->fat_type == 12 ? 18 : 36);
1034             s->sectors_per_cluster=1;
1035         }
1036         s->first_sectors_number = 1;
1037         bs->cyls=80; bs->heads=2;
1038     } else {
1039         /* 32MB or 504MB disk*/
1040         if (!s->fat_type) {
1041             s->fat_type = 16;
1042         }
1043         bs->cyls=(s->fat_type == 12 ? 64 : 1024);
1044         bs->heads=16; bs->secs=63;
1045     }
1046
1047     s->sector_count=bs->cyls*bs->heads*bs->secs-(s->first_sectors_number-1);
1048
1049     if (strstr(dirname, ":rw:")) {
1050         if (enable_write_target(s))
1051             return -1;
1052         bs->read_only = 0;
1053     }
1054
1055     i = strrchr(dirname, ':') - dirname;
1056     assert(i >= 3);
1057     if (dirname[i-2] == ':' && qemu_isalpha(dirname[i-1]))
1058         /* workaround for DOS drive names */
1059         dirname += i-1;
1060     else
1061         dirname += i+1;
1062
1063     bs->total_sectors=bs->cyls*bs->heads*bs->secs;
1064
1065     if(init_directories(s, dirname))
1066         return -1;
1067
1068     s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
1069
1070     if(s->first_sectors_number==0x40)
1071         init_mbr(s);
1072     else {
1073         /* MS-DOS does not like to know about CHS (?). */
1074         bs->heads = bs->cyls = bs->secs = 0;
1075     }
1076
1077     //    assert(is_consistent(s));
1078     qemu_co_mutex_init(&s->lock);
1079
1080     /* Disable migration when vvfat is used rw */
1081     if (s->qcow) {
1082         error_set(&s->migration_blocker,
1083                   QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
1084                   "vvfat (rw)", bs->device_name, "live migration");
1085         migrate_add_blocker(s->migration_blocker);
1086     }
1087
1088     return 0;
1089 }
1090
1091 static inline void vvfat_close_current_file(BDRVVVFATState *s)
1092 {
1093     if(s->current_mapping) {
1094         s->current_mapping = NULL;
1095         if (s->current_fd) {
1096                 close(s->current_fd);
1097                 s->current_fd = 0;
1098         }
1099     }
1100     s->current_cluster = -1;
1101 }
1102
1103 /* mappings between index1 and index2-1 are supposed to be ordered
1104  * return value is the index of the last mapping for which end>cluster_num
1105  */
1106 static inline int find_mapping_for_cluster_aux(BDRVVVFATState* s,int cluster_num,int index1,int index2)
1107 {
1108     while(1) {
1109         int index3;
1110         mapping_t* mapping;
1111         index3=(index1+index2)/2;
1112         mapping=array_get(&(s->mapping),index3);
1113         assert(mapping->begin < mapping->end);
1114         if(mapping->begin>=cluster_num) {
1115             assert(index2!=index3 || index2==0);
1116             if(index2==index3)
1117                 return index1;
1118             index2=index3;
1119         } else {
1120             if(index1==index3)
1121                 return mapping->end<=cluster_num ? index2 : index1;
1122             index1=index3;
1123         }
1124         assert(index1<=index2);
1125         DLOG(mapping=array_get(&(s->mapping),index1);
1126         assert(mapping->begin<=cluster_num);
1127         assert(index2 >= s->mapping.next ||
1128                 ((mapping = array_get(&(s->mapping),index2)) &&
1129                 mapping->end>cluster_num)));
1130     }
1131 }
1132
1133 static inline mapping_t* find_mapping_for_cluster(BDRVVVFATState* s,int cluster_num)
1134 {
1135     int index=find_mapping_for_cluster_aux(s,cluster_num,0,s->mapping.next);
1136     mapping_t* mapping;
1137     if(index>=s->mapping.next)
1138         return NULL;
1139     mapping=array_get(&(s->mapping),index);
1140     if(mapping->begin>cluster_num)
1141         return NULL;
1142     assert(mapping->begin<=cluster_num && mapping->end>cluster_num);
1143     return mapping;
1144 }
1145
1146 static int open_file(BDRVVVFATState* s,mapping_t* mapping)
1147 {
1148     if(!mapping)
1149         return -1;
1150     if(!s->current_mapping ||
1151             strcmp(s->current_mapping->path,mapping->path)) {
1152         /* open file */
1153         int fd = open(mapping->path, O_RDONLY | O_BINARY | O_LARGEFILE);
1154         if(fd<0)
1155             return -1;
1156         vvfat_close_current_file(s);
1157         s->current_fd = fd;
1158         s->current_mapping = mapping;
1159     }
1160     return 0;
1161 }
1162
1163 static inline int read_cluster(BDRVVVFATState *s,int cluster_num)
1164 {
1165     if(s->current_cluster != cluster_num) {
1166         int result=0;
1167         off_t offset;
1168         assert(!s->current_mapping || s->current_fd || (s->current_mapping->mode & MODE_DIRECTORY));
1169         if(!s->current_mapping
1170                 || s->current_mapping->begin>cluster_num
1171                 || s->current_mapping->end<=cluster_num) {
1172             /* binary search of mappings for file */
1173             mapping_t* mapping=find_mapping_for_cluster(s,cluster_num);
1174
1175             assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
1176
1177             if (mapping && mapping->mode & MODE_DIRECTORY) {
1178                 vvfat_close_current_file(s);
1179                 s->current_mapping = mapping;
1180 read_cluster_directory:
1181                 offset = s->cluster_size*(cluster_num-s->current_mapping->begin);
1182                 s->cluster = (unsigned char*)s->directory.pointer+offset
1183                         + 0x20*s->current_mapping->info.dir.first_dir_index;
1184                 assert(((s->cluster-(unsigned char*)s->directory.pointer)%s->cluster_size)==0);
1185                 assert((char*)s->cluster+s->cluster_size <= s->directory.pointer+s->directory.next*s->directory.item_size);
1186                 s->current_cluster = cluster_num;
1187                 return 0;
1188             }
1189
1190             if(open_file(s,mapping))
1191                 return -2;
1192         } else if (s->current_mapping->mode & MODE_DIRECTORY)
1193             goto read_cluster_directory;
1194
1195         assert(s->current_fd);
1196
1197         offset=s->cluster_size*(cluster_num-s->current_mapping->begin)+s->current_mapping->info.file.offset;
1198         if(lseek(s->current_fd, offset, SEEK_SET)!=offset)
1199             return -3;
1200         s->cluster=s->cluster_buffer;
1201         result=read(s->current_fd,s->cluster,s->cluster_size);
1202         if(result<0) {
1203             s->current_cluster = -1;
1204             return -1;
1205         }
1206         s->current_cluster = cluster_num;
1207     }
1208     return 0;
1209 }
1210
1211 #ifdef DEBUG
1212 static void print_direntry(const direntry_t* direntry)
1213 {
1214     int j = 0;
1215     char buffer[1024];
1216
1217     fprintf(stderr, "direntry %p: ", direntry);
1218     if(!direntry)
1219         return;
1220     if(is_long_name(direntry)) {
1221         unsigned char* c=(unsigned char*)direntry;
1222         int i;
1223         for(i=1;i<11 && c[i] && c[i]!=0xff;i+=2)
1224 #define ADD_CHAR(c) {buffer[j] = (c); if (buffer[j] < ' ') buffer[j] = 0xb0; j++;}
1225             ADD_CHAR(c[i]);
1226         for(i=14;i<26 && c[i] && c[i]!=0xff;i+=2)
1227             ADD_CHAR(c[i]);
1228         for(i=28;i<32 && c[i] && c[i]!=0xff;i+=2)
1229             ADD_CHAR(c[i]);
1230         buffer[j] = 0;
1231         fprintf(stderr, "%s\n", buffer);
1232     } else {
1233         int i;
1234         for(i=0;i<11;i++)
1235             ADD_CHAR(direntry->name[i]);
1236         buffer[j] = 0;
1237         fprintf(stderr,"%s attributes=0x%02x begin=%d size=%d\n",
1238                 buffer,
1239                 direntry->attributes,
1240                 begin_of_direntry(direntry),le32_to_cpu(direntry->size));
1241     }
1242 }
1243
1244 static void print_mapping(const mapping_t* mapping)
1245 {
1246     fprintf(stderr, "mapping (%p): begin, end = %d, %d, dir_index = %d, "
1247         "first_mapping_index = %d, name = %s, mode = 0x%x, " ,
1248         mapping, mapping->begin, mapping->end, mapping->dir_index,
1249         mapping->first_mapping_index, mapping->path, mapping->mode);
1250
1251     if (mapping->mode & MODE_DIRECTORY)
1252         fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
1253     else
1254         fprintf(stderr, "offset = %d\n", mapping->info.file.offset);
1255 }
1256 #endif
1257
1258 static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
1259                     uint8_t *buf, int nb_sectors)
1260 {
1261     BDRVVVFATState *s = bs->opaque;
1262     int i;
1263
1264     for(i=0;i<nb_sectors;i++,sector_num++) {
1265         if (sector_num >= bs->total_sectors)
1266            return -1;
1267         if (s->qcow) {
1268             int n;
1269             if (bdrv_is_allocated(s->qcow, sector_num, nb_sectors-i, &n)) {
1270 DLOG(fprintf(stderr, "sectors %d+%d allocated\n", (int)sector_num, n));
1271                 if (bdrv_read(s->qcow, sector_num, buf + i*0x200, n)) {
1272                     return -1;
1273                 }
1274                 i += n - 1;
1275                 sector_num += n - 1;
1276                 continue;
1277             }
1278 DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num));
1279         }
1280         if(sector_num<s->faked_sectors) {
1281             if(sector_num<s->first_sectors_number)
1282                 memcpy(buf+i*0x200,&(s->first_sectors[sector_num*0x200]),0x200);
1283             else if(sector_num-s->first_sectors_number<s->sectors_per_fat)
1284                 memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number)*0x200]),0x200);
1285             else if(sector_num-s->first_sectors_number-s->sectors_per_fat<s->sectors_per_fat)
1286                 memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number-s->sectors_per_fat)*0x200]),0x200);
1287         } else {
1288             uint32_t sector=sector_num-s->faked_sectors,
1289             sector_offset_in_cluster=(sector%s->sectors_per_cluster),
1290             cluster_num=sector/s->sectors_per_cluster;
1291             if(cluster_num > s->cluster_count || read_cluster(s, cluster_num) != 0) {
1292                 /* LATER TODO: strict: return -1; */
1293                 memset(buf+i*0x200,0,0x200);
1294                 continue;
1295             }
1296             memcpy(buf+i*0x200,s->cluster+sector_offset_in_cluster*0x200,0x200);
1297         }
1298     }
1299     return 0;
1300 }
1301
1302 static coroutine_fn int vvfat_co_read(BlockDriverState *bs, int64_t sector_num,
1303                                       uint8_t *buf, int nb_sectors)
1304 {
1305     int ret;
1306     BDRVVVFATState *s = bs->opaque;
1307     qemu_co_mutex_lock(&s->lock);
1308     ret = vvfat_read(bs, sector_num, buf, nb_sectors);
1309     qemu_co_mutex_unlock(&s->lock);
1310     return ret;
1311 }
1312
1313 /* LATER TODO: statify all functions */
1314
1315 /*
1316  * Idea of the write support (use snapshot):
1317  *
1318  * 1. check if all data is consistent, recording renames, modifications,
1319  *    new files and directories (in s->commits).
1320  *
1321  * 2. if the data is not consistent, stop committing
1322  *
1323  * 3. handle renames, and create new files and directories (do not yet
1324  *    write their contents)
1325  *
1326  * 4. walk the directories, fixing the mapping and direntries, and marking
1327  *    the handled mappings as not deleted
1328  *
1329  * 5. commit the contents of the files
1330  *
1331  * 6. handle deleted files and directories
1332  *
1333  */
1334
1335 typedef struct commit_t {
1336     char* path;
1337     union {
1338         struct { uint32_t cluster; } rename;
1339         struct { int dir_index; uint32_t modified_offset; } writeout;
1340         struct { uint32_t first_cluster; } new_file;
1341         struct { uint32_t cluster; } mkdir;
1342     } param;
1343     /* DELETEs and RMDIRs are handled differently: see handle_deletes() */
1344     enum {
1345         ACTION_RENAME, ACTION_WRITEOUT, ACTION_NEW_FILE, ACTION_MKDIR
1346     } action;
1347 } commit_t;
1348
1349 static void clear_commits(BDRVVVFATState* s)
1350 {
1351     int i;
1352 DLOG(fprintf(stderr, "clear_commits (%d commits)\n", s->commits.next));
1353     for (i = 0; i < s->commits.next; i++) {
1354         commit_t* commit = array_get(&(s->commits), i);
1355         assert(commit->path || commit->action == ACTION_WRITEOUT);
1356         if (commit->action != ACTION_WRITEOUT) {
1357             assert(commit->path);
1358             g_free(commit->path);
1359         } else
1360             assert(commit->path == NULL);
1361     }
1362     s->commits.next = 0;
1363 }
1364
1365 static void schedule_rename(BDRVVVFATState* s,
1366         uint32_t cluster, char* new_path)
1367 {
1368     commit_t* commit = array_get_next(&(s->commits));
1369     commit->path = new_path;
1370     commit->param.rename.cluster = cluster;
1371     commit->action = ACTION_RENAME;
1372 }
1373
1374 static void schedule_writeout(BDRVVVFATState* s,
1375         int dir_index, uint32_t modified_offset)
1376 {
1377     commit_t* commit = array_get_next(&(s->commits));
1378     commit->path = NULL;
1379     commit->param.writeout.dir_index = dir_index;
1380     commit->param.writeout.modified_offset = modified_offset;
1381     commit->action = ACTION_WRITEOUT;
1382 }
1383
1384 static void schedule_new_file(BDRVVVFATState* s,
1385         char* path, uint32_t first_cluster)
1386 {
1387     commit_t* commit = array_get_next(&(s->commits));
1388     commit->path = path;
1389     commit->param.new_file.first_cluster = first_cluster;
1390     commit->action = ACTION_NEW_FILE;
1391 }
1392
1393 static void schedule_mkdir(BDRVVVFATState* s, uint32_t cluster, char* path)
1394 {
1395     commit_t* commit = array_get_next(&(s->commits));
1396     commit->path = path;
1397     commit->param.mkdir.cluster = cluster;
1398     commit->action = ACTION_MKDIR;
1399 }
1400
1401 typedef struct {
1402     /*
1403      * Since the sequence number is at most 0x3f, and the filename
1404      * length is at most 13 times the sequence number, the maximal
1405      * filename length is 0x3f * 13 bytes.
1406      */
1407     unsigned char name[0x3f * 13 + 1];
1408     int checksum, len;
1409     int sequence_number;
1410 } long_file_name;
1411
1412 static void lfn_init(long_file_name* lfn)
1413 {
1414    lfn->sequence_number = lfn->len = 0;
1415    lfn->checksum = 0x100;
1416 }
1417
1418 /* return 0 if parsed successfully, > 0 if no long name, < 0 if error */
1419 static int parse_long_name(long_file_name* lfn,
1420         const direntry_t* direntry)
1421 {
1422     int i, j, offset;
1423     const unsigned char* pointer = (const unsigned char*)direntry;
1424
1425     if (!is_long_name(direntry))
1426         return 1;
1427
1428     if (pointer[0] & 0x40) {
1429         lfn->sequence_number = pointer[0] & 0x3f;
1430         lfn->checksum = pointer[13];
1431         lfn->name[0] = 0;
1432         lfn->name[lfn->sequence_number * 13] = 0;
1433     } else if ((pointer[0] & 0x3f) != --lfn->sequence_number)
1434         return -1;
1435     else if (pointer[13] != lfn->checksum)
1436         return -2;
1437     else if (pointer[12] || pointer[26] || pointer[27])
1438         return -3;
1439
1440     offset = 13 * (lfn->sequence_number - 1);
1441     for (i = 0, j = 1; i < 13; i++, j+=2) {
1442         if (j == 11)
1443             j = 14;
1444         else if (j == 26)
1445             j = 28;
1446
1447         if (pointer[j+1] == 0)
1448             lfn->name[offset + i] = pointer[j];
1449         else if (pointer[j+1] != 0xff || (pointer[0] & 0x40) == 0)
1450             return -4;
1451         else
1452             lfn->name[offset + i] = 0;
1453     }
1454
1455     if (pointer[0] & 0x40)
1456         lfn->len = offset + strlen((char*)lfn->name + offset);
1457
1458     return 0;
1459 }
1460
1461 /* returns 0 if successful, >0 if no short_name, and <0 on error */
1462 static int parse_short_name(BDRVVVFATState* s,
1463         long_file_name* lfn, direntry_t* direntry)
1464 {
1465     int i, j;
1466
1467     if (!is_short_name(direntry))
1468         return 1;
1469
1470     for (j = 7; j >= 0 && direntry->name[j] == ' '; j--);
1471     for (i = 0; i <= j; i++) {
1472         if (direntry->name[i] <= ' ' || direntry->name[i] > 0x7f)
1473             return -1;
1474         else if (s->downcase_short_names)
1475             lfn->name[i] = qemu_tolower(direntry->name[i]);
1476         else
1477             lfn->name[i] = direntry->name[i];
1478     }
1479
1480     for (j = 2; j >= 0 && direntry->extension[j] == ' '; j--);
1481     if (j >= 0) {
1482         lfn->name[i++] = '.';
1483         lfn->name[i + j + 1] = '\0';
1484         for (;j >= 0; j--) {
1485             if (direntry->extension[j] <= ' ' || direntry->extension[j] > 0x7f)
1486                 return -2;
1487             else if (s->downcase_short_names)
1488                 lfn->name[i + j] = qemu_tolower(direntry->extension[j]);
1489             else
1490                 lfn->name[i + j] = direntry->extension[j];
1491         }
1492     } else
1493         lfn->name[i + j + 1] = '\0';
1494
1495     lfn->len = strlen((char*)lfn->name);
1496
1497     return 0;
1498 }
1499
1500 static inline uint32_t modified_fat_get(BDRVVVFATState* s,
1501         unsigned int cluster)
1502 {
1503     if (cluster < s->last_cluster_of_root_directory) {
1504         if (cluster + 1 == s->last_cluster_of_root_directory)
1505             return s->max_fat_value;
1506         else
1507             return cluster + 1;
1508     }
1509
1510     if (s->fat_type==32) {
1511         uint32_t* entry=((uint32_t*)s->fat2)+cluster;
1512         return le32_to_cpu(*entry);
1513     } else if (s->fat_type==16) {
1514         uint16_t* entry=((uint16_t*)s->fat2)+cluster;
1515         return le16_to_cpu(*entry);
1516     } else {
1517         const uint8_t* x=s->fat2+cluster*3/2;
1518         return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
1519     }
1520 }
1521
1522 static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num)
1523 {
1524     int was_modified = 0;
1525     int i, dummy;
1526
1527     if (s->qcow == NULL)
1528         return 0;
1529
1530     for (i = 0; !was_modified && i < s->sectors_per_cluster; i++)
1531         was_modified = bdrv_is_allocated(s->qcow,
1532                 cluster2sector(s, cluster_num) + i, 1, &dummy);
1533
1534     return was_modified;
1535 }
1536
1537 static const char* get_basename(const char* path)
1538 {
1539     char* basename = strrchr(path, '/');
1540     if (basename == NULL)
1541         return path;
1542     else
1543         return basename + 1; /* strip '/' */
1544 }
1545
1546 /*
1547  * The array s->used_clusters holds the states of the clusters. If it is
1548  * part of a file, it has bit 2 set, in case of a directory, bit 1. If it
1549  * was modified, bit 3 is set.
1550  * If any cluster is allocated, but not part of a file or directory, this
1551  * driver refuses to commit.
1552  */
1553 typedef enum {
1554      USED_DIRECTORY = 1, USED_FILE = 2, USED_ANY = 3, USED_ALLOCATED = 4
1555 } used_t;
1556
1557 /*
1558  * get_cluster_count_for_direntry() not only determines how many clusters
1559  * are occupied by direntry, but also if it was renamed or modified.
1560  *
1561  * A file is thought to be renamed *only* if there already was a file with
1562  * exactly the same first cluster, but a different name.
1563  *
1564  * Further, the files/directories handled by this function are
1565  * assumed to be *not* deleted (and *only* those).
1566  */
1567 static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
1568         direntry_t* direntry, const char* path)
1569 {
1570     /*
1571      * This is a little bit tricky:
1572      * IF the guest OS just inserts a cluster into the file chain,
1573      * and leaves the rest alone, (i.e. the original file had clusters
1574      * 15 -> 16, but now has 15 -> 32 -> 16), then the following happens:
1575      *
1576      * - do_commit will write the cluster into the file at the given
1577      *   offset, but
1578      *
1579      * - the cluster which is overwritten should be moved to a later
1580      *   position in the file.
1581      *
1582      * I am not aware that any OS does something as braindead, but this
1583      * situation could happen anyway when not committing for a long time.
1584      * Just to be sure that this does not bite us, detect it, and copy the
1585      * contents of the clusters to-be-overwritten into the qcow.
1586      */
1587     int copy_it = 0;
1588     int was_modified = 0;
1589     int32_t ret = 0;
1590
1591     uint32_t cluster_num = begin_of_direntry(direntry);
1592     uint32_t offset = 0;
1593     int first_mapping_index = -1;
1594     mapping_t* mapping = NULL;
1595     const char* basename2 = NULL;
1596
1597     vvfat_close_current_file(s);
1598
1599     /* the root directory */
1600     if (cluster_num == 0)
1601         return 0;
1602
1603     /* write support */
1604     if (s->qcow) {
1605         basename2 = get_basename(path);
1606
1607         mapping = find_mapping_for_cluster(s, cluster_num);
1608
1609         if (mapping) {
1610             const char* basename;
1611
1612             assert(mapping->mode & MODE_DELETED);
1613             mapping->mode &= ~MODE_DELETED;
1614
1615             basename = get_basename(mapping->path);
1616
1617             assert(mapping->mode & MODE_NORMAL);
1618
1619             /* rename */
1620             if (strcmp(basename, basename2))
1621                 schedule_rename(s, cluster_num, g_strdup(path));
1622         } else if (is_file(direntry))
1623             /* new file */
1624             schedule_new_file(s, g_strdup(path), cluster_num);
1625         else {
1626             abort();
1627             return 0;
1628         }
1629     }
1630
1631     while(1) {
1632         if (s->qcow) {
1633             if (!copy_it && cluster_was_modified(s, cluster_num)) {
1634                 if (mapping == NULL ||
1635                         mapping->begin > cluster_num ||
1636                         mapping->end <= cluster_num)
1637                 mapping = find_mapping_for_cluster(s, cluster_num);
1638
1639
1640                 if (mapping &&
1641                         (mapping->mode & MODE_DIRECTORY) == 0) {
1642
1643                     /* was modified in qcow */
1644                     if (offset != mapping->info.file.offset + s->cluster_size
1645                             * (cluster_num - mapping->begin)) {
1646                         /* offset of this cluster in file chain has changed */
1647                         abort();
1648                         copy_it = 1;
1649                     } else if (offset == 0) {
1650                         const char* basename = get_basename(mapping->path);
1651
1652                         if (strcmp(basename, basename2))
1653                             copy_it = 1;
1654                         first_mapping_index = array_index(&(s->mapping), mapping);
1655                     }
1656
1657                     if (mapping->first_mapping_index != first_mapping_index
1658                             && mapping->info.file.offset > 0) {
1659                         abort();
1660                         copy_it = 1;
1661                     }
1662
1663                     /* need to write out? */
1664                     if (!was_modified && is_file(direntry)) {
1665                         was_modified = 1;
1666                         schedule_writeout(s, mapping->dir_index, offset);
1667                     }
1668                 }
1669             }
1670
1671             if (copy_it) {
1672                 int i, dummy;
1673                 /*
1674                  * This is horribly inefficient, but that is okay, since
1675                  * it is rarely executed, if at all.
1676                  */
1677                 int64_t offset = cluster2sector(s, cluster_num);
1678
1679                 vvfat_close_current_file(s);
1680                 for (i = 0; i < s->sectors_per_cluster; i++) {
1681                     if (!bdrv_is_allocated(s->qcow, offset + i, 1, &dummy)) {
1682                         if (vvfat_read(s->bs, offset, s->cluster_buffer, 1)) {
1683                             return -1;
1684                         }
1685                         if (bdrv_write(s->qcow, offset, s->cluster_buffer, 1)) {
1686                             return -2;
1687                         }
1688                     }
1689                 }
1690             }
1691         }
1692
1693         ret++;
1694         if (s->used_clusters[cluster_num] & USED_ANY)
1695             return 0;
1696         s->used_clusters[cluster_num] = USED_FILE;
1697
1698         cluster_num = modified_fat_get(s, cluster_num);
1699
1700         if (fat_eof(s, cluster_num))
1701             return ret;
1702         else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
1703             return -1;
1704
1705         offset += s->cluster_size;
1706     }
1707 }
1708
1709 /*
1710  * This function looks at the modified data (qcow).
1711  * It returns 0 upon inconsistency or error, and the number of clusters
1712  * used by the directory, its subdirectories and their files.
1713  */
1714 static int check_directory_consistency(BDRVVVFATState *s,
1715         int cluster_num, const char* path)
1716 {
1717     int ret = 0;
1718     unsigned char* cluster = g_malloc(s->cluster_size);
1719     direntry_t* direntries = (direntry_t*)cluster;
1720     mapping_t* mapping = find_mapping_for_cluster(s, cluster_num);
1721
1722     long_file_name lfn;
1723     int path_len = strlen(path);
1724     char path2[PATH_MAX + 1];
1725
1726     assert(path_len < PATH_MAX); /* len was tested before! */
1727     pstrcpy(path2, sizeof(path2), path);
1728     path2[path_len] = '/';
1729     path2[path_len + 1] = '\0';
1730
1731     if (mapping) {
1732         const char* basename = get_basename(mapping->path);
1733         const char* basename2 = get_basename(path);
1734
1735         assert(mapping->mode & MODE_DIRECTORY);
1736
1737         assert(mapping->mode & MODE_DELETED);
1738         mapping->mode &= ~MODE_DELETED;
1739
1740         if (strcmp(basename, basename2))
1741             schedule_rename(s, cluster_num, g_strdup(path));
1742     } else
1743         /* new directory */
1744         schedule_mkdir(s, cluster_num, g_strdup(path));
1745
1746     lfn_init(&lfn);
1747     do {
1748         int i;
1749         int subret = 0;
1750
1751         ret++;
1752
1753         if (s->used_clusters[cluster_num] & USED_ANY) {
1754             fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
1755             return 0;
1756         }
1757         s->used_clusters[cluster_num] = USED_DIRECTORY;
1758
1759 DLOG(fprintf(stderr, "read cluster %d (sector %d)\n", (int)cluster_num, (int)cluster2sector(s, cluster_num)));
1760         subret = vvfat_read(s->bs, cluster2sector(s, cluster_num), cluster,
1761                 s->sectors_per_cluster);
1762         if (subret) {
1763             fprintf(stderr, "Error fetching direntries\n");
1764         fail:
1765             g_free(cluster);
1766             return 0;
1767         }
1768
1769         for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
1770             int cluster_count = 0;
1771
1772 DLOG(fprintf(stderr, "check direntry %d:\n", i); print_direntry(direntries + i));
1773             if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
1774                     is_free(direntries + i))
1775                 continue;
1776
1777             subret = parse_long_name(&lfn, direntries + i);
1778             if (subret < 0) {
1779                 fprintf(stderr, "Error in long name\n");
1780                 goto fail;
1781             }
1782             if (subret == 0 || is_free(direntries + i))
1783                 continue;
1784
1785             if (fat_chksum(direntries+i) != lfn.checksum) {
1786                 subret = parse_short_name(s, &lfn, direntries + i);
1787                 if (subret < 0) {
1788                     fprintf(stderr, "Error in short name (%d)\n", subret);
1789                     goto fail;
1790                 }
1791                 if (subret > 0 || !strcmp((char*)lfn.name, ".")
1792                         || !strcmp((char*)lfn.name, ".."))
1793                     continue;
1794             }
1795             lfn.checksum = 0x100; /* cannot use long name twice */
1796
1797             if (path_len + 1 + lfn.len >= PATH_MAX) {
1798                 fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
1799                 goto fail;
1800             }
1801             pstrcpy(path2 + path_len + 1, sizeof(path2) - path_len - 1,
1802                     (char*)lfn.name);
1803
1804             if (is_directory(direntries + i)) {
1805                 if (begin_of_direntry(direntries + i) == 0) {
1806                     DLOG(fprintf(stderr, "invalid begin for directory: %s\n", path2); print_direntry(direntries + i));
1807                     goto fail;
1808                 }
1809                 cluster_count = check_directory_consistency(s,
1810                         begin_of_direntry(direntries + i), path2);
1811                 if (cluster_count == 0) {
1812                     DLOG(fprintf(stderr, "problem in directory %s:\n", path2); print_direntry(direntries + i));
1813                     goto fail;
1814                 }
1815             } else if (is_file(direntries + i)) {
1816                 /* check file size with FAT */
1817                 cluster_count = get_cluster_count_for_direntry(s, direntries + i, path2);
1818                 if (cluster_count !=
1819                         (le32_to_cpu(direntries[i].size) + s->cluster_size
1820                          - 1) / s->cluster_size) {
1821                     DLOG(fprintf(stderr, "Cluster count mismatch\n"));
1822                     goto fail;
1823                 }
1824             } else
1825                 abort(); /* cluster_count = 0; */
1826
1827             ret += cluster_count;
1828         }
1829
1830         cluster_num = modified_fat_get(s, cluster_num);
1831     } while(!fat_eof(s, cluster_num));
1832
1833     g_free(cluster);
1834     return ret;
1835 }
1836
1837 /* returns 1 on success */
1838 static int is_consistent(BDRVVVFATState* s)
1839 {
1840     int i, check;
1841     int used_clusters_count = 0;
1842
1843 DLOG(checkpoint());
1844     /*
1845      * - get modified FAT
1846      * - compare the two FATs (TODO)
1847      * - get buffer for marking used clusters
1848      * - recurse direntries from root (using bs->bdrv_read to make
1849      *    sure to get the new data)
1850      *   - check that the FAT agrees with the size
1851      *   - count the number of clusters occupied by this directory and
1852      *     its files
1853      * - check that the cumulative used cluster count agrees with the
1854      *   FAT
1855      * - if all is fine, return number of used clusters
1856      */
1857     if (s->fat2 == NULL) {
1858         int size = 0x200 * s->sectors_per_fat;
1859         s->fat2 = g_malloc(size);
1860         memcpy(s->fat2, s->fat.pointer, size);
1861     }
1862     check = vvfat_read(s->bs,
1863             s->first_sectors_number, s->fat2, s->sectors_per_fat);
1864     if (check) {
1865         fprintf(stderr, "Could not copy fat\n");
1866         return 0;
1867     }
1868     assert (s->used_clusters);
1869     for (i = 0; i < sector2cluster(s, s->sector_count); i++)
1870         s->used_clusters[i] &= ~USED_ANY;
1871
1872     clear_commits(s);
1873
1874     /* mark every mapped file/directory as deleted.
1875      * (check_directory_consistency() will unmark those still present). */
1876     if (s->qcow)
1877         for (i = 0; i < s->mapping.next; i++) {
1878             mapping_t* mapping = array_get(&(s->mapping), i);
1879             if (mapping->first_mapping_index < 0)
1880                 mapping->mode |= MODE_DELETED;
1881         }
1882
1883     used_clusters_count = check_directory_consistency(s, 0, s->path);
1884     if (used_clusters_count <= 0) {
1885         DLOG(fprintf(stderr, "problem in directory\n"));
1886         return 0;
1887     }
1888
1889     check = s->last_cluster_of_root_directory;
1890     for (i = check; i < sector2cluster(s, s->sector_count); i++) {
1891         if (modified_fat_get(s, i)) {
1892             if(!s->used_clusters[i]) {
1893                 DLOG(fprintf(stderr, "FAT was modified (%d), but cluster is not used?\n", i));
1894                 return 0;
1895             }
1896             check++;
1897         }
1898
1899         if (s->used_clusters[i] == USED_ALLOCATED) {
1900             /* allocated, but not used... */
1901             DLOG(fprintf(stderr, "unused, modified cluster: %d\n", i));
1902             return 0;
1903         }
1904     }
1905
1906     if (check != used_clusters_count)
1907         return 0;
1908
1909     return used_clusters_count;
1910 }
1911
1912 static inline void adjust_mapping_indices(BDRVVVFATState* s,
1913         int offset, int adjust)
1914 {
1915     int i;
1916
1917     for (i = 0; i < s->mapping.next; i++) {
1918         mapping_t* mapping = array_get(&(s->mapping), i);
1919
1920 #define ADJUST_MAPPING_INDEX(name) \
1921         if (mapping->name >= offset) \
1922             mapping->name += adjust
1923
1924         ADJUST_MAPPING_INDEX(first_mapping_index);
1925         if (mapping->mode & MODE_DIRECTORY)
1926             ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
1927     }
1928 }
1929
1930 /* insert or update mapping */
1931 static mapping_t* insert_mapping(BDRVVVFATState* s,
1932         uint32_t begin, uint32_t end)
1933 {
1934     /*
1935      * - find mapping where mapping->begin >= begin,
1936      * - if mapping->begin > begin: insert
1937      *   - adjust all references to mappings!
1938      * - else: adjust
1939      * - replace name
1940      */
1941     int index = find_mapping_for_cluster_aux(s, begin, 0, s->mapping.next);
1942     mapping_t* mapping = NULL;
1943     mapping_t* first_mapping = array_get(&(s->mapping), 0);
1944
1945     if (index < s->mapping.next && (mapping = array_get(&(s->mapping), index))
1946             && mapping->begin < begin) {
1947         mapping->end = begin;
1948         index++;
1949         mapping = array_get(&(s->mapping), index);
1950     }
1951     if (index >= s->mapping.next || mapping->begin > begin) {
1952         mapping = array_insert(&(s->mapping), index, 1);
1953         mapping->path = NULL;
1954         adjust_mapping_indices(s, index, +1);
1955     }
1956
1957     mapping->begin = begin;
1958     mapping->end = end;
1959
1960 DLOG(mapping_t* next_mapping;
1961 assert(index + 1 >= s->mapping.next ||
1962 ((next_mapping = array_get(&(s->mapping), index + 1)) &&
1963  next_mapping->begin >= end)));
1964
1965     if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1966         s->current_mapping = array_get(&(s->mapping),
1967                 s->current_mapping - first_mapping);
1968
1969     return mapping;
1970 }
1971
1972 static int remove_mapping(BDRVVVFATState* s, int mapping_index)
1973 {
1974     mapping_t* mapping = array_get(&(s->mapping), mapping_index);
1975     mapping_t* first_mapping = array_get(&(s->mapping), 0);
1976
1977     /* free mapping */
1978     if (mapping->first_mapping_index < 0) {
1979         g_free(mapping->path);
1980     }
1981
1982     /* remove from s->mapping */
1983     array_remove(&(s->mapping), mapping_index);
1984
1985     /* adjust all references to mappings */
1986     adjust_mapping_indices(s, mapping_index, -1);
1987
1988     if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1989         s->current_mapping = array_get(&(s->mapping),
1990                 s->current_mapping - first_mapping);
1991
1992     return 0;
1993 }
1994
1995 static void adjust_dirindices(BDRVVVFATState* s, int offset, int adjust)
1996 {
1997     int i;
1998     for (i = 0; i < s->mapping.next; i++) {
1999         mapping_t* mapping = array_get(&(s->mapping), i);
2000         if (mapping->dir_index >= offset)
2001             mapping->dir_index += adjust;
2002         if ((mapping->mode & MODE_DIRECTORY) &&
2003                 mapping->info.dir.first_dir_index >= offset)
2004             mapping->info.dir.first_dir_index += adjust;
2005     }
2006 }
2007
2008 static direntry_t* insert_direntries(BDRVVVFATState* s,
2009         int dir_index, int count)
2010 {
2011     /*
2012      * make room in s->directory,
2013      * adjust_dirindices
2014      */
2015     direntry_t* result = array_insert(&(s->directory), dir_index, count);
2016     if (result == NULL)
2017         return NULL;
2018     adjust_dirindices(s, dir_index, count);
2019     return result;
2020 }
2021
2022 static int remove_direntries(BDRVVVFATState* s, int dir_index, int count)
2023 {
2024     int ret = array_remove_slice(&(s->directory), dir_index, count);
2025     if (ret)
2026         return ret;
2027     adjust_dirindices(s, dir_index, -count);
2028     return 0;
2029 }
2030
2031 /*
2032  * Adapt the mappings of the cluster chain starting at first cluster
2033  * (i.e. if a file starts at first_cluster, the chain is followed according
2034  * to the modified fat, and the corresponding entries in s->mapping are
2035  * adjusted)
2036  */
2037 static int commit_mappings(BDRVVVFATState* s,
2038         uint32_t first_cluster, int dir_index)
2039 {
2040     mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2041     direntry_t* direntry = array_get(&(s->directory), dir_index);
2042     uint32_t cluster = first_cluster;
2043
2044     vvfat_close_current_file(s);
2045
2046     assert(mapping);
2047     assert(mapping->begin == first_cluster);
2048     mapping->first_mapping_index = -1;
2049     mapping->dir_index = dir_index;
2050     mapping->mode = (dir_index <= 0 || is_directory(direntry)) ?
2051         MODE_DIRECTORY : MODE_NORMAL;
2052
2053     while (!fat_eof(s, cluster)) {
2054         uint32_t c, c1;
2055
2056         for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
2057                 c = c1, c1 = modified_fat_get(s, c1));
2058
2059         c++;
2060         if (c > mapping->end) {
2061             int index = array_index(&(s->mapping), mapping);
2062             int i, max_i = s->mapping.next - index;
2063             for (i = 1; i < max_i && mapping[i].begin < c; i++);
2064             while (--i > 0)
2065                 remove_mapping(s, index + 1);
2066         }
2067         assert(mapping == array_get(&(s->mapping), s->mapping.next - 1)
2068                 || mapping[1].begin >= c);
2069         mapping->end = c;
2070
2071         if (!fat_eof(s, c1)) {
2072             int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next);
2073             mapping_t* next_mapping = i >= s->mapping.next ? NULL :
2074                 array_get(&(s->mapping), i);
2075
2076             if (next_mapping == NULL || next_mapping->begin > c1) {
2077                 int i1 = array_index(&(s->mapping), mapping);
2078
2079                 next_mapping = insert_mapping(s, c1, c1+1);
2080
2081                 if (c1 < c)
2082                     i1++;
2083                 mapping = array_get(&(s->mapping), i1);
2084             }
2085
2086             next_mapping->dir_index = mapping->dir_index;
2087             next_mapping->first_mapping_index =
2088                 mapping->first_mapping_index < 0 ?
2089                 array_index(&(s->mapping), mapping) :
2090                 mapping->first_mapping_index;
2091             next_mapping->path = mapping->path;
2092             next_mapping->mode = mapping->mode;
2093             next_mapping->read_only = mapping->read_only;
2094             if (mapping->mode & MODE_DIRECTORY) {
2095                 next_mapping->info.dir.parent_mapping_index =
2096                         mapping->info.dir.parent_mapping_index;
2097                 next_mapping->info.dir.first_dir_index =
2098                         mapping->info.dir.first_dir_index +
2099                         0x10 * s->sectors_per_cluster *
2100                         (mapping->end - mapping->begin);
2101             } else
2102                 next_mapping->info.file.offset = mapping->info.file.offset +
2103                         mapping->end - mapping->begin;
2104
2105             mapping = next_mapping;
2106         }
2107
2108         cluster = c1;
2109     }
2110
2111     return 0;
2112 }
2113
2114 static int commit_direntries(BDRVVVFATState* s,
2115         int dir_index, int parent_mapping_index)
2116 {
2117     direntry_t* direntry = array_get(&(s->directory), dir_index);
2118     uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
2119     mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2120
2121     int factor = 0x10 * s->sectors_per_cluster;
2122     int old_cluster_count, new_cluster_count;
2123     int current_dir_index = mapping->info.dir.first_dir_index;
2124     int first_dir_index = current_dir_index;
2125     int ret, i;
2126     uint32_t c;
2127
2128 DLOG(fprintf(stderr, "commit_direntries for %s, parent_mapping_index %d\n", mapping->path, parent_mapping_index));
2129
2130     assert(direntry);
2131     assert(mapping);
2132     assert(mapping->begin == first_cluster);
2133     assert(mapping->info.dir.first_dir_index < s->directory.next);
2134     assert(mapping->mode & MODE_DIRECTORY);
2135     assert(dir_index == 0 || is_directory(direntry));
2136
2137     mapping->info.dir.parent_mapping_index = parent_mapping_index;
2138
2139     if (first_cluster == 0) {
2140         old_cluster_count = new_cluster_count =
2141             s->last_cluster_of_root_directory;
2142     } else {
2143         for (old_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2144                 c = fat_get(s, c))
2145             old_cluster_count++;
2146
2147         for (new_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2148                 c = modified_fat_get(s, c))
2149             new_cluster_count++;
2150     }
2151
2152     if (new_cluster_count > old_cluster_count) {
2153         if (insert_direntries(s,
2154                 current_dir_index + factor * old_cluster_count,
2155                 factor * (new_cluster_count - old_cluster_count)) == NULL)
2156             return -1;
2157     } else if (new_cluster_count < old_cluster_count)
2158         remove_direntries(s,
2159                 current_dir_index + factor * new_cluster_count,
2160                 factor * (old_cluster_count - new_cluster_count));
2161
2162     for (c = first_cluster; !fat_eof(s, c); c = modified_fat_get(s, c)) {
2163         void* direntry = array_get(&(s->directory), current_dir_index);
2164         int ret = vvfat_read(s->bs, cluster2sector(s, c), direntry,
2165                 s->sectors_per_cluster);
2166         if (ret)
2167             return ret;
2168         assert(!strncmp(s->directory.pointer, "QEMU", 4));
2169         current_dir_index += factor;
2170     }
2171
2172     ret = commit_mappings(s, first_cluster, dir_index);
2173     if (ret)
2174         return ret;
2175
2176     /* recurse */
2177     for (i = 0; i < factor * new_cluster_count; i++) {
2178         direntry = array_get(&(s->directory), first_dir_index + i);
2179         if (is_directory(direntry) && !is_dot(direntry)) {
2180             mapping = find_mapping_for_cluster(s, first_cluster);
2181             assert(mapping->mode & MODE_DIRECTORY);
2182             ret = commit_direntries(s, first_dir_index + i,
2183                 array_index(&(s->mapping), mapping));
2184             if (ret)
2185                 return ret;
2186         }
2187     }
2188
2189     return 0;
2190 }
2191
2192 /* commit one file (adjust contents, adjust mapping),
2193    return first_mapping_index */
2194 static int commit_one_file(BDRVVVFATState* s,
2195         int dir_index, uint32_t offset)
2196 {
2197     direntry_t* direntry = array_get(&(s->directory), dir_index);
2198     uint32_t c = begin_of_direntry(direntry);
2199     uint32_t first_cluster = c;
2200     mapping_t* mapping = find_mapping_for_cluster(s, c);
2201     uint32_t size = filesize_of_direntry(direntry);
2202     char* cluster = g_malloc(s->cluster_size);
2203     uint32_t i;
2204     int fd = 0;
2205
2206     assert(offset < size);
2207     assert((offset % s->cluster_size) == 0);
2208
2209     for (i = s->cluster_size; i < offset; i += s->cluster_size)
2210         c = modified_fat_get(s, c);
2211
2212     fd = open(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666);
2213     if (fd < 0) {
2214         fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path,
2215                 strerror(errno), errno);
2216         g_free(cluster);
2217         return fd;
2218     }
2219     if (offset > 0) {
2220         if (lseek(fd, offset, SEEK_SET) != offset) {
2221             g_free(cluster);
2222             return -3;
2223         }
2224     }
2225
2226     while (offset < size) {
2227         uint32_t c1;
2228         int rest_size = (size - offset > s->cluster_size ?
2229                 s->cluster_size : size - offset);
2230         int ret;
2231
2232         c1 = modified_fat_get(s, c);
2233
2234         assert((size - offset == 0 && fat_eof(s, c)) ||
2235                 (size > offset && c >=2 && !fat_eof(s, c)));
2236
2237         ret = vvfat_read(s->bs, cluster2sector(s, c),
2238             (uint8_t*)cluster, (rest_size + 0x1ff) / 0x200);
2239
2240         if (ret < 0) {
2241             g_free(cluster);
2242             return ret;
2243         }
2244
2245         if (write(fd, cluster, rest_size) < 0) {
2246             g_free(cluster);
2247             return -2;
2248         }
2249
2250         offset += rest_size;
2251         c = c1;
2252     }
2253
2254     if (ftruncate(fd, size)) {
2255         perror("ftruncate()");
2256         close(fd);
2257         g_free(cluster);
2258         return -4;
2259     }
2260     close(fd);
2261     g_free(cluster);
2262
2263     return commit_mappings(s, first_cluster, dir_index);
2264 }
2265
2266 #ifdef DEBUG
2267 /* test, if all mappings point to valid direntries */
2268 static void check1(BDRVVVFATState* s)
2269 {
2270     int i;
2271     for (i = 0; i < s->mapping.next; i++) {
2272         mapping_t* mapping = array_get(&(s->mapping), i);
2273         if (mapping->mode & MODE_DELETED) {
2274             fprintf(stderr, "deleted\n");
2275             continue;
2276         }
2277         assert(mapping->dir_index < s->directory.next);
2278         direntry_t* direntry = array_get(&(s->directory), mapping->dir_index);
2279         assert(mapping->begin == begin_of_direntry(direntry) || mapping->first_mapping_index >= 0);
2280         if (mapping->mode & MODE_DIRECTORY) {
2281             assert(mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster * (mapping->end - mapping->begin) <= s->directory.next);
2282             assert((mapping->info.dir.first_dir_index % (0x10 * s->sectors_per_cluster)) == 0);
2283         }
2284     }
2285 }
2286
2287 /* test, if all direntries have mappings */
2288 static void check2(BDRVVVFATState* s)
2289 {
2290     int i;
2291     int first_mapping = -1;
2292
2293     for (i = 0; i < s->directory.next; i++) {
2294         direntry_t* direntry = array_get(&(s->directory), i);
2295
2296         if (is_short_name(direntry) && begin_of_direntry(direntry)) {
2297             mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
2298             assert(mapping);
2299             assert(mapping->dir_index == i || is_dot(direntry));
2300             assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry));
2301         }
2302
2303         if ((i % (0x10 * s->sectors_per_cluster)) == 0) {
2304             /* cluster start */
2305             int j, count = 0;
2306
2307             for (j = 0; j < s->mapping.next; j++) {
2308                 mapping_t* mapping = array_get(&(s->mapping), j);
2309                 if (mapping->mode & MODE_DELETED)
2310                     continue;
2311                 if (mapping->mode & MODE_DIRECTORY) {
2312                     if (mapping->info.dir.first_dir_index <= i && mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster > i) {
2313                         assert(++count == 1);
2314                         if (mapping->first_mapping_index == -1)
2315                             first_mapping = array_index(&(s->mapping), mapping);
2316                         else
2317                             assert(first_mapping == mapping->first_mapping_index);
2318                         if (mapping->info.dir.parent_mapping_index < 0)
2319                             assert(j == 0);
2320                         else {
2321                             mapping_t* parent = array_get(&(s->mapping), mapping->info.dir.parent_mapping_index);
2322                             assert(parent->mode & MODE_DIRECTORY);
2323                             assert(parent->info.dir.first_dir_index < mapping->info.dir.first_dir_index);
2324                         }
2325                     }
2326                 }
2327             }
2328             if (count == 0)
2329                 first_mapping = -1;
2330         }
2331     }
2332 }
2333 #endif
2334
2335 static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2336 {
2337     int i;
2338
2339 #ifdef DEBUG
2340     fprintf(stderr, "handle_renames\n");
2341     for (i = 0; i < s->commits.next; i++) {
2342         commit_t* commit = array_get(&(s->commits), i);
2343         fprintf(stderr, "%d, %s (%d, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action);
2344     }
2345 #endif
2346
2347     for (i = 0; i < s->commits.next;) {
2348         commit_t* commit = array_get(&(s->commits), i);
2349         if (commit->action == ACTION_RENAME) {
2350             mapping_t* mapping = find_mapping_for_cluster(s,
2351                     commit->param.rename.cluster);
2352             char* old_path = mapping->path;
2353
2354             assert(commit->path);
2355             mapping->path = commit->path;
2356             if (rename(old_path, mapping->path))
2357                 return -2;
2358
2359             if (mapping->mode & MODE_DIRECTORY) {
2360                 int l1 = strlen(mapping->path);
2361                 int l2 = strlen(old_path);
2362                 int diff = l1 - l2;
2363                 direntry_t* direntry = array_get(&(s->directory),
2364                         mapping->info.dir.first_dir_index);
2365                 uint32_t c = mapping->begin;
2366                 int i = 0;
2367
2368                 /* recurse */
2369                 while (!fat_eof(s, c)) {
2370                     do {
2371                         direntry_t* d = direntry + i;
2372
2373                         if (is_file(d) || (is_directory(d) && !is_dot(d))) {
2374                             mapping_t* m = find_mapping_for_cluster(s,
2375                                     begin_of_direntry(d));
2376                             int l = strlen(m->path);
2377                             char* new_path = g_malloc(l + diff + 1);
2378
2379                             assert(!strncmp(m->path, mapping->path, l2));
2380
2381                             pstrcpy(new_path, l + diff + 1, mapping->path);
2382                             pstrcpy(new_path + l1, l + diff + 1 - l1,
2383                                     m->path + l2);
2384
2385                             schedule_rename(s, m->begin, new_path);
2386                         }
2387                         i++;
2388                     } while((i % (0x10 * s->sectors_per_cluster)) != 0);
2389                     c = fat_get(s, c);
2390                 }
2391             }
2392
2393             g_free(old_path);
2394             array_remove(&(s->commits), i);
2395             continue;
2396         } else if (commit->action == ACTION_MKDIR) {
2397             mapping_t* mapping;
2398             int j, parent_path_len;
2399
2400 #ifdef __MINGW32__
2401             if (mkdir(commit->path))
2402                 return -5;
2403 #else
2404             if (mkdir(commit->path, 0755))
2405                 return -5;
2406 #endif
2407
2408             mapping = insert_mapping(s, commit->param.mkdir.cluster,
2409                     commit->param.mkdir.cluster + 1);
2410             if (mapping == NULL)
2411                 return -6;
2412
2413             mapping->mode = MODE_DIRECTORY;
2414             mapping->read_only = 0;
2415             mapping->path = commit->path;
2416             j = s->directory.next;
2417             assert(j);
2418             insert_direntries(s, s->directory.next,
2419                     0x10 * s->sectors_per_cluster);
2420             mapping->info.dir.first_dir_index = j;
2421
2422             parent_path_len = strlen(commit->path)
2423                 - strlen(get_basename(commit->path)) - 1;
2424             for (j = 0; j < s->mapping.next; j++) {
2425                 mapping_t* m = array_get(&(s->mapping), j);
2426                 if (m->first_mapping_index < 0 && m != mapping &&
2427                         !strncmp(m->path, mapping->path, parent_path_len) &&
2428                         strlen(m->path) == parent_path_len)
2429                     break;
2430             }
2431             assert(j < s->mapping.next);
2432             mapping->info.dir.parent_mapping_index = j;
2433
2434             array_remove(&(s->commits), i);
2435             continue;
2436         }
2437
2438         i++;
2439     }
2440     return 0;
2441 }
2442
2443 /*
2444  * TODO: make sure that the short name is not matching *another* file
2445  */
2446 static int handle_commits(BDRVVVFATState* s)
2447 {
2448     int i, fail = 0;
2449
2450     vvfat_close_current_file(s);
2451
2452     for (i = 0; !fail && i < s->commits.next; i++) {
2453         commit_t* commit = array_get(&(s->commits), i);
2454         switch(commit->action) {
2455         case ACTION_RENAME: case ACTION_MKDIR:
2456             abort();
2457             fail = -2;
2458             break;
2459         case ACTION_WRITEOUT: {
2460 #ifndef NDEBUG
2461             /* these variables are only used by assert() below */
2462             direntry_t* entry = array_get(&(s->directory),
2463                     commit->param.writeout.dir_index);
2464             uint32_t begin = begin_of_direntry(entry);
2465             mapping_t* mapping = find_mapping_for_cluster(s, begin);
2466 #endif
2467
2468             assert(mapping);
2469             assert(mapping->begin == begin);
2470             assert(commit->path == NULL);
2471
2472             if (commit_one_file(s, commit->param.writeout.dir_index,
2473                         commit->param.writeout.modified_offset))
2474                 fail = -3;
2475
2476             break;
2477         }
2478         case ACTION_NEW_FILE: {
2479             int begin = commit->param.new_file.first_cluster;
2480             mapping_t* mapping = find_mapping_for_cluster(s, begin);
2481             direntry_t* entry;
2482             int i;
2483
2484             /* find direntry */
2485             for (i = 0; i < s->directory.next; i++) {
2486                 entry = array_get(&(s->directory), i);
2487                 if (is_file(entry) && begin_of_direntry(entry) == begin)
2488                     break;
2489             }
2490
2491             if (i >= s->directory.next) {
2492                 fail = -6;
2493                 continue;
2494             }
2495
2496             /* make sure there exists an initial mapping */
2497             if (mapping && mapping->begin != begin) {
2498                 mapping->end = begin;
2499                 mapping = NULL;
2500             }
2501             if (mapping == NULL) {
2502                 mapping = insert_mapping(s, begin, begin+1);
2503             }
2504             /* most members will be fixed in commit_mappings() */
2505             assert(commit->path);
2506             mapping->path = commit->path;
2507             mapping->read_only = 0;
2508             mapping->mode = MODE_NORMAL;
2509             mapping->info.file.offset = 0;
2510
2511             if (commit_one_file(s, i, 0))
2512                 fail = -7;
2513
2514             break;
2515         }
2516         default:
2517             abort();
2518         }
2519     }
2520     if (i > 0 && array_remove_slice(&(s->commits), 0, i))
2521         return -1;
2522     return fail;
2523 }
2524
2525 static int handle_deletes(BDRVVVFATState* s)
2526 {
2527     int i, deferred = 1, deleted = 1;
2528
2529     /* delete files corresponding to mappings marked as deleted */
2530     /* handle DELETEs and unused mappings (modified_fat_get(s, mapping->begin) == 0) */
2531     while (deferred && deleted) {
2532         deferred = 0;
2533         deleted = 0;
2534
2535         for (i = 1; i < s->mapping.next; i++) {
2536             mapping_t* mapping = array_get(&(s->mapping), i);
2537             if (mapping->mode & MODE_DELETED) {
2538                 direntry_t* entry = array_get(&(s->directory),
2539                         mapping->dir_index);
2540
2541                 if (is_free(entry)) {
2542                     /* remove file/directory */
2543                     if (mapping->mode & MODE_DIRECTORY) {
2544                         int j, next_dir_index = s->directory.next,
2545                         first_dir_index = mapping->info.dir.first_dir_index;
2546
2547                         if (rmdir(mapping->path) < 0) {
2548                             if (errno == ENOTEMPTY) {
2549                                 deferred++;
2550                                 continue;
2551                             } else
2552                                 return -5;
2553                         }
2554
2555                         for (j = 1; j < s->mapping.next; j++) {
2556                             mapping_t* m = array_get(&(s->mapping), j);
2557                             if (m->mode & MODE_DIRECTORY &&
2558                                     m->info.dir.first_dir_index >
2559                                     first_dir_index &&
2560                                     m->info.dir.first_dir_index <
2561                                     next_dir_index)
2562                                 next_dir_index =
2563                                     m->info.dir.first_dir_index;
2564                         }
2565                         remove_direntries(s, first_dir_index,
2566                                 next_dir_index - first_dir_index);
2567
2568                         deleted++;
2569                     }
2570                 } else {
2571                     if (unlink(mapping->path))
2572                         return -4;
2573                     deleted++;
2574                 }
2575                 DLOG(fprintf(stderr, "DELETE (%d)\n", i); print_mapping(mapping); print_direntry(entry));
2576                 remove_mapping(s, i);
2577             }
2578         }
2579     }
2580
2581     return 0;
2582 }
2583
2584 /*
2585  * synchronize mapping with new state:
2586  *
2587  * - copy FAT (with bdrv_read)
2588  * - mark all filenames corresponding to mappings as deleted
2589  * - recurse direntries from root (using bs->bdrv_read)
2590  * - delete files corresponding to mappings marked as deleted
2591  */
2592 static int do_commit(BDRVVVFATState* s)
2593 {
2594     int ret = 0;
2595
2596     /* the real meat are the commits. Nothing to do? Move along! */
2597     if (s->commits.next == 0)
2598         return 0;
2599
2600     vvfat_close_current_file(s);
2601
2602     ret = handle_renames_and_mkdirs(s);
2603     if (ret) {
2604         fprintf(stderr, "Error handling renames (%d)\n", ret);
2605         abort();
2606         return ret;
2607     }
2608
2609     /* copy FAT (with bdrv_read) */
2610     memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
2611
2612     /* recurse direntries from root (using bs->bdrv_read) */
2613     ret = commit_direntries(s, 0, -1);
2614     if (ret) {
2615         fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
2616         abort();
2617         return ret;
2618     }
2619
2620     ret = handle_commits(s);
2621     if (ret) {
2622         fprintf(stderr, "Error handling commits (%d)\n", ret);
2623         abort();
2624         return ret;
2625     }
2626
2627     ret = handle_deletes(s);
2628     if (ret) {
2629         fprintf(stderr, "Error deleting\n");
2630         abort();
2631         return ret;
2632     }
2633
2634     if (s->qcow->drv->bdrv_make_empty) {
2635         s->qcow->drv->bdrv_make_empty(s->qcow);
2636     }
2637
2638     memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
2639
2640 DLOG(checkpoint());
2641     return 0;
2642 }
2643
2644 static int try_commit(BDRVVVFATState* s)
2645 {
2646     vvfat_close_current_file(s);
2647 DLOG(checkpoint());
2648     if(!is_consistent(s))
2649         return -1;
2650     return do_commit(s);
2651 }
2652
2653 static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
2654                     const uint8_t *buf, int nb_sectors)
2655 {
2656     BDRVVVFATState *s = bs->opaque;
2657     int i, ret;
2658
2659 DLOG(checkpoint());
2660
2661     /* Check if we're operating in read-only mode */
2662     if (s->qcow == NULL) {
2663         return -EACCES;
2664     }
2665
2666     vvfat_close_current_file(s);
2667
2668     /*
2669      * Some sanity checks:
2670      * - do not allow writing to the boot sector
2671      * - do not allow to write non-ASCII filenames
2672      */
2673
2674     if (sector_num < s->first_sectors_number)
2675         return -1;
2676
2677     for (i = sector2cluster(s, sector_num);
2678             i <= sector2cluster(s, sector_num + nb_sectors - 1);) {
2679         mapping_t* mapping = find_mapping_for_cluster(s, i);
2680         if (mapping) {
2681             if (mapping->read_only) {
2682                 fprintf(stderr, "Tried to write to write-protected file %s\n",
2683                         mapping->path);
2684                 return -1;
2685             }
2686
2687             if (mapping->mode & MODE_DIRECTORY) {
2688                 int begin = cluster2sector(s, i);
2689                 int end = begin + s->sectors_per_cluster, k;
2690                 int dir_index;
2691                 const direntry_t* direntries;
2692                 long_file_name lfn;
2693
2694                 lfn_init(&lfn);
2695
2696                 if (begin < sector_num)
2697                     begin = sector_num;
2698                 if (end > sector_num + nb_sectors)
2699                     end = sector_num + nb_sectors;
2700                 dir_index  = mapping->dir_index +
2701                     0x10 * (begin - mapping->begin * s->sectors_per_cluster);
2702                 direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
2703
2704                 for (k = 0; k < (end - begin) * 0x10; k++) {
2705                     /* do not allow non-ASCII filenames */
2706                     if (parse_long_name(&lfn, direntries + k) < 0) {
2707                         fprintf(stderr, "Warning: non-ASCII filename\n");
2708                         return -1;
2709                     }
2710                     /* no access to the direntry of a read-only file */
2711                     else if (is_short_name(direntries+k) &&
2712                             (direntries[k].attributes & 1)) {
2713                         if (memcmp(direntries + k,
2714                                     array_get(&(s->directory), dir_index + k),
2715                                     sizeof(direntry_t))) {
2716                             fprintf(stderr, "Warning: tried to write to write-protected file\n");
2717                             return -1;
2718                         }
2719                     }
2720                 }
2721             }
2722             i = mapping->end;
2723         } else
2724             i++;
2725     }
2726
2727     /*
2728      * Use qcow backend. Commit later.
2729      */
2730 DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
2731     ret = bdrv_write(s->qcow, sector_num, buf, nb_sectors);
2732     if (ret < 0) {
2733         fprintf(stderr, "Error writing to qcow backend\n");
2734         return ret;
2735     }
2736
2737     for (i = sector2cluster(s, sector_num);
2738             i <= sector2cluster(s, sector_num + nb_sectors - 1); i++)
2739         if (i >= 0)
2740             s->used_clusters[i] |= USED_ALLOCATED;
2741
2742 DLOG(checkpoint());
2743     /* TODO: add timeout */
2744     try_commit(s);
2745
2746 DLOG(checkpoint());
2747     return 0;
2748 }
2749
2750 static coroutine_fn int vvfat_co_write(BlockDriverState *bs, int64_t sector_num,
2751                                        const uint8_t *buf, int nb_sectors)
2752 {
2753     int ret;
2754     BDRVVVFATState *s = bs->opaque;
2755     qemu_co_mutex_lock(&s->lock);
2756     ret = vvfat_write(bs, sector_num, buf, nb_sectors);
2757     qemu_co_mutex_unlock(&s->lock);
2758     return ret;
2759 }
2760
2761 static int coroutine_fn vvfat_co_is_allocated(BlockDriverState *bs,
2762         int64_t sector_num, int nb_sectors, int* n)
2763 {
2764     BDRVVVFATState* s = bs->opaque;
2765     *n = s->sector_count - sector_num;
2766     if (*n > nb_sectors)
2767         *n = nb_sectors;
2768     else if (*n < 0)
2769         return 0;
2770     return 1;
2771 }
2772
2773 static int write_target_commit(BlockDriverState *bs, int64_t sector_num,
2774         const uint8_t* buffer, int nb_sectors) {
2775     BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
2776     return try_commit(s);
2777 }
2778
2779 static void write_target_close(BlockDriverState *bs) {
2780     BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
2781     bdrv_delete(s->qcow);
2782     g_free(s->qcow_filename);
2783 }
2784
2785 static BlockDriver vvfat_write_target = {
2786     .format_name        = "vvfat_write_target",
2787     .bdrv_write         = write_target_commit,
2788     .bdrv_close         = write_target_close,
2789 };
2790
2791 static int enable_write_target(BDRVVVFATState *s)
2792 {
2793     BlockDriver *bdrv_qcow;
2794     QEMUOptionParameter *options;
2795     int ret;
2796     int size = sector2cluster(s, s->sector_count);
2797     s->used_clusters = calloc(size, 1);
2798
2799     array_init(&(s->commits), sizeof(commit_t));
2800
2801     s->qcow_filename = g_malloc(1024);
2802     get_tmp_filename(s->qcow_filename, 1024);
2803
2804     bdrv_qcow = bdrv_find_format("qcow");
2805     options = parse_option_parameters("", bdrv_qcow->create_options, NULL);
2806     set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512);
2807     set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:");
2808
2809     if (bdrv_create(bdrv_qcow, s->qcow_filename, options) < 0)
2810         return -1;
2811
2812     s->qcow = bdrv_new("");
2813     if (s->qcow == NULL) {
2814         return -1;
2815     }
2816
2817     ret = bdrv_open(s->qcow, s->qcow_filename,
2818             BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, bdrv_qcow);
2819     if (ret < 0) {
2820         return ret;
2821     }
2822
2823 #ifndef _WIN32
2824     unlink(s->qcow_filename);
2825 #endif
2826
2827     s->bs->backing_hd = calloc(sizeof(BlockDriverState), 1);
2828     s->bs->backing_hd->drv = &vvfat_write_target;
2829     s->bs->backing_hd->opaque = g_malloc(sizeof(void*));
2830     *(void**)s->bs->backing_hd->opaque = s;
2831
2832     return 0;
2833 }
2834
2835 static void vvfat_close(BlockDriverState *bs)
2836 {
2837     BDRVVVFATState *s = bs->opaque;
2838
2839     vvfat_close_current_file(s);
2840     array_free(&(s->fat));
2841     array_free(&(s->directory));
2842     array_free(&(s->mapping));
2843     g_free(s->cluster_buffer);
2844
2845     if (s->qcow) {
2846         migrate_del_blocker(s->migration_blocker);
2847         error_free(s->migration_blocker);
2848     }
2849 }
2850
2851 static BlockDriver bdrv_vvfat = {
2852     .format_name        = "vvfat",
2853     .instance_size      = sizeof(BDRVVVFATState),
2854     .bdrv_file_open     = vvfat_open,
2855     .bdrv_read          = vvfat_co_read,
2856     .bdrv_write         = vvfat_co_write,
2857     .bdrv_close         = vvfat_close,
2858     .bdrv_co_is_allocated = vvfat_co_is_allocated,
2859     .protocol_name      = "fat",
2860 };
2861
2862 static void bdrv_vvfat_init(void)
2863 {
2864     bdrv_register(&bdrv_vvfat);
2865 }
2866
2867 block_init(bdrv_vvfat_init);
2868
2869 #ifdef DEBUG
2870 static void checkpoint(void) {
2871     assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2);
2872     check1(vvv);
2873     check2(vvv);
2874     assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY));
2875 #if 0
2876     if (((direntry_t*)vvv->directory.pointer)[1].attributes != 0xf)
2877         fprintf(stderr, "Nonono!\n");
2878     mapping_t* mapping;
2879     direntry_t* direntry;
2880     assert(vvv->mapping.size >= vvv->mapping.item_size * vvv->mapping.next);
2881     assert(vvv->directory.size >= vvv->directory.item_size * vvv->directory.next);
2882     if (vvv->mapping.next<47)
2883         return;
2884     assert((mapping = array_get(&(vvv->mapping), 47)));
2885     assert(mapping->dir_index < vvv->directory.next);
2886     direntry = array_get(&(vvv->directory), mapping->dir_index);
2887     assert(!memcmp(direntry->name, "USB     H  ", 11) || direntry->name[0]==0);
2888 #endif
2889 }
2890 #endif
This page took 0.185734 seconds and 4 git commands to generate.