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