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