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