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