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