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