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