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