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