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