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