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