qxl: store memory region and offset instead of pointer for guest slots
[qemu/kevin.git] / block / vvfat.c
blob5569450616c20cb302c0a3806eb828aa1fb74357
1 /* vim:set shiftwidth=4 ts=4: */
2 /*
3 * QEMU Block driver for virtual VFAT (shadows a local directory)
5 * Copyright (c) 2004,2005 Johannes E. Schindelin
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:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
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.
25 #include "qemu/osdep.h"
26 #include <dirent.h>
27 #include "qapi/error.h"
28 #include "block/block_int.h"
29 #include "qemu/module.h"
30 #include "qemu/bswap.h"
31 #include "migration/migration.h"
32 #include "qapi/qmp/qint.h"
33 #include "qapi/qmp/qbool.h"
34 #include "qapi/qmp/qstring.h"
35 #include "qemu/cutils.h"
37 #ifndef S_IWGRP
38 #define S_IWGRP 0
39 #endif
40 #ifndef S_IWOTH
41 #define S_IWOTH 0
42 #endif
44 /* TODO: add ":bootsector=blabla.img:" */
45 /* LATER TODO: add automatic boot sector generation from
46 BOOTEASY.ASM and Ranish Partition Manager
47 Note that DOS assumes the system files to be the first files in the
48 file system (test if the boot sector still relies on that fact)! */
49 /* MAYBE TODO: write block-visofs.c */
50 /* TODO: call try_commit() only after a timeout */
52 /* #define DEBUG */
54 #ifdef DEBUG
56 #define DLOG(a) a
58 static void checkpoint(void);
60 #ifdef __MINGW32__
61 void nonono(const char* file, int line, const char* msg) {
62 fprintf(stderr, "Nonono! %s:%d %s\n", file, line, msg);
63 exit(-5);
65 #undef assert
66 #define assert(a) do {if (!(a)) nonono(__FILE__, __LINE__, #a);}while(0)
67 #endif
69 #else
71 #define DLOG(a)
73 #endif
75 /* dynamic array functions */
76 typedef struct array_t {
77 char* pointer;
78 unsigned int size,next,item_size;
79 } array_t;
81 static inline void array_init(array_t* array,unsigned int item_size)
83 array->pointer = NULL;
84 array->size=0;
85 array->next=0;
86 array->item_size=item_size;
89 static inline void array_free(array_t* array)
91 g_free(array->pointer);
92 array->size=array->next=0;
95 /* does not automatically grow */
96 static inline void* array_get(array_t* array,unsigned int index) {
97 assert(index < array->next);
98 return array->pointer + index * array->item_size;
101 static inline int array_ensure_allocated(array_t* array, int index)
103 if((index + 1) * array->item_size > array->size) {
104 int new_size = (index + 32) * array->item_size;
105 array->pointer = g_realloc(array->pointer, new_size);
106 if (!array->pointer)
107 return -1;
108 array->size = new_size;
109 array->next = index + 1;
112 return 0;
115 static inline void* array_get_next(array_t* array) {
116 unsigned int next = array->next;
118 if (array_ensure_allocated(array, next) < 0)
119 return NULL;
121 array->next = next + 1;
122 return array_get(array, next);
125 static inline void* array_insert(array_t* array,unsigned int index,unsigned int count) {
126 if((array->next+count)*array->item_size>array->size) {
127 int increment=count*array->item_size;
128 array->pointer=g_realloc(array->pointer,array->size+increment);
129 if(!array->pointer)
130 return NULL;
131 array->size+=increment;
133 memmove(array->pointer+(index+count)*array->item_size,
134 array->pointer+index*array->item_size,
135 (array->next-index)*array->item_size);
136 array->next+=count;
137 return array->pointer+index*array->item_size;
140 /* this performs a "roll", so that the element which was at index_from becomes
141 * index_to, but the order of all other elements is preserved. */
142 static inline int array_roll(array_t* array,int index_to,int index_from,int count)
144 char* buf;
145 char* from;
146 char* to;
147 int is;
149 if(!array ||
150 index_to<0 || index_to>=array->next ||
151 index_from<0 || index_from>=array->next)
152 return -1;
154 if(index_to==index_from)
155 return 0;
157 is=array->item_size;
158 from=array->pointer+index_from*is;
159 to=array->pointer+index_to*is;
160 buf=g_malloc(is*count);
161 memcpy(buf,from,is*count);
163 if(index_to<index_from)
164 memmove(to+is*count,to,from-to);
165 else
166 memmove(from,from+is*count,to-from);
168 memcpy(to,buf,is*count);
170 g_free(buf);
172 return 0;
175 static inline int array_remove_slice(array_t* array,int index, int count)
177 assert(index >=0);
178 assert(count > 0);
179 assert(index + count <= array->next);
180 if(array_roll(array,array->next-1,index,count))
181 return -1;
182 array->next -= count;
183 return 0;
186 static int array_remove(array_t* array,int index)
188 return array_remove_slice(array, index, 1);
191 /* return the index for a given member */
192 static int array_index(array_t* array, void* pointer)
194 size_t offset = (char*)pointer - array->pointer;
195 assert((offset % array->item_size) == 0);
196 assert(offset/array->item_size < array->next);
197 return offset/array->item_size;
200 /* These structures are used to fake a disk and the VFAT filesystem.
201 * For this reason we need to use QEMU_PACKED. */
203 typedef struct bootsector_t {
204 uint8_t jump[3];
205 uint8_t name[8];
206 uint16_t sector_size;
207 uint8_t sectors_per_cluster;
208 uint16_t reserved_sectors;
209 uint8_t number_of_fats;
210 uint16_t root_entries;
211 uint16_t total_sectors16;
212 uint8_t media_type;
213 uint16_t sectors_per_fat;
214 uint16_t sectors_per_track;
215 uint16_t number_of_heads;
216 uint32_t hidden_sectors;
217 uint32_t total_sectors;
218 union {
219 struct {
220 uint8_t drive_number;
221 uint8_t current_head;
222 uint8_t signature;
223 uint32_t id;
224 uint8_t volume_label[11];
225 } QEMU_PACKED fat16;
226 struct {
227 uint32_t sectors_per_fat;
228 uint16_t flags;
229 uint8_t major,minor;
230 uint32_t first_cluster_of_root_directory;
231 uint16_t info_sector;
232 uint16_t backup_boot_sector;
233 uint16_t ignored;
234 } QEMU_PACKED fat32;
235 } u;
236 uint8_t fat_type[8];
237 uint8_t ignored[0x1c0];
238 uint8_t magic[2];
239 } QEMU_PACKED bootsector_t;
241 typedef struct {
242 uint8_t head;
243 uint8_t sector;
244 uint8_t cylinder;
245 } mbr_chs_t;
247 typedef struct partition_t {
248 uint8_t attributes; /* 0x80 = bootable */
249 mbr_chs_t start_CHS;
250 uint8_t fs_type; /* 0x1 = FAT12, 0x6 = FAT16, 0xe = FAT16_LBA, 0xb = FAT32, 0xc = FAT32_LBA */
251 mbr_chs_t end_CHS;
252 uint32_t start_sector_long;
253 uint32_t length_sector_long;
254 } QEMU_PACKED partition_t;
256 typedef struct mbr_t {
257 uint8_t ignored[0x1b8];
258 uint32_t nt_id;
259 uint8_t ignored2[2];
260 partition_t partition[4];
261 uint8_t magic[2];
262 } QEMU_PACKED mbr_t;
264 typedef struct direntry_t {
265 uint8_t name[8 + 3];
266 uint8_t attributes;
267 uint8_t reserved[2];
268 uint16_t ctime;
269 uint16_t cdate;
270 uint16_t adate;
271 uint16_t begin_hi;
272 uint16_t mtime;
273 uint16_t mdate;
274 uint16_t begin;
275 uint32_t size;
276 } QEMU_PACKED direntry_t;
278 /* this structure are used to transparently access the files */
280 typedef struct mapping_t {
281 /* begin is the first cluster, end is the last+1 */
282 uint32_t begin,end;
283 /* as s->directory is growable, no pointer may be used here */
284 unsigned int dir_index;
285 /* the clusters of a file may be in any order; this points to the first */
286 int first_mapping_index;
287 union {
288 /* offset is
289 * - the offset in the file (in clusters) for a file, or
290 * - the next cluster of the directory for a directory, and
291 * - the address of the buffer for a faked entry
293 struct {
294 uint32_t offset;
295 } file;
296 struct {
297 int parent_mapping_index;
298 int first_dir_index;
299 } dir;
300 } info;
301 /* path contains the full path, i.e. it always starts with s->path */
302 char* path;
304 enum { MODE_UNDEFINED = 0, MODE_NORMAL = 1, MODE_MODIFIED = 2,
305 MODE_DIRECTORY = 4, MODE_FAKED = 8,
306 MODE_DELETED = 16, MODE_RENAMED = 32 } mode;
307 int read_only;
308 } mapping_t;
310 #ifdef DEBUG
311 static void print_direntry(const struct direntry_t*);
312 static void print_mapping(const struct mapping_t* mapping);
313 #endif
315 /* here begins the real VVFAT driver */
317 typedef struct BDRVVVFATState {
318 CoMutex lock;
319 BlockDriverState* bs; /* pointer to parent */
320 unsigned int first_sectors_number; /* 1 for a single partition, 0x40 for a disk with partition table */
321 unsigned char first_sectors[0x40*0x200];
323 int fat_type; /* 16 or 32 */
324 array_t fat,directory,mapping;
325 char volume_label[11];
327 unsigned int cluster_size;
328 unsigned int sectors_per_cluster;
329 unsigned int sectors_per_fat;
330 unsigned int sectors_of_root_directory;
331 uint32_t last_cluster_of_root_directory;
332 unsigned int faked_sectors; /* how many sectors are faked before file data */
333 uint32_t sector_count; /* total number of sectors of the partition */
334 uint32_t cluster_count; /* total number of clusters of this partition */
335 uint32_t max_fat_value;
337 int current_fd;
338 mapping_t* current_mapping;
339 unsigned char* cluster; /* points to current cluster */
340 unsigned char* cluster_buffer; /* points to a buffer to hold temp data */
341 unsigned int current_cluster;
343 /* write support */
344 BlockDriverState* write_target;
345 char* qcow_filename;
346 BlockDriverState* qcow;
347 void* fat2;
348 char* used_clusters;
349 array_t commits;
350 const char* path;
351 int downcase_short_names;
353 Error *migration_blocker;
354 } BDRVVVFATState;
356 /* take the sector position spos and convert it to Cylinder/Head/Sector position
357 * if the position is outside the specified geometry, fill maximum value for CHS
358 * and return 1 to signal overflow.
360 static int sector2CHS(mbr_chs_t *chs, int spos, int cyls, int heads, int secs)
362 int head,sector;
363 sector = spos % secs; spos /= secs;
364 head = spos % heads; spos /= heads;
365 if (spos >= cyls) {
366 /* Overflow,
367 it happens if 32bit sector positions are used, while CHS is only 24bit.
368 Windows/Dos is said to take 1023/255/63 as nonrepresentable CHS */
369 chs->head = 0xFF;
370 chs->sector = 0xFF;
371 chs->cylinder = 0xFF;
372 return 1;
374 chs->head = (uint8_t)head;
375 chs->sector = (uint8_t)( (sector+1) | ((spos>>8)<<6) );
376 chs->cylinder = (uint8_t)spos;
377 return 0;
380 static void init_mbr(BDRVVVFATState *s, int cyls, int heads, int secs)
382 /* TODO: if the files mbr.img and bootsect.img exist, use them */
383 mbr_t* real_mbr=(mbr_t*)s->first_sectors;
384 partition_t* partition = &(real_mbr->partition[0]);
385 int lba;
387 memset(s->first_sectors,0,512);
389 /* Win NT Disk Signature */
390 real_mbr->nt_id= cpu_to_le32(0xbe1afdfa);
392 partition->attributes=0x80; /* bootable */
394 /* LBA is used when partition is outside the CHS geometry */
395 lba = sector2CHS(&partition->start_CHS, s->first_sectors_number - 1,
396 cyls, heads, secs);
397 lba |= sector2CHS(&partition->end_CHS, s->bs->total_sectors - 1,
398 cyls, heads, secs);
400 /*LBA partitions are identified only by start/length_sector_long not by CHS*/
401 partition->start_sector_long = cpu_to_le32(s->first_sectors_number - 1);
402 partition->length_sector_long = cpu_to_le32(s->bs->total_sectors
403 - s->first_sectors_number + 1);
405 /* FAT12/FAT16/FAT32 */
406 /* DOS uses different types when partition is LBA,
407 probably to prevent older versions from using CHS on them */
408 partition->fs_type= s->fat_type==12 ? 0x1:
409 s->fat_type==16 ? (lba?0xe:0x06):
410 /*fat_tyoe==32*/ (lba?0xc:0x0b);
412 real_mbr->magic[0]=0x55; real_mbr->magic[1]=0xaa;
415 /* direntry functions */
417 /* dest is assumed to hold 258 bytes, and pads with 0xffff up to next multiple of 26 */
418 static inline int short2long_name(char* dest,const char* src)
420 int i;
421 int len;
422 for(i=0;i<129 && src[i];i++) {
423 dest[2*i]=src[i];
424 dest[2*i+1]=0;
426 len=2*i;
427 dest[2*i]=dest[2*i+1]=0;
428 for(i=2*i+2;(i%26);i++)
429 dest[i]=0xff;
430 return len;
433 static inline direntry_t* create_long_filename(BDRVVVFATState* s,const char* filename)
435 char buffer[258];
436 int length=short2long_name(buffer,filename),
437 number_of_entries=(length+25)/26,i;
438 direntry_t* entry;
440 for(i=0;i<number_of_entries;i++) {
441 entry=array_get_next(&(s->directory));
442 entry->attributes=0xf;
443 entry->reserved[0]=0;
444 entry->begin=0;
445 entry->name[0]=(number_of_entries-i)|(i==0?0x40:0);
447 for(i=0;i<26*number_of_entries;i++) {
448 int offset=(i%26);
449 if(offset<10) offset=1+offset;
450 else if(offset<22) offset=14+offset-10;
451 else offset=28+offset-22;
452 entry=array_get(&(s->directory),s->directory.next-1-(i/26));
453 entry->name[offset]=buffer[i];
455 return array_get(&(s->directory),s->directory.next-number_of_entries);
458 static char is_free(const direntry_t* direntry)
460 return direntry->name[0]==0xe5 || direntry->name[0]==0x00;
463 static char is_volume_label(const direntry_t* direntry)
465 return direntry->attributes == 0x28;
468 static char is_long_name(const direntry_t* direntry)
470 return direntry->attributes == 0xf;
473 static char is_short_name(const direntry_t* direntry)
475 return !is_volume_label(direntry) && !is_long_name(direntry)
476 && !is_free(direntry);
479 static char is_directory(const direntry_t* direntry)
481 return direntry->attributes & 0x10 && direntry->name[0] != 0xe5;
484 static inline char is_dot(const direntry_t* direntry)
486 return is_short_name(direntry) && direntry->name[0] == '.';
489 static char is_file(const direntry_t* direntry)
491 return is_short_name(direntry) && !is_directory(direntry);
494 static inline uint32_t begin_of_direntry(const direntry_t* direntry)
496 return le16_to_cpu(direntry->begin)|(le16_to_cpu(direntry->begin_hi)<<16);
499 static inline uint32_t filesize_of_direntry(const direntry_t* direntry)
501 return le32_to_cpu(direntry->size);
504 static void set_begin_of_direntry(direntry_t* direntry, uint32_t begin)
506 direntry->begin = cpu_to_le16(begin & 0xffff);
507 direntry->begin_hi = cpu_to_le16((begin >> 16) & 0xffff);
510 /* fat functions */
512 static inline uint8_t fat_chksum(const direntry_t* entry)
514 uint8_t chksum=0;
515 int i;
517 for (i = 0; i < ARRAY_SIZE(entry->name); i++) {
518 chksum = (((chksum & 0xfe) >> 1) |
519 ((chksum & 0x01) ? 0x80 : 0)) + entry->name[i];
522 return chksum;
525 /* if return_time==0, this returns the fat_date, else the fat_time */
526 static uint16_t fat_datetime(time_t time,int return_time) {
527 struct tm* t;
528 struct tm t1;
529 t = &t1;
530 localtime_r(&time,t);
531 if(return_time)
532 return cpu_to_le16((t->tm_sec/2)|(t->tm_min<<5)|(t->tm_hour<<11));
533 return cpu_to_le16((t->tm_mday)|((t->tm_mon+1)<<5)|((t->tm_year-80)<<9));
536 static inline void fat_set(BDRVVVFATState* s,unsigned int cluster,uint32_t value)
538 if(s->fat_type==32) {
539 uint32_t* entry=array_get(&(s->fat),cluster);
540 *entry=cpu_to_le32(value);
541 } else if(s->fat_type==16) {
542 uint16_t* entry=array_get(&(s->fat),cluster);
543 *entry=cpu_to_le16(value&0xffff);
544 } else {
545 int offset = (cluster*3/2);
546 unsigned char* p = array_get(&(s->fat), offset);
547 switch (cluster&1) {
548 case 0:
549 p[0] = value&0xff;
550 p[1] = (p[1]&0xf0) | ((value>>8)&0xf);
551 break;
552 case 1:
553 p[0] = (p[0]&0xf) | ((value&0xf)<<4);
554 p[1] = (value>>4);
555 break;
560 static inline uint32_t fat_get(BDRVVVFATState* s,unsigned int cluster)
562 if(s->fat_type==32) {
563 uint32_t* entry=array_get(&(s->fat),cluster);
564 return le32_to_cpu(*entry);
565 } else if(s->fat_type==16) {
566 uint16_t* entry=array_get(&(s->fat),cluster);
567 return le16_to_cpu(*entry);
568 } else {
569 const uint8_t* x=(uint8_t*)(s->fat.pointer)+cluster*3/2;
570 return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
574 static inline int fat_eof(BDRVVVFATState* s,uint32_t fat_entry)
576 if(fat_entry>s->max_fat_value-8)
577 return -1;
578 return 0;
581 static inline void init_fat(BDRVVVFATState* s)
583 if (s->fat_type == 12) {
584 array_init(&(s->fat),1);
585 array_ensure_allocated(&(s->fat),
586 s->sectors_per_fat * 0x200 * 3 / 2 - 1);
587 } else {
588 array_init(&(s->fat),(s->fat_type==32?4:2));
589 array_ensure_allocated(&(s->fat),
590 s->sectors_per_fat * 0x200 / s->fat.item_size - 1);
592 memset(s->fat.pointer,0,s->fat.size);
594 switch(s->fat_type) {
595 case 12: s->max_fat_value=0xfff; break;
596 case 16: s->max_fat_value=0xffff; break;
597 case 32: s->max_fat_value=0x0fffffff; break;
598 default: s->max_fat_value=0; /* error... */
603 /* TODO: in create_short_filename, 0xe5->0x05 is not yet handled! */
604 /* TODO: in parse_short_filename, 0x05->0xe5 is not yet handled! */
605 static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,
606 unsigned int directory_start, const char* filename, int is_dot)
608 int i,j,long_index=s->directory.next;
609 direntry_t* entry = NULL;
610 direntry_t* entry_long = NULL;
612 if(is_dot) {
613 entry=array_get_next(&(s->directory));
614 memset(entry->name, 0x20, sizeof(entry->name));
615 memcpy(entry->name,filename,strlen(filename));
616 return entry;
619 entry_long=create_long_filename(s,filename);
621 i = strlen(filename);
622 for(j = i - 1; j>0 && filename[j]!='.';j--);
623 if (j > 0)
624 i = (j > 8 ? 8 : j);
625 else if (i > 8)
626 i = 8;
628 entry=array_get_next(&(s->directory));
629 memset(entry->name, 0x20, sizeof(entry->name));
630 memcpy(entry->name, filename, i);
632 if (j > 0) {
633 for (i = 0; i < 3 && filename[j + 1 + i]; i++) {
634 entry->name[8 + i] = filename[j + 1 + i];
638 /* upcase & remove unwanted characters */
639 for(i=10;i>=0;i--) {
640 if(i==10 || i==7) for(;i>0 && entry->name[i]==' ';i--);
641 if(entry->name[i]<=' ' || entry->name[i]>0x7f
642 || strchr(".*?<>|\":/\\[];,+='",entry->name[i]))
643 entry->name[i]='_';
644 else if(entry->name[i]>='a' && entry->name[i]<='z')
645 entry->name[i]+='A'-'a';
648 /* mangle duplicates */
649 while(1) {
650 direntry_t* entry1=array_get(&(s->directory),directory_start);
651 int j;
653 for(;entry1<entry;entry1++)
654 if(!is_long_name(entry1) && !memcmp(entry1->name,entry->name,11))
655 break; /* found dupe */
656 if(entry1==entry) /* no dupe found */
657 break;
659 /* use all 8 characters of name */
660 if(entry->name[7]==' ') {
661 int j;
662 for(j=6;j>0 && entry->name[j]==' ';j--)
663 entry->name[j]='~';
666 /* increment number */
667 for(j=7;j>0 && entry->name[j]=='9';j--)
668 entry->name[j]='0';
669 if(j>0) {
670 if(entry->name[j]<'0' || entry->name[j]>'9')
671 entry->name[j]='0';
672 else
673 entry->name[j]++;
677 /* calculate checksum; propagate to long name */
678 if(entry_long) {
679 uint8_t chksum=fat_chksum(entry);
681 /* calculate anew, because realloc could have taken place */
682 entry_long=array_get(&(s->directory),long_index);
683 while(entry_long<entry && is_long_name(entry_long)) {
684 entry_long->reserved[1]=chksum;
685 entry_long++;
689 return entry;
693 * Read a directory. (the index of the corresponding mapping must be passed).
695 static int read_directory(BDRVVVFATState* s, int mapping_index)
697 mapping_t* mapping = array_get(&(s->mapping), mapping_index);
698 direntry_t* direntry;
699 const char* dirname = mapping->path;
700 int first_cluster = mapping->begin;
701 int parent_index = mapping->info.dir.parent_mapping_index;
702 mapping_t* parent_mapping = (mapping_t*)
703 (parent_index >= 0 ? array_get(&(s->mapping), parent_index) : NULL);
704 int first_cluster_of_parent = parent_mapping ? parent_mapping->begin : -1;
706 DIR* dir=opendir(dirname);
707 struct dirent* entry;
708 int i;
710 assert(mapping->mode & MODE_DIRECTORY);
712 if(!dir) {
713 mapping->end = mapping->begin;
714 return -1;
717 i = mapping->info.dir.first_dir_index =
718 first_cluster == 0 ? 0 : s->directory.next;
720 /* actually read the directory, and allocate the mappings */
721 while((entry=readdir(dir))) {
722 unsigned int length=strlen(dirname)+2+strlen(entry->d_name);
723 char* buffer;
724 direntry_t* direntry;
725 struct stat st;
726 int is_dot=!strcmp(entry->d_name,".");
727 int is_dotdot=!strcmp(entry->d_name,"..");
729 if(first_cluster == 0 && (is_dotdot || is_dot))
730 continue;
732 buffer = g_malloc(length);
733 snprintf(buffer,length,"%s/%s",dirname,entry->d_name);
735 if(stat(buffer,&st)<0) {
736 g_free(buffer);
737 continue;
740 /* create directory entry for this file */
741 direntry=create_short_and_long_name(s, i, entry->d_name,
742 is_dot || is_dotdot);
743 direntry->attributes=(S_ISDIR(st.st_mode)?0x10:0x20);
744 direntry->reserved[0]=direntry->reserved[1]=0;
745 direntry->ctime=fat_datetime(st.st_ctime,1);
746 direntry->cdate=fat_datetime(st.st_ctime,0);
747 direntry->adate=fat_datetime(st.st_atime,0);
748 direntry->begin_hi=0;
749 direntry->mtime=fat_datetime(st.st_mtime,1);
750 direntry->mdate=fat_datetime(st.st_mtime,0);
751 if(is_dotdot)
752 set_begin_of_direntry(direntry, first_cluster_of_parent);
753 else if(is_dot)
754 set_begin_of_direntry(direntry, first_cluster);
755 else
756 direntry->begin=0; /* do that later */
757 if (st.st_size > 0x7fffffff) {
758 fprintf(stderr, "File %s is larger than 2GB\n", buffer);
759 g_free(buffer);
760 closedir(dir);
761 return -2;
763 direntry->size=cpu_to_le32(S_ISDIR(st.st_mode)?0:st.st_size);
765 /* create mapping for this file */
766 if(!is_dot && !is_dotdot && (S_ISDIR(st.st_mode) || st.st_size)) {
767 s->current_mapping = array_get_next(&(s->mapping));
768 s->current_mapping->begin=0;
769 s->current_mapping->end=st.st_size;
771 * we get the direntry of the most recent direntry, which
772 * contains the short name and all the relevant information.
774 s->current_mapping->dir_index=s->directory.next-1;
775 s->current_mapping->first_mapping_index = -1;
776 if (S_ISDIR(st.st_mode)) {
777 s->current_mapping->mode = MODE_DIRECTORY;
778 s->current_mapping->info.dir.parent_mapping_index =
779 mapping_index;
780 } else {
781 s->current_mapping->mode = MODE_UNDEFINED;
782 s->current_mapping->info.file.offset = 0;
784 s->current_mapping->path=buffer;
785 s->current_mapping->read_only =
786 (st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0;
787 } else {
788 g_free(buffer);
791 closedir(dir);
793 /* fill with zeroes up to the end of the cluster */
794 while(s->directory.next%(0x10*s->sectors_per_cluster)) {
795 direntry_t* direntry=array_get_next(&(s->directory));
796 memset(direntry,0,sizeof(direntry_t));
799 /* TODO: if there are more entries, bootsector has to be adjusted! */
800 #define ROOT_ENTRIES (0x02 * 0x10 * s->sectors_per_cluster)
801 if (mapping_index == 0 && s->directory.next < ROOT_ENTRIES) {
802 /* root directory */
803 int cur = s->directory.next;
804 array_ensure_allocated(&(s->directory), ROOT_ENTRIES - 1);
805 s->directory.next = ROOT_ENTRIES;
806 memset(array_get(&(s->directory), cur), 0,
807 (ROOT_ENTRIES - cur) * sizeof(direntry_t));
810 /* reget the mapping, since s->mapping was possibly realloc()ed */
811 mapping = array_get(&(s->mapping), mapping_index);
812 first_cluster += (s->directory.next - mapping->info.dir.first_dir_index)
813 * 0x20 / s->cluster_size;
814 mapping->end = first_cluster;
816 direntry = array_get(&(s->directory), mapping->dir_index);
817 set_begin_of_direntry(direntry, mapping->begin);
819 return 0;
822 static inline uint32_t sector2cluster(BDRVVVFATState* s,off_t sector_num)
824 return (sector_num-s->faked_sectors)/s->sectors_per_cluster;
827 static inline off_t cluster2sector(BDRVVVFATState* s, uint32_t cluster_num)
829 return s->faked_sectors + s->sectors_per_cluster * cluster_num;
832 static int init_directories(BDRVVVFATState* s,
833 const char *dirname, int heads, int secs,
834 Error **errp)
836 bootsector_t* bootsector;
837 mapping_t* mapping;
838 unsigned int i;
839 unsigned int cluster;
841 memset(&(s->first_sectors[0]),0,0x40*0x200);
843 s->cluster_size=s->sectors_per_cluster*0x200;
844 s->cluster_buffer=g_malloc(s->cluster_size);
847 * The formula: sc = spf+1+spf*spc*(512*8/fat_type),
848 * where sc is sector_count,
849 * spf is sectors_per_fat,
850 * spc is sectors_per_clusters, and
851 * fat_type = 12, 16 or 32.
853 i = 1+s->sectors_per_cluster*0x200*8/s->fat_type;
854 s->sectors_per_fat=(s->sector_count+i)/i; /* round up */
856 array_init(&(s->mapping),sizeof(mapping_t));
857 array_init(&(s->directory),sizeof(direntry_t));
859 /* add volume label */
861 direntry_t* entry=array_get_next(&(s->directory));
862 entry->attributes=0x28; /* archive | volume label */
863 memcpy(entry->name, s->volume_label, sizeof(entry->name));
866 /* Now build FAT, and write back information into directory */
867 init_fat(s);
869 s->faked_sectors=s->first_sectors_number+s->sectors_per_fat*2;
870 s->cluster_count=sector2cluster(s, s->sector_count);
872 mapping = array_get_next(&(s->mapping));
873 mapping->begin = 0;
874 mapping->dir_index = 0;
875 mapping->info.dir.parent_mapping_index = -1;
876 mapping->first_mapping_index = -1;
877 mapping->path = g_strdup(dirname);
878 i = strlen(mapping->path);
879 if (i > 0 && mapping->path[i - 1] == '/')
880 mapping->path[i - 1] = '\0';
881 mapping->mode = MODE_DIRECTORY;
882 mapping->read_only = 0;
883 s->path = mapping->path;
885 for (i = 0, cluster = 0; i < s->mapping.next; i++) {
886 /* MS-DOS expects the FAT to be 0 for the root directory
887 * (except for the media byte). */
888 /* LATER TODO: still true for FAT32? */
889 int fix_fat = (i != 0);
890 mapping = array_get(&(s->mapping), i);
892 if (mapping->mode & MODE_DIRECTORY) {
893 mapping->begin = cluster;
894 if(read_directory(s, i)) {
895 error_setg(errp, "Could not read directory %s",
896 mapping->path);
897 return -1;
899 mapping = array_get(&(s->mapping), i);
900 } else {
901 assert(mapping->mode == MODE_UNDEFINED);
902 mapping->mode=MODE_NORMAL;
903 mapping->begin = cluster;
904 if (mapping->end > 0) {
905 direntry_t* direntry = array_get(&(s->directory),
906 mapping->dir_index);
908 mapping->end = cluster + 1 + (mapping->end-1)/s->cluster_size;
909 set_begin_of_direntry(direntry, mapping->begin);
910 } else {
911 mapping->end = cluster + 1;
912 fix_fat = 0;
916 assert(mapping->begin < mapping->end);
918 /* next free cluster */
919 cluster = mapping->end;
921 if(cluster > s->cluster_count) {
922 error_setg(errp,
923 "Directory does not fit in FAT%d (capacity %.2f MB)",
924 s->fat_type, s->sector_count / 2000.0);
925 return -1;
928 /* fix fat for entry */
929 if (fix_fat) {
930 int j;
931 for(j = mapping->begin; j < mapping->end - 1; j++)
932 fat_set(s, j, j+1);
933 fat_set(s, mapping->end - 1, s->max_fat_value);
937 mapping = array_get(&(s->mapping), 0);
938 s->sectors_of_root_directory = mapping->end * s->sectors_per_cluster;
939 s->last_cluster_of_root_directory = mapping->end;
941 /* the FAT signature */
942 fat_set(s,0,s->max_fat_value);
943 fat_set(s,1,s->max_fat_value);
945 s->current_mapping = NULL;
947 bootsector=(bootsector_t*)(s->first_sectors+(s->first_sectors_number-1)*0x200);
948 bootsector->jump[0]=0xeb;
949 bootsector->jump[1]=0x3e;
950 bootsector->jump[2]=0x90;
951 memcpy(bootsector->name,"QEMU ",8);
952 bootsector->sector_size=cpu_to_le16(0x200);
953 bootsector->sectors_per_cluster=s->sectors_per_cluster;
954 bootsector->reserved_sectors=cpu_to_le16(1);
955 bootsector->number_of_fats=0x2; /* number of FATs */
956 bootsector->root_entries=cpu_to_le16(s->sectors_of_root_directory*0x10);
957 bootsector->total_sectors16=s->sector_count>0xffff?0:cpu_to_le16(s->sector_count);
958 bootsector->media_type=(s->first_sectors_number>1?0xf8:0xf0); /* media descriptor (f8=hd, f0=3.5 fd)*/
959 s->fat.pointer[0] = bootsector->media_type;
960 bootsector->sectors_per_fat=cpu_to_le16(s->sectors_per_fat);
961 bootsector->sectors_per_track = cpu_to_le16(secs);
962 bootsector->number_of_heads = cpu_to_le16(heads);
963 bootsector->hidden_sectors=cpu_to_le32(s->first_sectors_number==1?0:0x3f);
964 bootsector->total_sectors=cpu_to_le32(s->sector_count>0xffff?s->sector_count:0);
966 /* LATER TODO: if FAT32, this is wrong */
967 bootsector->u.fat16.drive_number=s->first_sectors_number==1?0:0x80; /* fda=0, hda=0x80 */
968 bootsector->u.fat16.current_head=0;
969 bootsector->u.fat16.signature=0x29;
970 bootsector->u.fat16.id=cpu_to_le32(0xfabe1afd);
972 memcpy(bootsector->u.fat16.volume_label, s->volume_label,
973 sizeof(bootsector->u.fat16.volume_label));
974 memcpy(bootsector->fat_type,(s->fat_type==12?"FAT12 ":s->fat_type==16?"FAT16 ":"FAT32 "),8);
975 bootsector->magic[0]=0x55; bootsector->magic[1]=0xaa;
977 return 0;
980 #ifdef DEBUG
981 static BDRVVVFATState *vvv = NULL;
982 #endif
984 static int enable_write_target(BDRVVVFATState *s, Error **errp);
985 static int is_consistent(BDRVVVFATState *s);
987 static QemuOptsList runtime_opts = {
988 .name = "vvfat",
989 .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
990 .desc = {
992 .name = "dir",
993 .type = QEMU_OPT_STRING,
994 .help = "Host directory to map to the vvfat device",
997 .name = "fat-type",
998 .type = QEMU_OPT_NUMBER,
999 .help = "FAT type (12, 16 or 32)",
1002 .name = "floppy",
1003 .type = QEMU_OPT_BOOL,
1004 .help = "Create a floppy rather than a hard disk image",
1007 .name = "label",
1008 .type = QEMU_OPT_STRING,
1009 .help = "Use a volume label other than QEMU VVFAT",
1012 .name = "rw",
1013 .type = QEMU_OPT_BOOL,
1014 .help = "Make the image writable",
1016 { /* end of list */ }
1020 static void vvfat_parse_filename(const char *filename, QDict *options,
1021 Error **errp)
1023 int fat_type = 0;
1024 bool floppy = false;
1025 bool rw = false;
1026 int i;
1028 if (!strstart(filename, "fat:", NULL)) {
1029 error_setg(errp, "File name string must start with 'fat:'");
1030 return;
1033 /* Parse options */
1034 if (strstr(filename, ":32:")) {
1035 fat_type = 32;
1036 } else if (strstr(filename, ":16:")) {
1037 fat_type = 16;
1038 } else if (strstr(filename, ":12:")) {
1039 fat_type = 12;
1042 if (strstr(filename, ":floppy:")) {
1043 floppy = true;
1046 if (strstr(filename, ":rw:")) {
1047 rw = true;
1050 /* Get the directory name without options */
1051 i = strrchr(filename, ':') - filename;
1052 assert(i >= 3);
1053 if (filename[i - 2] == ':' && qemu_isalpha(filename[i - 1])) {
1054 /* workaround for DOS drive names */
1055 filename += i - 1;
1056 } else {
1057 filename += i + 1;
1060 /* Fill in the options QDict */
1061 qdict_put(options, "dir", qstring_from_str(filename));
1062 qdict_put(options, "fat-type", qint_from_int(fat_type));
1063 qdict_put(options, "floppy", qbool_from_bool(floppy));
1064 qdict_put(options, "rw", qbool_from_bool(rw));
1067 static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
1068 Error **errp)
1070 BDRVVVFATState *s = bs->opaque;
1071 int cyls, heads, secs;
1072 bool floppy;
1073 const char *dirname, *label;
1074 QemuOpts *opts;
1075 Error *local_err = NULL;
1076 int ret;
1078 #ifdef DEBUG
1079 vvv = s;
1080 #endif
1082 opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
1083 qemu_opts_absorb_qdict(opts, options, &local_err);
1084 if (local_err) {
1085 error_propagate(errp, local_err);
1086 ret = -EINVAL;
1087 goto fail;
1090 dirname = qemu_opt_get(opts, "dir");
1091 if (!dirname) {
1092 error_setg(errp, "vvfat block driver requires a 'dir' option");
1093 ret = -EINVAL;
1094 goto fail;
1097 s->fat_type = qemu_opt_get_number(opts, "fat-type", 0);
1098 floppy = qemu_opt_get_bool(opts, "floppy", false);
1100 memset(s->volume_label, ' ', sizeof(s->volume_label));
1101 label = qemu_opt_get(opts, "label");
1102 if (label) {
1103 size_t label_length = strlen(label);
1104 if (label_length > 11) {
1105 error_setg(errp, "vvfat label cannot be longer than 11 bytes");
1106 ret = -EINVAL;
1107 goto fail;
1109 memcpy(s->volume_label, label, label_length);
1110 } else {
1111 memcpy(s->volume_label, "QEMU VVFAT", 10);
1114 if (floppy) {
1115 /* 1.44MB or 2.88MB floppy. 2.88MB can be FAT12 (default) or FAT16. */
1116 if (!s->fat_type) {
1117 s->fat_type = 12;
1118 secs = 36;
1119 s->sectors_per_cluster = 2;
1120 } else {
1121 secs = s->fat_type == 12 ? 18 : 36;
1122 s->sectors_per_cluster = 1;
1124 s->first_sectors_number = 1;
1125 cyls = 80;
1126 heads = 2;
1127 } else {
1128 /* 32MB or 504MB disk*/
1129 if (!s->fat_type) {
1130 s->fat_type = 16;
1132 s->first_sectors_number = 0x40;
1133 cyls = s->fat_type == 12 ? 64 : 1024;
1134 heads = 16;
1135 secs = 63;
1138 switch (s->fat_type) {
1139 case 32:
1140 fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. "
1141 "You are welcome to do so!\n");
1142 break;
1143 case 16:
1144 case 12:
1145 break;
1146 default:
1147 error_setg(errp, "Valid FAT types are only 12, 16 and 32");
1148 ret = -EINVAL;
1149 goto fail;
1153 s->bs = bs;
1155 /* LATER TODO: if FAT32, adjust */
1156 s->sectors_per_cluster=0x10;
1158 s->current_cluster=0xffffffff;
1160 /* read only is the default for safety */
1161 bs->read_only = 1;
1162 s->qcow = s->write_target = NULL;
1163 s->qcow_filename = NULL;
1164 s->fat2 = NULL;
1165 s->downcase_short_names = 1;
1167 fprintf(stderr, "vvfat %s chs %d,%d,%d\n",
1168 dirname, cyls, heads, secs);
1170 s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1);
1172 if (qemu_opt_get_bool(opts, "rw", false)) {
1173 ret = enable_write_target(s, errp);
1174 if (ret < 0) {
1175 goto fail;
1177 bs->read_only = 0;
1180 bs->request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O supported */
1181 bs->total_sectors = cyls * heads * secs;
1183 if (init_directories(s, dirname, heads, secs, errp)) {
1184 ret = -EIO;
1185 goto fail;
1188 s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
1190 if (s->first_sectors_number == 0x40) {
1191 init_mbr(s, cyls, heads, secs);
1194 // assert(is_consistent(s));
1195 qemu_co_mutex_init(&s->lock);
1197 /* Disable migration when vvfat is used rw */
1198 if (s->qcow) {
1199 error_setg(&s->migration_blocker,
1200 "The vvfat (rw) format used by node '%s' "
1201 "does not support live migration",
1202 bdrv_get_device_or_node_name(bs));
1203 migrate_add_blocker(s->migration_blocker);
1206 ret = 0;
1207 fail:
1208 qemu_opts_del(opts);
1209 return ret;
1212 static inline void vvfat_close_current_file(BDRVVVFATState *s)
1214 if(s->current_mapping) {
1215 s->current_mapping = NULL;
1216 if (s->current_fd) {
1217 qemu_close(s->current_fd);
1218 s->current_fd = 0;
1221 s->current_cluster = -1;
1224 /* mappings between index1 and index2-1 are supposed to be ordered
1225 * return value is the index of the last mapping for which end>cluster_num
1227 static inline int find_mapping_for_cluster_aux(BDRVVVFATState* s,int cluster_num,int index1,int index2)
1229 while(1) {
1230 int index3;
1231 mapping_t* mapping;
1232 index3=(index1+index2)/2;
1233 mapping=array_get(&(s->mapping),index3);
1234 assert(mapping->begin < mapping->end);
1235 if(mapping->begin>=cluster_num) {
1236 assert(index2!=index3 || index2==0);
1237 if(index2==index3)
1238 return index1;
1239 index2=index3;
1240 } else {
1241 if(index1==index3)
1242 return mapping->end<=cluster_num ? index2 : index1;
1243 index1=index3;
1245 assert(index1<=index2);
1246 DLOG(mapping=array_get(&(s->mapping),index1);
1247 assert(mapping->begin<=cluster_num);
1248 assert(index2 >= s->mapping.next ||
1249 ((mapping = array_get(&(s->mapping),index2)) &&
1250 mapping->end>cluster_num)));
1254 static inline mapping_t* find_mapping_for_cluster(BDRVVVFATState* s,int cluster_num)
1256 int index=find_mapping_for_cluster_aux(s,cluster_num,0,s->mapping.next);
1257 mapping_t* mapping;
1258 if(index>=s->mapping.next)
1259 return NULL;
1260 mapping=array_get(&(s->mapping),index);
1261 if(mapping->begin>cluster_num)
1262 return NULL;
1263 assert(mapping->begin<=cluster_num && mapping->end>cluster_num);
1264 return mapping;
1267 static int open_file(BDRVVVFATState* s,mapping_t* mapping)
1269 if(!mapping)
1270 return -1;
1271 if(!s->current_mapping ||
1272 strcmp(s->current_mapping->path,mapping->path)) {
1273 /* open file */
1274 int fd = qemu_open(mapping->path, O_RDONLY | O_BINARY | O_LARGEFILE);
1275 if(fd<0)
1276 return -1;
1277 vvfat_close_current_file(s);
1278 s->current_fd = fd;
1279 s->current_mapping = mapping;
1281 return 0;
1284 static inline int read_cluster(BDRVVVFATState *s,int cluster_num)
1286 if(s->current_cluster != cluster_num) {
1287 int result=0;
1288 off_t offset;
1289 assert(!s->current_mapping || s->current_fd || (s->current_mapping->mode & MODE_DIRECTORY));
1290 if(!s->current_mapping
1291 || s->current_mapping->begin>cluster_num
1292 || s->current_mapping->end<=cluster_num) {
1293 /* binary search of mappings for file */
1294 mapping_t* mapping=find_mapping_for_cluster(s,cluster_num);
1296 assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
1298 if (mapping && mapping->mode & MODE_DIRECTORY) {
1299 vvfat_close_current_file(s);
1300 s->current_mapping = mapping;
1301 read_cluster_directory:
1302 offset = s->cluster_size*(cluster_num-s->current_mapping->begin);
1303 s->cluster = (unsigned char*)s->directory.pointer+offset
1304 + 0x20*s->current_mapping->info.dir.first_dir_index;
1305 assert(((s->cluster-(unsigned char*)s->directory.pointer)%s->cluster_size)==0);
1306 assert((char*)s->cluster+s->cluster_size <= s->directory.pointer+s->directory.next*s->directory.item_size);
1307 s->current_cluster = cluster_num;
1308 return 0;
1311 if(open_file(s,mapping))
1312 return -2;
1313 } else if (s->current_mapping->mode & MODE_DIRECTORY)
1314 goto read_cluster_directory;
1316 assert(s->current_fd);
1318 offset=s->cluster_size*(cluster_num-s->current_mapping->begin)+s->current_mapping->info.file.offset;
1319 if(lseek(s->current_fd, offset, SEEK_SET)!=offset)
1320 return -3;
1321 s->cluster=s->cluster_buffer;
1322 result=read(s->current_fd,s->cluster,s->cluster_size);
1323 if(result<0) {
1324 s->current_cluster = -1;
1325 return -1;
1327 s->current_cluster = cluster_num;
1329 return 0;
1332 #ifdef DEBUG
1333 static void print_direntry(const direntry_t* direntry)
1335 int j = 0;
1336 char buffer[1024];
1338 fprintf(stderr, "direntry %p: ", direntry);
1339 if(!direntry)
1340 return;
1341 if(is_long_name(direntry)) {
1342 unsigned char* c=(unsigned char*)direntry;
1343 int i;
1344 for(i=1;i<11 && c[i] && c[i]!=0xff;i+=2)
1345 #define ADD_CHAR(c) {buffer[j] = (c); if (buffer[j] < ' ') buffer[j] = 0xb0; j++;}
1346 ADD_CHAR(c[i]);
1347 for(i=14;i<26 && c[i] && c[i]!=0xff;i+=2)
1348 ADD_CHAR(c[i]);
1349 for(i=28;i<32 && c[i] && c[i]!=0xff;i+=2)
1350 ADD_CHAR(c[i]);
1351 buffer[j] = 0;
1352 fprintf(stderr, "%s\n", buffer);
1353 } else {
1354 int i;
1355 for(i=0;i<11;i++)
1356 ADD_CHAR(direntry->name[i]);
1357 buffer[j] = 0;
1358 fprintf(stderr,"%s attributes=0x%02x begin=%d size=%d\n",
1359 buffer,
1360 direntry->attributes,
1361 begin_of_direntry(direntry),le32_to_cpu(direntry->size));
1365 static void print_mapping(const mapping_t* mapping)
1367 fprintf(stderr, "mapping (%p): begin, end = %d, %d, dir_index = %d, "
1368 "first_mapping_index = %d, name = %s, mode = 0x%x, " ,
1369 mapping, mapping->begin, mapping->end, mapping->dir_index,
1370 mapping->first_mapping_index, mapping->path, mapping->mode);
1372 if (mapping->mode & MODE_DIRECTORY)
1373 fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
1374 else
1375 fprintf(stderr, "offset = %d\n", mapping->info.file.offset);
1377 #endif
1379 static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
1380 uint8_t *buf, int nb_sectors)
1382 BDRVVVFATState *s = bs->opaque;
1383 int i;
1385 for(i=0;i<nb_sectors;i++,sector_num++) {
1386 if (sector_num >= bs->total_sectors)
1387 return -1;
1388 if (s->qcow) {
1389 int n;
1390 if (bdrv_is_allocated(s->qcow, sector_num, nb_sectors-i, &n)) {
1391 DLOG(fprintf(stderr, "sectors %d+%d allocated\n", (int)sector_num, n));
1392 if (bdrv_read(s->qcow, sector_num, buf + i*0x200, n)) {
1393 return -1;
1395 i += n - 1;
1396 sector_num += n - 1;
1397 continue;
1399 DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num));
1401 if(sector_num<s->faked_sectors) {
1402 if(sector_num<s->first_sectors_number)
1403 memcpy(buf+i*0x200,&(s->first_sectors[sector_num*0x200]),0x200);
1404 else if(sector_num-s->first_sectors_number<s->sectors_per_fat)
1405 memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number)*0x200]),0x200);
1406 else if(sector_num-s->first_sectors_number-s->sectors_per_fat<s->sectors_per_fat)
1407 memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number-s->sectors_per_fat)*0x200]),0x200);
1408 } else {
1409 uint32_t sector=sector_num-s->faked_sectors,
1410 sector_offset_in_cluster=(sector%s->sectors_per_cluster),
1411 cluster_num=sector/s->sectors_per_cluster;
1412 if(cluster_num > s->cluster_count || read_cluster(s, cluster_num) != 0) {
1413 /* LATER TODO: strict: return -1; */
1414 memset(buf+i*0x200,0,0x200);
1415 continue;
1417 memcpy(buf+i*0x200,s->cluster+sector_offset_in_cluster*0x200,0x200);
1420 return 0;
1423 static int coroutine_fn
1424 vvfat_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
1425 QEMUIOVector *qiov, int flags)
1427 int ret;
1428 BDRVVVFATState *s = bs->opaque;
1429 uint64_t sector_num = offset >> BDRV_SECTOR_BITS;
1430 int nb_sectors = bytes >> BDRV_SECTOR_BITS;
1431 void *buf;
1433 assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
1434 assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
1436 buf = g_try_malloc(bytes);
1437 if (bytes && buf == NULL) {
1438 return -ENOMEM;
1441 qemu_co_mutex_lock(&s->lock);
1442 ret = vvfat_read(bs, sector_num, buf, nb_sectors);
1443 qemu_co_mutex_unlock(&s->lock);
1445 qemu_iovec_from_buf(qiov, 0, buf, bytes);
1446 g_free(buf);
1448 return ret;
1451 /* LATER TODO: statify all functions */
1454 * Idea of the write support (use snapshot):
1456 * 1. check if all data is consistent, recording renames, modifications,
1457 * new files and directories (in s->commits).
1459 * 2. if the data is not consistent, stop committing
1461 * 3. handle renames, and create new files and directories (do not yet
1462 * write their contents)
1464 * 4. walk the directories, fixing the mapping and direntries, and marking
1465 * the handled mappings as not deleted
1467 * 5. commit the contents of the files
1469 * 6. handle deleted files and directories
1473 typedef struct commit_t {
1474 char* path;
1475 union {
1476 struct { uint32_t cluster; } rename;
1477 struct { int dir_index; uint32_t modified_offset; } writeout;
1478 struct { uint32_t first_cluster; } new_file;
1479 struct { uint32_t cluster; } mkdir;
1480 } param;
1481 /* DELETEs and RMDIRs are handled differently: see handle_deletes() */
1482 enum {
1483 ACTION_RENAME, ACTION_WRITEOUT, ACTION_NEW_FILE, ACTION_MKDIR
1484 } action;
1485 } commit_t;
1487 static void clear_commits(BDRVVVFATState* s)
1489 int i;
1490 DLOG(fprintf(stderr, "clear_commits (%d commits)\n", s->commits.next));
1491 for (i = 0; i < s->commits.next; i++) {
1492 commit_t* commit = array_get(&(s->commits), i);
1493 assert(commit->path || commit->action == ACTION_WRITEOUT);
1494 if (commit->action != ACTION_WRITEOUT) {
1495 assert(commit->path);
1496 g_free(commit->path);
1497 } else
1498 assert(commit->path == NULL);
1500 s->commits.next = 0;
1503 static void schedule_rename(BDRVVVFATState* s,
1504 uint32_t cluster, char* new_path)
1506 commit_t* commit = array_get_next(&(s->commits));
1507 commit->path = new_path;
1508 commit->param.rename.cluster = cluster;
1509 commit->action = ACTION_RENAME;
1512 static void schedule_writeout(BDRVVVFATState* s,
1513 int dir_index, uint32_t modified_offset)
1515 commit_t* commit = array_get_next(&(s->commits));
1516 commit->path = NULL;
1517 commit->param.writeout.dir_index = dir_index;
1518 commit->param.writeout.modified_offset = modified_offset;
1519 commit->action = ACTION_WRITEOUT;
1522 static void schedule_new_file(BDRVVVFATState* s,
1523 char* path, uint32_t first_cluster)
1525 commit_t* commit = array_get_next(&(s->commits));
1526 commit->path = path;
1527 commit->param.new_file.first_cluster = first_cluster;
1528 commit->action = ACTION_NEW_FILE;
1531 static void schedule_mkdir(BDRVVVFATState* s, uint32_t cluster, char* path)
1533 commit_t* commit = array_get_next(&(s->commits));
1534 commit->path = path;
1535 commit->param.mkdir.cluster = cluster;
1536 commit->action = ACTION_MKDIR;
1539 typedef struct {
1541 * Since the sequence number is at most 0x3f, and the filename
1542 * length is at most 13 times the sequence number, the maximal
1543 * filename length is 0x3f * 13 bytes.
1545 unsigned char name[0x3f * 13 + 1];
1546 int checksum, len;
1547 int sequence_number;
1548 } long_file_name;
1550 static void lfn_init(long_file_name* lfn)
1552 lfn->sequence_number = lfn->len = 0;
1553 lfn->checksum = 0x100;
1556 /* return 0 if parsed successfully, > 0 if no long name, < 0 if error */
1557 static int parse_long_name(long_file_name* lfn,
1558 const direntry_t* direntry)
1560 int i, j, offset;
1561 const unsigned char* pointer = (const unsigned char*)direntry;
1563 if (!is_long_name(direntry))
1564 return 1;
1566 if (pointer[0] & 0x40) {
1567 lfn->sequence_number = pointer[0] & 0x3f;
1568 lfn->checksum = pointer[13];
1569 lfn->name[0] = 0;
1570 lfn->name[lfn->sequence_number * 13] = 0;
1571 } else if ((pointer[0] & 0x3f) != --lfn->sequence_number)
1572 return -1;
1573 else if (pointer[13] != lfn->checksum)
1574 return -2;
1575 else if (pointer[12] || pointer[26] || pointer[27])
1576 return -3;
1578 offset = 13 * (lfn->sequence_number - 1);
1579 for (i = 0, j = 1; i < 13; i++, j+=2) {
1580 if (j == 11)
1581 j = 14;
1582 else if (j == 26)
1583 j = 28;
1585 if (pointer[j+1] == 0)
1586 lfn->name[offset + i] = pointer[j];
1587 else if (pointer[j+1] != 0xff || (pointer[0] & 0x40) == 0)
1588 return -4;
1589 else
1590 lfn->name[offset + i] = 0;
1593 if (pointer[0] & 0x40)
1594 lfn->len = offset + strlen((char*)lfn->name + offset);
1596 return 0;
1599 /* returns 0 if successful, >0 if no short_name, and <0 on error */
1600 static int parse_short_name(BDRVVVFATState* s,
1601 long_file_name* lfn, direntry_t* direntry)
1603 int i, j;
1605 if (!is_short_name(direntry))
1606 return 1;
1608 for (j = 7; j >= 0 && direntry->name[j] == ' '; j--);
1609 for (i = 0; i <= j; i++) {
1610 if (direntry->name[i] <= ' ' || direntry->name[i] > 0x7f)
1611 return -1;
1612 else if (s->downcase_short_names)
1613 lfn->name[i] = qemu_tolower(direntry->name[i]);
1614 else
1615 lfn->name[i] = direntry->name[i];
1618 for (j = 2; j >= 0 && direntry->name[8 + j] == ' '; j--) {
1620 if (j >= 0) {
1621 lfn->name[i++] = '.';
1622 lfn->name[i + j + 1] = '\0';
1623 for (;j >= 0; j--) {
1624 uint8_t c = direntry->name[8 + j];
1625 if (c <= ' ' || c > 0x7f) {
1626 return -2;
1627 } else if (s->downcase_short_names) {
1628 lfn->name[i + j] = qemu_tolower(c);
1629 } else {
1630 lfn->name[i + j] = c;
1633 } else
1634 lfn->name[i + j + 1] = '\0';
1636 lfn->len = strlen((char*)lfn->name);
1638 return 0;
1641 static inline uint32_t modified_fat_get(BDRVVVFATState* s,
1642 unsigned int cluster)
1644 if (cluster < s->last_cluster_of_root_directory) {
1645 if (cluster + 1 == s->last_cluster_of_root_directory)
1646 return s->max_fat_value;
1647 else
1648 return cluster + 1;
1651 if (s->fat_type==32) {
1652 uint32_t* entry=((uint32_t*)s->fat2)+cluster;
1653 return le32_to_cpu(*entry);
1654 } else if (s->fat_type==16) {
1655 uint16_t* entry=((uint16_t*)s->fat2)+cluster;
1656 return le16_to_cpu(*entry);
1657 } else {
1658 const uint8_t* x=s->fat2+cluster*3/2;
1659 return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
1663 static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num)
1665 int was_modified = 0;
1666 int i, dummy;
1668 if (s->qcow == NULL)
1669 return 0;
1671 for (i = 0; !was_modified && i < s->sectors_per_cluster; i++)
1672 was_modified = bdrv_is_allocated(s->qcow,
1673 cluster2sector(s, cluster_num) + i, 1, &dummy);
1675 return was_modified;
1678 static const char* get_basename(const char* path)
1680 char* basename = strrchr(path, '/');
1681 if (basename == NULL)
1682 return path;
1683 else
1684 return basename + 1; /* strip '/' */
1688 * The array s->used_clusters holds the states of the clusters. If it is
1689 * part of a file, it has bit 2 set, in case of a directory, bit 1. If it
1690 * was modified, bit 3 is set.
1691 * If any cluster is allocated, but not part of a file or directory, this
1692 * driver refuses to commit.
1694 typedef enum {
1695 USED_DIRECTORY = 1, USED_FILE = 2, USED_ANY = 3, USED_ALLOCATED = 4
1696 } used_t;
1699 * get_cluster_count_for_direntry() not only determines how many clusters
1700 * are occupied by direntry, but also if it was renamed or modified.
1702 * A file is thought to be renamed *only* if there already was a file with
1703 * exactly the same first cluster, but a different name.
1705 * Further, the files/directories handled by this function are
1706 * assumed to be *not* deleted (and *only* those).
1708 static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
1709 direntry_t* direntry, const char* path)
1712 * This is a little bit tricky:
1713 * IF the guest OS just inserts a cluster into the file chain,
1714 * and leaves the rest alone, (i.e. the original file had clusters
1715 * 15 -> 16, but now has 15 -> 32 -> 16), then the following happens:
1717 * - do_commit will write the cluster into the file at the given
1718 * offset, but
1720 * - the cluster which is overwritten should be moved to a later
1721 * position in the file.
1723 * I am not aware that any OS does something as braindead, but this
1724 * situation could happen anyway when not committing for a long time.
1725 * Just to be sure that this does not bite us, detect it, and copy the
1726 * contents of the clusters to-be-overwritten into the qcow.
1728 int copy_it = 0;
1729 int was_modified = 0;
1730 int32_t ret = 0;
1732 uint32_t cluster_num = begin_of_direntry(direntry);
1733 uint32_t offset = 0;
1734 int first_mapping_index = -1;
1735 mapping_t* mapping = NULL;
1736 const char* basename2 = NULL;
1738 vvfat_close_current_file(s);
1740 /* the root directory */
1741 if (cluster_num == 0)
1742 return 0;
1744 /* write support */
1745 if (s->qcow) {
1746 basename2 = get_basename(path);
1748 mapping = find_mapping_for_cluster(s, cluster_num);
1750 if (mapping) {
1751 const char* basename;
1753 assert(mapping->mode & MODE_DELETED);
1754 mapping->mode &= ~MODE_DELETED;
1756 basename = get_basename(mapping->path);
1758 assert(mapping->mode & MODE_NORMAL);
1760 /* rename */
1761 if (strcmp(basename, basename2))
1762 schedule_rename(s, cluster_num, g_strdup(path));
1763 } else if (is_file(direntry))
1764 /* new file */
1765 schedule_new_file(s, g_strdup(path), cluster_num);
1766 else {
1767 abort();
1768 return 0;
1772 while(1) {
1773 if (s->qcow) {
1774 if (!copy_it && cluster_was_modified(s, cluster_num)) {
1775 if (mapping == NULL ||
1776 mapping->begin > cluster_num ||
1777 mapping->end <= cluster_num)
1778 mapping = find_mapping_for_cluster(s, cluster_num);
1781 if (mapping &&
1782 (mapping->mode & MODE_DIRECTORY) == 0) {
1784 /* was modified in qcow */
1785 if (offset != mapping->info.file.offset + s->cluster_size
1786 * (cluster_num - mapping->begin)) {
1787 /* offset of this cluster in file chain has changed */
1788 abort();
1789 copy_it = 1;
1790 } else if (offset == 0) {
1791 const char* basename = get_basename(mapping->path);
1793 if (strcmp(basename, basename2))
1794 copy_it = 1;
1795 first_mapping_index = array_index(&(s->mapping), mapping);
1798 if (mapping->first_mapping_index != first_mapping_index
1799 && mapping->info.file.offset > 0) {
1800 abort();
1801 copy_it = 1;
1804 /* need to write out? */
1805 if (!was_modified && is_file(direntry)) {
1806 was_modified = 1;
1807 schedule_writeout(s, mapping->dir_index, offset);
1812 if (copy_it) {
1813 int i, dummy;
1815 * This is horribly inefficient, but that is okay, since
1816 * it is rarely executed, if at all.
1818 int64_t offset = cluster2sector(s, cluster_num);
1820 vvfat_close_current_file(s);
1821 for (i = 0; i < s->sectors_per_cluster; i++) {
1822 if (!bdrv_is_allocated(s->qcow, offset + i, 1, &dummy)) {
1823 if (vvfat_read(s->bs, offset, s->cluster_buffer, 1)) {
1824 return -1;
1826 if (bdrv_write(s->qcow, offset, s->cluster_buffer, 1)) {
1827 return -2;
1834 ret++;
1835 if (s->used_clusters[cluster_num] & USED_ANY)
1836 return 0;
1837 s->used_clusters[cluster_num] = USED_FILE;
1839 cluster_num = modified_fat_get(s, cluster_num);
1841 if (fat_eof(s, cluster_num))
1842 return ret;
1843 else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
1844 return -1;
1846 offset += s->cluster_size;
1851 * This function looks at the modified data (qcow).
1852 * It returns 0 upon inconsistency or error, and the number of clusters
1853 * used by the directory, its subdirectories and their files.
1855 static int check_directory_consistency(BDRVVVFATState *s,
1856 int cluster_num, const char* path)
1858 int ret = 0;
1859 unsigned char* cluster = g_malloc(s->cluster_size);
1860 direntry_t* direntries = (direntry_t*)cluster;
1861 mapping_t* mapping = find_mapping_for_cluster(s, cluster_num);
1863 long_file_name lfn;
1864 int path_len = strlen(path);
1865 char path2[PATH_MAX + 1];
1867 assert(path_len < PATH_MAX); /* len was tested before! */
1868 pstrcpy(path2, sizeof(path2), path);
1869 path2[path_len] = '/';
1870 path2[path_len + 1] = '\0';
1872 if (mapping) {
1873 const char* basename = get_basename(mapping->path);
1874 const char* basename2 = get_basename(path);
1876 assert(mapping->mode & MODE_DIRECTORY);
1878 assert(mapping->mode & MODE_DELETED);
1879 mapping->mode &= ~MODE_DELETED;
1881 if (strcmp(basename, basename2))
1882 schedule_rename(s, cluster_num, g_strdup(path));
1883 } else
1884 /* new directory */
1885 schedule_mkdir(s, cluster_num, g_strdup(path));
1887 lfn_init(&lfn);
1888 do {
1889 int i;
1890 int subret = 0;
1892 ret++;
1894 if (s->used_clusters[cluster_num] & USED_ANY) {
1895 fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
1896 goto fail;
1898 s->used_clusters[cluster_num] = USED_DIRECTORY;
1900 DLOG(fprintf(stderr, "read cluster %d (sector %d)\n", (int)cluster_num, (int)cluster2sector(s, cluster_num)));
1901 subret = vvfat_read(s->bs, cluster2sector(s, cluster_num), cluster,
1902 s->sectors_per_cluster);
1903 if (subret) {
1904 fprintf(stderr, "Error fetching direntries\n");
1905 fail:
1906 g_free(cluster);
1907 return 0;
1910 for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
1911 int cluster_count = 0;
1913 DLOG(fprintf(stderr, "check direntry %d:\n", i); print_direntry(direntries + i));
1914 if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
1915 is_free(direntries + i))
1916 continue;
1918 subret = parse_long_name(&lfn, direntries + i);
1919 if (subret < 0) {
1920 fprintf(stderr, "Error in long name\n");
1921 goto fail;
1923 if (subret == 0 || is_free(direntries + i))
1924 continue;
1926 if (fat_chksum(direntries+i) != lfn.checksum) {
1927 subret = parse_short_name(s, &lfn, direntries + i);
1928 if (subret < 0) {
1929 fprintf(stderr, "Error in short name (%d)\n", subret);
1930 goto fail;
1932 if (subret > 0 || !strcmp((char*)lfn.name, ".")
1933 || !strcmp((char*)lfn.name, ".."))
1934 continue;
1936 lfn.checksum = 0x100; /* cannot use long name twice */
1938 if (path_len + 1 + lfn.len >= PATH_MAX) {
1939 fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
1940 goto fail;
1942 pstrcpy(path2 + path_len + 1, sizeof(path2) - path_len - 1,
1943 (char*)lfn.name);
1945 if (is_directory(direntries + i)) {
1946 if (begin_of_direntry(direntries + i) == 0) {
1947 DLOG(fprintf(stderr, "invalid begin for directory: %s\n", path2); print_direntry(direntries + i));
1948 goto fail;
1950 cluster_count = check_directory_consistency(s,
1951 begin_of_direntry(direntries + i), path2);
1952 if (cluster_count == 0) {
1953 DLOG(fprintf(stderr, "problem in directory %s:\n", path2); print_direntry(direntries + i));
1954 goto fail;
1956 } else if (is_file(direntries + i)) {
1957 /* check file size with FAT */
1958 cluster_count = get_cluster_count_for_direntry(s, direntries + i, path2);
1959 if (cluster_count !=
1960 DIV_ROUND_UP(le32_to_cpu(direntries[i].size), s->cluster_size)) {
1961 DLOG(fprintf(stderr, "Cluster count mismatch\n"));
1962 goto fail;
1964 } else
1965 abort(); /* cluster_count = 0; */
1967 ret += cluster_count;
1970 cluster_num = modified_fat_get(s, cluster_num);
1971 } while(!fat_eof(s, cluster_num));
1973 g_free(cluster);
1974 return ret;
1977 /* returns 1 on success */
1978 static int is_consistent(BDRVVVFATState* s)
1980 int i, check;
1981 int used_clusters_count = 0;
1983 DLOG(checkpoint());
1985 * - get modified FAT
1986 * - compare the two FATs (TODO)
1987 * - get buffer for marking used clusters
1988 * - recurse direntries from root (using bs->bdrv_read to make
1989 * sure to get the new data)
1990 * - check that the FAT agrees with the size
1991 * - count the number of clusters occupied by this directory and
1992 * its files
1993 * - check that the cumulative used cluster count agrees with the
1994 * FAT
1995 * - if all is fine, return number of used clusters
1997 if (s->fat2 == NULL) {
1998 int size = 0x200 * s->sectors_per_fat;
1999 s->fat2 = g_malloc(size);
2000 memcpy(s->fat2, s->fat.pointer, size);
2002 check = vvfat_read(s->bs,
2003 s->first_sectors_number, s->fat2, s->sectors_per_fat);
2004 if (check) {
2005 fprintf(stderr, "Could not copy fat\n");
2006 return 0;
2008 assert (s->used_clusters);
2009 for (i = 0; i < sector2cluster(s, s->sector_count); i++)
2010 s->used_clusters[i] &= ~USED_ANY;
2012 clear_commits(s);
2014 /* mark every mapped file/directory as deleted.
2015 * (check_directory_consistency() will unmark those still present). */
2016 if (s->qcow)
2017 for (i = 0; i < s->mapping.next; i++) {
2018 mapping_t* mapping = array_get(&(s->mapping), i);
2019 if (mapping->first_mapping_index < 0)
2020 mapping->mode |= MODE_DELETED;
2023 used_clusters_count = check_directory_consistency(s, 0, s->path);
2024 if (used_clusters_count <= 0) {
2025 DLOG(fprintf(stderr, "problem in directory\n"));
2026 return 0;
2029 check = s->last_cluster_of_root_directory;
2030 for (i = check; i < sector2cluster(s, s->sector_count); i++) {
2031 if (modified_fat_get(s, i)) {
2032 if(!s->used_clusters[i]) {
2033 DLOG(fprintf(stderr, "FAT was modified (%d), but cluster is not used?\n", i));
2034 return 0;
2036 check++;
2039 if (s->used_clusters[i] == USED_ALLOCATED) {
2040 /* allocated, but not used... */
2041 DLOG(fprintf(stderr, "unused, modified cluster: %d\n", i));
2042 return 0;
2046 if (check != used_clusters_count)
2047 return 0;
2049 return used_clusters_count;
2052 static inline void adjust_mapping_indices(BDRVVVFATState* s,
2053 int offset, int adjust)
2055 int i;
2057 for (i = 0; i < s->mapping.next; i++) {
2058 mapping_t* mapping = array_get(&(s->mapping), i);
2060 #define ADJUST_MAPPING_INDEX(name) \
2061 if (mapping->name >= offset) \
2062 mapping->name += adjust
2064 ADJUST_MAPPING_INDEX(first_mapping_index);
2065 if (mapping->mode & MODE_DIRECTORY)
2066 ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
2070 /* insert or update mapping */
2071 static mapping_t* insert_mapping(BDRVVVFATState* s,
2072 uint32_t begin, uint32_t end)
2075 * - find mapping where mapping->begin >= begin,
2076 * - if mapping->begin > begin: insert
2077 * - adjust all references to mappings!
2078 * - else: adjust
2079 * - replace name
2081 int index = find_mapping_for_cluster_aux(s, begin, 0, s->mapping.next);
2082 mapping_t* mapping = NULL;
2083 mapping_t* first_mapping = array_get(&(s->mapping), 0);
2085 if (index < s->mapping.next && (mapping = array_get(&(s->mapping), index))
2086 && mapping->begin < begin) {
2087 mapping->end = begin;
2088 index++;
2089 mapping = array_get(&(s->mapping), index);
2091 if (index >= s->mapping.next || mapping->begin > begin) {
2092 mapping = array_insert(&(s->mapping), index, 1);
2093 mapping->path = NULL;
2094 adjust_mapping_indices(s, index, +1);
2097 mapping->begin = begin;
2098 mapping->end = end;
2100 DLOG(mapping_t* next_mapping;
2101 assert(index + 1 >= s->mapping.next ||
2102 ((next_mapping = array_get(&(s->mapping), index + 1)) &&
2103 next_mapping->begin >= end)));
2105 if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
2106 s->current_mapping = array_get(&(s->mapping),
2107 s->current_mapping - first_mapping);
2109 return mapping;
2112 static int remove_mapping(BDRVVVFATState* s, int mapping_index)
2114 mapping_t* mapping = array_get(&(s->mapping), mapping_index);
2115 mapping_t* first_mapping = array_get(&(s->mapping), 0);
2117 /* free mapping */
2118 if (mapping->first_mapping_index < 0) {
2119 g_free(mapping->path);
2122 /* remove from s->mapping */
2123 array_remove(&(s->mapping), mapping_index);
2125 /* adjust all references to mappings */
2126 adjust_mapping_indices(s, mapping_index, -1);
2128 if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
2129 s->current_mapping = array_get(&(s->mapping),
2130 s->current_mapping - first_mapping);
2132 return 0;
2135 static void adjust_dirindices(BDRVVVFATState* s, int offset, int adjust)
2137 int i;
2138 for (i = 0; i < s->mapping.next; i++) {
2139 mapping_t* mapping = array_get(&(s->mapping), i);
2140 if (mapping->dir_index >= offset)
2141 mapping->dir_index += adjust;
2142 if ((mapping->mode & MODE_DIRECTORY) &&
2143 mapping->info.dir.first_dir_index >= offset)
2144 mapping->info.dir.first_dir_index += adjust;
2148 static direntry_t* insert_direntries(BDRVVVFATState* s,
2149 int dir_index, int count)
2152 * make room in s->directory,
2153 * adjust_dirindices
2155 direntry_t* result = array_insert(&(s->directory), dir_index, count);
2156 if (result == NULL)
2157 return NULL;
2158 adjust_dirindices(s, dir_index, count);
2159 return result;
2162 static int remove_direntries(BDRVVVFATState* s, int dir_index, int count)
2164 int ret = array_remove_slice(&(s->directory), dir_index, count);
2165 if (ret)
2166 return ret;
2167 adjust_dirindices(s, dir_index, -count);
2168 return 0;
2172 * Adapt the mappings of the cluster chain starting at first cluster
2173 * (i.e. if a file starts at first_cluster, the chain is followed according
2174 * to the modified fat, and the corresponding entries in s->mapping are
2175 * adjusted)
2177 static int commit_mappings(BDRVVVFATState* s,
2178 uint32_t first_cluster, int dir_index)
2180 mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2181 direntry_t* direntry = array_get(&(s->directory), dir_index);
2182 uint32_t cluster = first_cluster;
2184 vvfat_close_current_file(s);
2186 assert(mapping);
2187 assert(mapping->begin == first_cluster);
2188 mapping->first_mapping_index = -1;
2189 mapping->dir_index = dir_index;
2190 mapping->mode = (dir_index <= 0 || is_directory(direntry)) ?
2191 MODE_DIRECTORY : MODE_NORMAL;
2193 while (!fat_eof(s, cluster)) {
2194 uint32_t c, c1;
2196 for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
2197 c = c1, c1 = modified_fat_get(s, c1));
2199 c++;
2200 if (c > mapping->end) {
2201 int index = array_index(&(s->mapping), mapping);
2202 int i, max_i = s->mapping.next - index;
2203 for (i = 1; i < max_i && mapping[i].begin < c; i++);
2204 while (--i > 0)
2205 remove_mapping(s, index + 1);
2207 assert(mapping == array_get(&(s->mapping), s->mapping.next - 1)
2208 || mapping[1].begin >= c);
2209 mapping->end = c;
2211 if (!fat_eof(s, c1)) {
2212 int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next);
2213 mapping_t* next_mapping = i >= s->mapping.next ? NULL :
2214 array_get(&(s->mapping), i);
2216 if (next_mapping == NULL || next_mapping->begin > c1) {
2217 int i1 = array_index(&(s->mapping), mapping);
2219 next_mapping = insert_mapping(s, c1, c1+1);
2221 if (c1 < c)
2222 i1++;
2223 mapping = array_get(&(s->mapping), i1);
2226 next_mapping->dir_index = mapping->dir_index;
2227 next_mapping->first_mapping_index =
2228 mapping->first_mapping_index < 0 ?
2229 array_index(&(s->mapping), mapping) :
2230 mapping->first_mapping_index;
2231 next_mapping->path = mapping->path;
2232 next_mapping->mode = mapping->mode;
2233 next_mapping->read_only = mapping->read_only;
2234 if (mapping->mode & MODE_DIRECTORY) {
2235 next_mapping->info.dir.parent_mapping_index =
2236 mapping->info.dir.parent_mapping_index;
2237 next_mapping->info.dir.first_dir_index =
2238 mapping->info.dir.first_dir_index +
2239 0x10 * s->sectors_per_cluster *
2240 (mapping->end - mapping->begin);
2241 } else
2242 next_mapping->info.file.offset = mapping->info.file.offset +
2243 mapping->end - mapping->begin;
2245 mapping = next_mapping;
2248 cluster = c1;
2251 return 0;
2254 static int commit_direntries(BDRVVVFATState* s,
2255 int dir_index, int parent_mapping_index)
2257 direntry_t* direntry = array_get(&(s->directory), dir_index);
2258 uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
2259 mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2261 int factor = 0x10 * s->sectors_per_cluster;
2262 int old_cluster_count, new_cluster_count;
2263 int current_dir_index = mapping->info.dir.first_dir_index;
2264 int first_dir_index = current_dir_index;
2265 int ret, i;
2266 uint32_t c;
2268 DLOG(fprintf(stderr, "commit_direntries for %s, parent_mapping_index %d\n", mapping->path, parent_mapping_index));
2270 assert(direntry);
2271 assert(mapping);
2272 assert(mapping->begin == first_cluster);
2273 assert(mapping->info.dir.first_dir_index < s->directory.next);
2274 assert(mapping->mode & MODE_DIRECTORY);
2275 assert(dir_index == 0 || is_directory(direntry));
2277 mapping->info.dir.parent_mapping_index = parent_mapping_index;
2279 if (first_cluster == 0) {
2280 old_cluster_count = new_cluster_count =
2281 s->last_cluster_of_root_directory;
2282 } else {
2283 for (old_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2284 c = fat_get(s, c))
2285 old_cluster_count++;
2287 for (new_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2288 c = modified_fat_get(s, c))
2289 new_cluster_count++;
2292 if (new_cluster_count > old_cluster_count) {
2293 if (insert_direntries(s,
2294 current_dir_index + factor * old_cluster_count,
2295 factor * (new_cluster_count - old_cluster_count)) == NULL)
2296 return -1;
2297 } else if (new_cluster_count < old_cluster_count)
2298 remove_direntries(s,
2299 current_dir_index + factor * new_cluster_count,
2300 factor * (old_cluster_count - new_cluster_count));
2302 for (c = first_cluster; !fat_eof(s, c); c = modified_fat_get(s, c)) {
2303 direntry_t *first_direntry;
2304 void* direntry = array_get(&(s->directory), current_dir_index);
2305 int ret = vvfat_read(s->bs, cluster2sector(s, c), direntry,
2306 s->sectors_per_cluster);
2307 if (ret)
2308 return ret;
2310 /* The first directory entry on the filesystem is the volume name */
2311 first_direntry = (direntry_t*) s->directory.pointer;
2312 assert(!memcmp(first_direntry->name, s->volume_label, 11));
2314 current_dir_index += factor;
2317 ret = commit_mappings(s, first_cluster, dir_index);
2318 if (ret)
2319 return ret;
2321 /* recurse */
2322 for (i = 0; i < factor * new_cluster_count; i++) {
2323 direntry = array_get(&(s->directory), first_dir_index + i);
2324 if (is_directory(direntry) && !is_dot(direntry)) {
2325 mapping = find_mapping_for_cluster(s, first_cluster);
2326 assert(mapping->mode & MODE_DIRECTORY);
2327 ret = commit_direntries(s, first_dir_index + i,
2328 array_index(&(s->mapping), mapping));
2329 if (ret)
2330 return ret;
2334 return 0;
2337 /* commit one file (adjust contents, adjust mapping),
2338 return first_mapping_index */
2339 static int commit_one_file(BDRVVVFATState* s,
2340 int dir_index, uint32_t offset)
2342 direntry_t* direntry = array_get(&(s->directory), dir_index);
2343 uint32_t c = begin_of_direntry(direntry);
2344 uint32_t first_cluster = c;
2345 mapping_t* mapping = find_mapping_for_cluster(s, c);
2346 uint32_t size = filesize_of_direntry(direntry);
2347 char* cluster = g_malloc(s->cluster_size);
2348 uint32_t i;
2349 int fd = 0;
2351 assert(offset < size);
2352 assert((offset % s->cluster_size) == 0);
2354 for (i = s->cluster_size; i < offset; i += s->cluster_size)
2355 c = modified_fat_get(s, c);
2357 fd = qemu_open(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666);
2358 if (fd < 0) {
2359 fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path,
2360 strerror(errno), errno);
2361 g_free(cluster);
2362 return fd;
2364 if (offset > 0) {
2365 if (lseek(fd, offset, SEEK_SET) != offset) {
2366 qemu_close(fd);
2367 g_free(cluster);
2368 return -3;
2372 while (offset < size) {
2373 uint32_t c1;
2374 int rest_size = (size - offset > s->cluster_size ?
2375 s->cluster_size : size - offset);
2376 int ret;
2378 c1 = modified_fat_get(s, c);
2380 assert((size - offset == 0 && fat_eof(s, c)) ||
2381 (size > offset && c >=2 && !fat_eof(s, c)));
2383 ret = vvfat_read(s->bs, cluster2sector(s, c),
2384 (uint8_t*)cluster, (rest_size + 0x1ff) / 0x200);
2386 if (ret < 0) {
2387 qemu_close(fd);
2388 g_free(cluster);
2389 return ret;
2392 if (write(fd, cluster, rest_size) < 0) {
2393 qemu_close(fd);
2394 g_free(cluster);
2395 return -2;
2398 offset += rest_size;
2399 c = c1;
2402 if (ftruncate(fd, size)) {
2403 perror("ftruncate()");
2404 qemu_close(fd);
2405 g_free(cluster);
2406 return -4;
2408 qemu_close(fd);
2409 g_free(cluster);
2411 return commit_mappings(s, first_cluster, dir_index);
2414 #ifdef DEBUG
2415 /* test, if all mappings point to valid direntries */
2416 static void check1(BDRVVVFATState* s)
2418 int i;
2419 for (i = 0; i < s->mapping.next; i++) {
2420 mapping_t* mapping = array_get(&(s->mapping), i);
2421 if (mapping->mode & MODE_DELETED) {
2422 fprintf(stderr, "deleted\n");
2423 continue;
2425 assert(mapping->dir_index < s->directory.next);
2426 direntry_t* direntry = array_get(&(s->directory), mapping->dir_index);
2427 assert(mapping->begin == begin_of_direntry(direntry) || mapping->first_mapping_index >= 0);
2428 if (mapping->mode & MODE_DIRECTORY) {
2429 assert(mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster * (mapping->end - mapping->begin) <= s->directory.next);
2430 assert((mapping->info.dir.first_dir_index % (0x10 * s->sectors_per_cluster)) == 0);
2435 /* test, if all direntries have mappings */
2436 static void check2(BDRVVVFATState* s)
2438 int i;
2439 int first_mapping = -1;
2441 for (i = 0; i < s->directory.next; i++) {
2442 direntry_t* direntry = array_get(&(s->directory), i);
2444 if (is_short_name(direntry) && begin_of_direntry(direntry)) {
2445 mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
2446 assert(mapping);
2447 assert(mapping->dir_index == i || is_dot(direntry));
2448 assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry));
2451 if ((i % (0x10 * s->sectors_per_cluster)) == 0) {
2452 /* cluster start */
2453 int j, count = 0;
2455 for (j = 0; j < s->mapping.next; j++) {
2456 mapping_t* mapping = array_get(&(s->mapping), j);
2457 if (mapping->mode & MODE_DELETED)
2458 continue;
2459 if (mapping->mode & MODE_DIRECTORY) {
2460 if (mapping->info.dir.first_dir_index <= i && mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster > i) {
2461 assert(++count == 1);
2462 if (mapping->first_mapping_index == -1)
2463 first_mapping = array_index(&(s->mapping), mapping);
2464 else
2465 assert(first_mapping == mapping->first_mapping_index);
2466 if (mapping->info.dir.parent_mapping_index < 0)
2467 assert(j == 0);
2468 else {
2469 mapping_t* parent = array_get(&(s->mapping), mapping->info.dir.parent_mapping_index);
2470 assert(parent->mode & MODE_DIRECTORY);
2471 assert(parent->info.dir.first_dir_index < mapping->info.dir.first_dir_index);
2476 if (count == 0)
2477 first_mapping = -1;
2481 #endif
2483 static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2485 int i;
2487 #ifdef DEBUG
2488 fprintf(stderr, "handle_renames\n");
2489 for (i = 0; i < s->commits.next; i++) {
2490 commit_t* commit = array_get(&(s->commits), i);
2491 fprintf(stderr, "%d, %s (%d, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action);
2493 #endif
2495 for (i = 0; i < s->commits.next;) {
2496 commit_t* commit = array_get(&(s->commits), i);
2497 if (commit->action == ACTION_RENAME) {
2498 mapping_t* mapping = find_mapping_for_cluster(s,
2499 commit->param.rename.cluster);
2500 char* old_path = mapping->path;
2502 assert(commit->path);
2503 mapping->path = commit->path;
2504 if (rename(old_path, mapping->path))
2505 return -2;
2507 if (mapping->mode & MODE_DIRECTORY) {
2508 int l1 = strlen(mapping->path);
2509 int l2 = strlen(old_path);
2510 int diff = l1 - l2;
2511 direntry_t* direntry = array_get(&(s->directory),
2512 mapping->info.dir.first_dir_index);
2513 uint32_t c = mapping->begin;
2514 int i = 0;
2516 /* recurse */
2517 while (!fat_eof(s, c)) {
2518 do {
2519 direntry_t* d = direntry + i;
2521 if (is_file(d) || (is_directory(d) && !is_dot(d))) {
2522 mapping_t* m = find_mapping_for_cluster(s,
2523 begin_of_direntry(d));
2524 int l = strlen(m->path);
2525 char* new_path = g_malloc(l + diff + 1);
2527 assert(!strncmp(m->path, mapping->path, l2));
2529 pstrcpy(new_path, l + diff + 1, mapping->path);
2530 pstrcpy(new_path + l1, l + diff + 1 - l1,
2531 m->path + l2);
2533 schedule_rename(s, m->begin, new_path);
2535 i++;
2536 } while((i % (0x10 * s->sectors_per_cluster)) != 0);
2537 c = fat_get(s, c);
2541 g_free(old_path);
2542 array_remove(&(s->commits), i);
2543 continue;
2544 } else if (commit->action == ACTION_MKDIR) {
2545 mapping_t* mapping;
2546 int j, parent_path_len;
2548 #ifdef __MINGW32__
2549 if (mkdir(commit->path))
2550 return -5;
2551 #else
2552 if (mkdir(commit->path, 0755))
2553 return -5;
2554 #endif
2556 mapping = insert_mapping(s, commit->param.mkdir.cluster,
2557 commit->param.mkdir.cluster + 1);
2558 if (mapping == NULL)
2559 return -6;
2561 mapping->mode = MODE_DIRECTORY;
2562 mapping->read_only = 0;
2563 mapping->path = commit->path;
2564 j = s->directory.next;
2565 assert(j);
2566 insert_direntries(s, s->directory.next,
2567 0x10 * s->sectors_per_cluster);
2568 mapping->info.dir.first_dir_index = j;
2570 parent_path_len = strlen(commit->path)
2571 - strlen(get_basename(commit->path)) - 1;
2572 for (j = 0; j < s->mapping.next; j++) {
2573 mapping_t* m = array_get(&(s->mapping), j);
2574 if (m->first_mapping_index < 0 && m != mapping &&
2575 !strncmp(m->path, mapping->path, parent_path_len) &&
2576 strlen(m->path) == parent_path_len)
2577 break;
2579 assert(j < s->mapping.next);
2580 mapping->info.dir.parent_mapping_index = j;
2582 array_remove(&(s->commits), i);
2583 continue;
2586 i++;
2588 return 0;
2592 * TODO: make sure that the short name is not matching *another* file
2594 static int handle_commits(BDRVVVFATState* s)
2596 int i, fail = 0;
2598 vvfat_close_current_file(s);
2600 for (i = 0; !fail && i < s->commits.next; i++) {
2601 commit_t* commit = array_get(&(s->commits), i);
2602 switch(commit->action) {
2603 case ACTION_RENAME: case ACTION_MKDIR:
2604 abort();
2605 fail = -2;
2606 break;
2607 case ACTION_WRITEOUT: {
2608 #ifndef NDEBUG
2609 /* these variables are only used by assert() below */
2610 direntry_t* entry = array_get(&(s->directory),
2611 commit->param.writeout.dir_index);
2612 uint32_t begin = begin_of_direntry(entry);
2613 mapping_t* mapping = find_mapping_for_cluster(s, begin);
2614 #endif
2616 assert(mapping);
2617 assert(mapping->begin == begin);
2618 assert(commit->path == NULL);
2620 if (commit_one_file(s, commit->param.writeout.dir_index,
2621 commit->param.writeout.modified_offset))
2622 fail = -3;
2624 break;
2626 case ACTION_NEW_FILE: {
2627 int begin = commit->param.new_file.first_cluster;
2628 mapping_t* mapping = find_mapping_for_cluster(s, begin);
2629 direntry_t* entry;
2630 int i;
2632 /* find direntry */
2633 for (i = 0; i < s->directory.next; i++) {
2634 entry = array_get(&(s->directory), i);
2635 if (is_file(entry) && begin_of_direntry(entry) == begin)
2636 break;
2639 if (i >= s->directory.next) {
2640 fail = -6;
2641 continue;
2644 /* make sure there exists an initial mapping */
2645 if (mapping && mapping->begin != begin) {
2646 mapping->end = begin;
2647 mapping = NULL;
2649 if (mapping == NULL) {
2650 mapping = insert_mapping(s, begin, begin+1);
2652 /* most members will be fixed in commit_mappings() */
2653 assert(commit->path);
2654 mapping->path = commit->path;
2655 mapping->read_only = 0;
2656 mapping->mode = MODE_NORMAL;
2657 mapping->info.file.offset = 0;
2659 if (commit_one_file(s, i, 0))
2660 fail = -7;
2662 break;
2664 default:
2665 abort();
2668 if (i > 0 && array_remove_slice(&(s->commits), 0, i))
2669 return -1;
2670 return fail;
2673 static int handle_deletes(BDRVVVFATState* s)
2675 int i, deferred = 1, deleted = 1;
2677 /* delete files corresponding to mappings marked as deleted */
2678 /* handle DELETEs and unused mappings (modified_fat_get(s, mapping->begin) == 0) */
2679 while (deferred && deleted) {
2680 deferred = 0;
2681 deleted = 0;
2683 for (i = 1; i < s->mapping.next; i++) {
2684 mapping_t* mapping = array_get(&(s->mapping), i);
2685 if (mapping->mode & MODE_DELETED) {
2686 direntry_t* entry = array_get(&(s->directory),
2687 mapping->dir_index);
2689 if (is_free(entry)) {
2690 /* remove file/directory */
2691 if (mapping->mode & MODE_DIRECTORY) {
2692 int j, next_dir_index = s->directory.next,
2693 first_dir_index = mapping->info.dir.first_dir_index;
2695 if (rmdir(mapping->path) < 0) {
2696 if (errno == ENOTEMPTY) {
2697 deferred++;
2698 continue;
2699 } else
2700 return -5;
2703 for (j = 1; j < s->mapping.next; j++) {
2704 mapping_t* m = array_get(&(s->mapping), j);
2705 if (m->mode & MODE_DIRECTORY &&
2706 m->info.dir.first_dir_index >
2707 first_dir_index &&
2708 m->info.dir.first_dir_index <
2709 next_dir_index)
2710 next_dir_index =
2711 m->info.dir.first_dir_index;
2713 remove_direntries(s, first_dir_index,
2714 next_dir_index - first_dir_index);
2716 deleted++;
2718 } else {
2719 if (unlink(mapping->path))
2720 return -4;
2721 deleted++;
2723 DLOG(fprintf(stderr, "DELETE (%d)\n", i); print_mapping(mapping); print_direntry(entry));
2724 remove_mapping(s, i);
2729 return 0;
2733 * synchronize mapping with new state:
2735 * - copy FAT (with bdrv_read)
2736 * - mark all filenames corresponding to mappings as deleted
2737 * - recurse direntries from root (using bs->bdrv_read)
2738 * - delete files corresponding to mappings marked as deleted
2740 static int do_commit(BDRVVVFATState* s)
2742 int ret = 0;
2744 /* the real meat are the commits. Nothing to do? Move along! */
2745 if (s->commits.next == 0)
2746 return 0;
2748 vvfat_close_current_file(s);
2750 ret = handle_renames_and_mkdirs(s);
2751 if (ret) {
2752 fprintf(stderr, "Error handling renames (%d)\n", ret);
2753 abort();
2754 return ret;
2757 /* copy FAT (with bdrv_read) */
2758 memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
2760 /* recurse direntries from root (using bs->bdrv_read) */
2761 ret = commit_direntries(s, 0, -1);
2762 if (ret) {
2763 fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
2764 abort();
2765 return ret;
2768 ret = handle_commits(s);
2769 if (ret) {
2770 fprintf(stderr, "Error handling commits (%d)\n", ret);
2771 abort();
2772 return ret;
2775 ret = handle_deletes(s);
2776 if (ret) {
2777 fprintf(stderr, "Error deleting\n");
2778 abort();
2779 return ret;
2782 if (s->qcow->drv->bdrv_make_empty) {
2783 s->qcow->drv->bdrv_make_empty(s->qcow);
2786 memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
2788 DLOG(checkpoint());
2789 return 0;
2792 static int try_commit(BDRVVVFATState* s)
2794 vvfat_close_current_file(s);
2795 DLOG(checkpoint());
2796 if(!is_consistent(s))
2797 return -1;
2798 return do_commit(s);
2801 static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
2802 const uint8_t *buf, int nb_sectors)
2804 BDRVVVFATState *s = bs->opaque;
2805 int i, ret;
2807 DLOG(checkpoint());
2809 /* Check if we're operating in read-only mode */
2810 if (s->qcow == NULL) {
2811 return -EACCES;
2814 vvfat_close_current_file(s);
2817 * Some sanity checks:
2818 * - do not allow writing to the boot sector
2819 * - do not allow to write non-ASCII filenames
2822 if (sector_num < s->first_sectors_number)
2823 return -1;
2825 for (i = sector2cluster(s, sector_num);
2826 i <= sector2cluster(s, sector_num + nb_sectors - 1);) {
2827 mapping_t* mapping = find_mapping_for_cluster(s, i);
2828 if (mapping) {
2829 if (mapping->read_only) {
2830 fprintf(stderr, "Tried to write to write-protected file %s\n",
2831 mapping->path);
2832 return -1;
2835 if (mapping->mode & MODE_DIRECTORY) {
2836 int begin = cluster2sector(s, i);
2837 int end = begin + s->sectors_per_cluster, k;
2838 int dir_index;
2839 const direntry_t* direntries;
2840 long_file_name lfn;
2842 lfn_init(&lfn);
2844 if (begin < sector_num)
2845 begin = sector_num;
2846 if (end > sector_num + nb_sectors)
2847 end = sector_num + nb_sectors;
2848 dir_index = mapping->dir_index +
2849 0x10 * (begin - mapping->begin * s->sectors_per_cluster);
2850 direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
2852 for (k = 0; k < (end - begin) * 0x10; k++) {
2853 /* do not allow non-ASCII filenames */
2854 if (parse_long_name(&lfn, direntries + k) < 0) {
2855 fprintf(stderr, "Warning: non-ASCII filename\n");
2856 return -1;
2858 /* no access to the direntry of a read-only file */
2859 else if (is_short_name(direntries+k) &&
2860 (direntries[k].attributes & 1)) {
2861 if (memcmp(direntries + k,
2862 array_get(&(s->directory), dir_index + k),
2863 sizeof(direntry_t))) {
2864 fprintf(stderr, "Warning: tried to write to write-protected file\n");
2865 return -1;
2870 i = mapping->end;
2871 } else
2872 i++;
2876 * Use qcow backend. Commit later.
2878 DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
2879 ret = bdrv_write(s->qcow, sector_num, buf, nb_sectors);
2880 if (ret < 0) {
2881 fprintf(stderr, "Error writing to qcow backend\n");
2882 return ret;
2885 for (i = sector2cluster(s, sector_num);
2886 i <= sector2cluster(s, sector_num + nb_sectors - 1); i++)
2887 if (i >= 0)
2888 s->used_clusters[i] |= USED_ALLOCATED;
2890 DLOG(checkpoint());
2891 /* TODO: add timeout */
2892 try_commit(s);
2894 DLOG(checkpoint());
2895 return 0;
2898 static int coroutine_fn
2899 vvfat_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
2900 QEMUIOVector *qiov, int flags)
2902 int ret;
2903 BDRVVVFATState *s = bs->opaque;
2904 uint64_t sector_num = offset >> BDRV_SECTOR_BITS;
2905 int nb_sectors = bytes >> BDRV_SECTOR_BITS;
2906 void *buf;
2908 assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
2909 assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
2911 buf = g_try_malloc(bytes);
2912 if (bytes && buf == NULL) {
2913 return -ENOMEM;
2915 qemu_iovec_to_buf(qiov, 0, buf, bytes);
2917 qemu_co_mutex_lock(&s->lock);
2918 ret = vvfat_write(bs, sector_num, buf, nb_sectors);
2919 qemu_co_mutex_unlock(&s->lock);
2921 g_free(buf);
2923 return ret;
2926 static int64_t coroutine_fn vvfat_co_get_block_status(BlockDriverState *bs,
2927 int64_t sector_num, int nb_sectors, int *n, BlockDriverState **file)
2929 BDRVVVFATState* s = bs->opaque;
2930 *n = s->sector_count - sector_num;
2931 if (*n > nb_sectors) {
2932 *n = nb_sectors;
2933 } else if (*n < 0) {
2934 return 0;
2936 return BDRV_BLOCK_DATA;
2939 static int coroutine_fn
2940 write_target_commit(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
2941 QEMUIOVector *qiov, int flags)
2943 BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
2944 return try_commit(s);
2947 static void write_target_close(BlockDriverState *bs) {
2948 BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
2949 bdrv_unref(s->qcow);
2950 g_free(s->qcow_filename);
2953 static BlockDriver vvfat_write_target = {
2954 .format_name = "vvfat_write_target",
2955 .bdrv_co_pwritev = write_target_commit,
2956 .bdrv_close = write_target_close,
2959 static int enable_write_target(BDRVVVFATState *s, Error **errp)
2961 BlockDriver *bdrv_qcow = NULL;
2962 BlockDriverState *backing;
2963 QemuOpts *opts = NULL;
2964 int ret;
2965 int size = sector2cluster(s, s->sector_count);
2966 QDict *options;
2968 s->used_clusters = calloc(size, 1);
2970 array_init(&(s->commits), sizeof(commit_t));
2972 s->qcow_filename = g_malloc(PATH_MAX);
2973 ret = get_tmp_filename(s->qcow_filename, PATH_MAX);
2974 if (ret < 0) {
2975 error_setg_errno(errp, -ret, "can't create temporary file");
2976 goto err;
2979 bdrv_qcow = bdrv_find_format("qcow");
2980 if (!bdrv_qcow) {
2981 error_setg(errp, "Failed to locate qcow driver");
2982 ret = -ENOENT;
2983 goto err;
2986 opts = qemu_opts_create(bdrv_qcow->create_opts, NULL, 0, &error_abort);
2987 qemu_opt_set_number(opts, BLOCK_OPT_SIZE, s->sector_count * 512,
2988 &error_abort);
2989 qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, "fat:", &error_abort);
2991 ret = bdrv_create(bdrv_qcow, s->qcow_filename, opts, errp);
2992 qemu_opts_del(opts);
2993 if (ret < 0) {
2994 goto err;
2997 options = qdict_new();
2998 qdict_put(options, "driver", qstring_from_str("qcow"));
2999 s->qcow = bdrv_open(s->qcow_filename, NULL, options,
3000 BDRV_O_RDWR | BDRV_O_NO_FLUSH, errp);
3001 if (!s->qcow) {
3002 ret = -EINVAL;
3003 goto err;
3006 #ifndef _WIN32
3007 unlink(s->qcow_filename);
3008 #endif
3010 backing = bdrv_new();
3011 bdrv_set_backing_hd(s->bs, backing);
3012 bdrv_unref(backing);
3014 s->bs->backing->bs->drv = &vvfat_write_target;
3015 s->bs->backing->bs->opaque = g_new(void *, 1);
3016 *(void**)s->bs->backing->bs->opaque = s;
3018 return 0;
3020 err:
3021 g_free(s->qcow_filename);
3022 s->qcow_filename = NULL;
3023 return ret;
3026 static void vvfat_close(BlockDriverState *bs)
3028 BDRVVVFATState *s = bs->opaque;
3030 vvfat_close_current_file(s);
3031 array_free(&(s->fat));
3032 array_free(&(s->directory));
3033 array_free(&(s->mapping));
3034 g_free(s->cluster_buffer);
3036 if (s->qcow) {
3037 migrate_del_blocker(s->migration_blocker);
3038 error_free(s->migration_blocker);
3042 static BlockDriver bdrv_vvfat = {
3043 .format_name = "vvfat",
3044 .protocol_name = "fat",
3045 .instance_size = sizeof(BDRVVVFATState),
3047 .bdrv_parse_filename = vvfat_parse_filename,
3048 .bdrv_file_open = vvfat_open,
3049 .bdrv_close = vvfat_close,
3051 .bdrv_co_preadv = vvfat_co_preadv,
3052 .bdrv_co_pwritev = vvfat_co_pwritev,
3053 .bdrv_co_get_block_status = vvfat_co_get_block_status,
3056 static void bdrv_vvfat_init(void)
3058 bdrv_register(&bdrv_vvfat);
3061 block_init(bdrv_vvfat_init);
3063 #ifdef DEBUG
3064 static void checkpoint(void) {
3065 assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2);
3066 check1(vvv);
3067 check2(vvv);
3068 assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY));
3069 #if 0
3070 if (((direntry_t*)vvv->directory.pointer)[1].attributes != 0xf)
3071 fprintf(stderr, "Nonono!\n");
3072 mapping_t* mapping;
3073 direntry_t* direntry;
3074 assert(vvv->mapping.size >= vvv->mapping.item_size * vvv->mapping.next);
3075 assert(vvv->directory.size >= vvv->directory.item_size * vvv->directory.next);
3076 if (vvv->mapping.next<47)
3077 return;
3078 assert((mapping = array_get(&(vvv->mapping), 47)));
3079 assert(mapping->dir_index < vvv->directory.next);
3080 direntry = array_get(&(vvv->directory), mapping->dir_index);
3081 assert(!memcmp(direntry->name, "USB H ", 11) || direntry->name[0]==0);
3082 #endif
3084 #endif