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