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