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