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