s390x/cpumodel: generate CPU feature group lists
[qemu.git] / block / vvfat.c
blobba2620f3c204cd874e9a4af63e11282816d2eb07
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 char* qcow_filename;
345 BdrvChild* qcow;
346 void* fat2;
347 char* used_clusters;
348 array_t commits;
349 const char* path;
350 int downcase_short_names;
352 Error *migration_blocker;
353 } BDRVVVFATState;
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.
359 static int sector2CHS(mbr_chs_t *chs, int spos, int cyls, int heads, int secs)
361 int head,sector;
362 sector = spos % secs; spos /= secs;
363 head = spos % heads; spos /= heads;
364 if (spos >= cyls) {
365 /* Overflow,
366 it happens if 32bit sector positions are used, while CHS is only 24bit.
367 Windows/Dos is said to take 1023/255/63 as nonrepresentable CHS */
368 chs->head = 0xFF;
369 chs->sector = 0xFF;
370 chs->cylinder = 0xFF;
371 return 1;
373 chs->head = (uint8_t)head;
374 chs->sector = (uint8_t)( (sector+1) | ((spos>>8)<<6) );
375 chs->cylinder = (uint8_t)spos;
376 return 0;
379 static void init_mbr(BDRVVVFATState *s, int cyls, int heads, int secs)
381 /* TODO: if the files mbr.img and bootsect.img exist, use them */
382 mbr_t* real_mbr=(mbr_t*)s->first_sectors;
383 partition_t* partition = &(real_mbr->partition[0]);
384 int lba;
386 memset(s->first_sectors,0,512);
388 /* Win NT Disk Signature */
389 real_mbr->nt_id= cpu_to_le32(0xbe1afdfa);
391 partition->attributes=0x80; /* bootable */
393 /* LBA is used when partition is outside the CHS geometry */
394 lba = sector2CHS(&partition->start_CHS, s->first_sectors_number - 1,
395 cyls, heads, secs);
396 lba |= sector2CHS(&partition->end_CHS, s->bs->total_sectors - 1,
397 cyls, heads, secs);
399 /*LBA partitions are identified only by start/length_sector_long not by CHS*/
400 partition->start_sector_long = cpu_to_le32(s->first_sectors_number - 1);
401 partition->length_sector_long = cpu_to_le32(s->bs->total_sectors
402 - s->first_sectors_number + 1);
404 /* FAT12/FAT16/FAT32 */
405 /* DOS uses different types when partition is LBA,
406 probably to prevent older versions from using CHS on them */
407 partition->fs_type= s->fat_type==12 ? 0x1:
408 s->fat_type==16 ? (lba?0xe:0x06):
409 /*fat_tyoe==32*/ (lba?0xc:0x0b);
411 real_mbr->magic[0]=0x55; real_mbr->magic[1]=0xaa;
414 /* direntry functions */
416 /* dest is assumed to hold 258 bytes, and pads with 0xffff up to next multiple of 26 */
417 static inline int short2long_name(char* dest,const char* src)
419 int i;
420 int len;
421 for(i=0;i<129 && src[i];i++) {
422 dest[2*i]=src[i];
423 dest[2*i+1]=0;
425 len=2*i;
426 dest[2*i]=dest[2*i+1]=0;
427 for(i=2*i+2;(i%26);i++)
428 dest[i]=0xff;
429 return len;
432 static inline direntry_t* create_long_filename(BDRVVVFATState* s,const char* filename)
434 char buffer[258];
435 int length=short2long_name(buffer,filename),
436 number_of_entries=(length+25)/26,i;
437 direntry_t* entry;
439 for(i=0;i<number_of_entries;i++) {
440 entry=array_get_next(&(s->directory));
441 entry->attributes=0xf;
442 entry->reserved[0]=0;
443 entry->begin=0;
444 entry->name[0]=(number_of_entries-i)|(i==0?0x40:0);
446 for(i=0;i<26*number_of_entries;i++) {
447 int offset=(i%26);
448 if(offset<10) offset=1+offset;
449 else if(offset<22) offset=14+offset-10;
450 else offset=28+offset-22;
451 entry=array_get(&(s->directory),s->directory.next-1-(i/26));
452 entry->name[offset]=buffer[i];
454 return array_get(&(s->directory),s->directory.next-number_of_entries);
457 static char is_free(const direntry_t* direntry)
459 return direntry->name[0]==0xe5 || direntry->name[0]==0x00;
462 static char is_volume_label(const direntry_t* direntry)
464 return direntry->attributes == 0x28;
467 static char is_long_name(const direntry_t* direntry)
469 return direntry->attributes == 0xf;
472 static char is_short_name(const direntry_t* direntry)
474 return !is_volume_label(direntry) && !is_long_name(direntry)
475 && !is_free(direntry);
478 static char is_directory(const direntry_t* direntry)
480 return direntry->attributes & 0x10 && direntry->name[0] != 0xe5;
483 static inline char is_dot(const direntry_t* direntry)
485 return is_short_name(direntry) && direntry->name[0] == '.';
488 static char is_file(const direntry_t* direntry)
490 return is_short_name(direntry) && !is_directory(direntry);
493 static inline uint32_t begin_of_direntry(const direntry_t* direntry)
495 return le16_to_cpu(direntry->begin)|(le16_to_cpu(direntry->begin_hi)<<16);
498 static inline uint32_t filesize_of_direntry(const direntry_t* direntry)
500 return le32_to_cpu(direntry->size);
503 static void set_begin_of_direntry(direntry_t* direntry, uint32_t begin)
505 direntry->begin = cpu_to_le16(begin & 0xffff);
506 direntry->begin_hi = cpu_to_le16((begin >> 16) & 0xffff);
509 /* fat functions */
511 static inline uint8_t fat_chksum(const direntry_t* entry)
513 uint8_t chksum=0;
514 int i;
516 for (i = 0; i < ARRAY_SIZE(entry->name); i++) {
517 chksum = (((chksum & 0xfe) >> 1) |
518 ((chksum & 0x01) ? 0x80 : 0)) + entry->name[i];
521 return chksum;
524 /* if return_time==0, this returns the fat_date, else the fat_time */
525 static uint16_t fat_datetime(time_t time,int return_time) {
526 struct tm* t;
527 struct tm t1;
528 t = &t1;
529 localtime_r(&time,t);
530 if(return_time)
531 return cpu_to_le16((t->tm_sec/2)|(t->tm_min<<5)|(t->tm_hour<<11));
532 return cpu_to_le16((t->tm_mday)|((t->tm_mon+1)<<5)|((t->tm_year-80)<<9));
535 static inline void fat_set(BDRVVVFATState* s,unsigned int cluster,uint32_t value)
537 if(s->fat_type==32) {
538 uint32_t* entry=array_get(&(s->fat),cluster);
539 *entry=cpu_to_le32(value);
540 } else if(s->fat_type==16) {
541 uint16_t* entry=array_get(&(s->fat),cluster);
542 *entry=cpu_to_le16(value&0xffff);
543 } else {
544 int offset = (cluster*3/2);
545 unsigned char* p = array_get(&(s->fat), offset);
546 switch (cluster&1) {
547 case 0:
548 p[0] = value&0xff;
549 p[1] = (p[1]&0xf0) | ((value>>8)&0xf);
550 break;
551 case 1:
552 p[0] = (p[0]&0xf) | ((value&0xf)<<4);
553 p[1] = (value>>4);
554 break;
559 static inline uint32_t fat_get(BDRVVVFATState* s,unsigned int cluster)
561 if(s->fat_type==32) {
562 uint32_t* entry=array_get(&(s->fat),cluster);
563 return le32_to_cpu(*entry);
564 } else if(s->fat_type==16) {
565 uint16_t* entry=array_get(&(s->fat),cluster);
566 return le16_to_cpu(*entry);
567 } else {
568 const uint8_t* x=(uint8_t*)(s->fat.pointer)+cluster*3/2;
569 return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
573 static inline int fat_eof(BDRVVVFATState* s,uint32_t fat_entry)
575 if(fat_entry>s->max_fat_value-8)
576 return -1;
577 return 0;
580 static inline void init_fat(BDRVVVFATState* s)
582 if (s->fat_type == 12) {
583 array_init(&(s->fat),1);
584 array_ensure_allocated(&(s->fat),
585 s->sectors_per_fat * 0x200 * 3 / 2 - 1);
586 } else {
587 array_init(&(s->fat),(s->fat_type==32?4:2));
588 array_ensure_allocated(&(s->fat),
589 s->sectors_per_fat * 0x200 / s->fat.item_size - 1);
591 memset(s->fat.pointer,0,s->fat.size);
593 switch(s->fat_type) {
594 case 12: s->max_fat_value=0xfff; break;
595 case 16: s->max_fat_value=0xffff; break;
596 case 32: s->max_fat_value=0x0fffffff; break;
597 default: s->max_fat_value=0; /* error... */
602 /* TODO: in create_short_filename, 0xe5->0x05 is not yet handled! */
603 /* TODO: in parse_short_filename, 0x05->0xe5 is not yet handled! */
604 static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,
605 unsigned int directory_start, const char* filename, int is_dot)
607 int i,j,long_index=s->directory.next;
608 direntry_t* entry = NULL;
609 direntry_t* entry_long = NULL;
611 if(is_dot) {
612 entry=array_get_next(&(s->directory));
613 memset(entry->name, 0x20, sizeof(entry->name));
614 memcpy(entry->name,filename,strlen(filename));
615 return entry;
618 entry_long=create_long_filename(s,filename);
620 i = strlen(filename);
621 for(j = i - 1; j>0 && filename[j]!='.';j--);
622 if (j > 0)
623 i = (j > 8 ? 8 : j);
624 else if (i > 8)
625 i = 8;
627 entry=array_get_next(&(s->directory));
628 memset(entry->name, 0x20, sizeof(entry->name));
629 memcpy(entry->name, filename, i);
631 if (j > 0) {
632 for (i = 0; i < 3 && filename[j + 1 + i]; i++) {
633 entry->name[8 + i] = filename[j + 1 + i];
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';
647 /* mangle duplicates */
648 while(1) {
649 direntry_t* entry1=array_get(&(s->directory),directory_start);
650 int j;
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;
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]='~';
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]++;
676 /* calculate checksum; propagate to long name */
677 if(entry_long) {
678 uint8_t chksum=fat_chksum(entry);
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++;
688 return entry;
692 * Read a directory. (the index of the corresponding mapping must be passed).
694 static int read_directory(BDRVVVFATState* s, int mapping_index)
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;
705 DIR* dir=opendir(dirname);
706 struct dirent* entry;
707 int i;
709 assert(mapping->mode & MODE_DIRECTORY);
711 if(!dir) {
712 mapping->end = mapping->begin;
713 return -1;
716 i = mapping->info.dir.first_dir_index =
717 first_cluster == 0 ? 0 : s->directory.next;
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,"..");
728 if(first_cluster == 0 && (is_dotdot || is_dot))
729 continue;
731 buffer = g_malloc(length);
732 snprintf(buffer,length,"%s/%s",dirname,entry->d_name);
734 if(stat(buffer,&st)<0) {
735 g_free(buffer);
736 continue;
739 /* create directory entry for this file */
740 direntry=create_short_and_long_name(s, i, entry->d_name,
741 is_dot || is_dotdot);
742 direntry->attributes=(S_ISDIR(st.st_mode)?0x10:0x20);
743 direntry->reserved[0]=direntry->reserved[1]=0;
744 direntry->ctime=fat_datetime(st.st_ctime,1);
745 direntry->cdate=fat_datetime(st.st_ctime,0);
746 direntry->adate=fat_datetime(st.st_atime,0);
747 direntry->begin_hi=0;
748 direntry->mtime=fat_datetime(st.st_mtime,1);
749 direntry->mdate=fat_datetime(st.st_mtime,0);
750 if(is_dotdot)
751 set_begin_of_direntry(direntry, first_cluster_of_parent);
752 else if(is_dot)
753 set_begin_of_direntry(direntry, first_cluster);
754 else
755 direntry->begin=0; /* do that later */
756 if (st.st_size > 0x7fffffff) {
757 fprintf(stderr, "File %s is larger than 2GB\n", buffer);
758 g_free(buffer);
759 closedir(dir);
760 return -2;
762 direntry->size=cpu_to_le32(S_ISDIR(st.st_mode)?0:st.st_size);
764 /* create mapping for this file */
765 if(!is_dot && !is_dotdot && (S_ISDIR(st.st_mode) || st.st_size)) {
766 s->current_mapping = array_get_next(&(s->mapping));
767 s->current_mapping->begin=0;
768 s->current_mapping->end=st.st_size;
770 * we get the direntry of the most recent direntry, which
771 * contains the short name and all the relevant information.
773 s->current_mapping->dir_index=s->directory.next-1;
774 s->current_mapping->first_mapping_index = -1;
775 if (S_ISDIR(st.st_mode)) {
776 s->current_mapping->mode = MODE_DIRECTORY;
777 s->current_mapping->info.dir.parent_mapping_index =
778 mapping_index;
779 } else {
780 s->current_mapping->mode = MODE_UNDEFINED;
781 s->current_mapping->info.file.offset = 0;
783 s->current_mapping->path=buffer;
784 s->current_mapping->read_only =
785 (st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0;
786 } else {
787 g_free(buffer);
790 closedir(dir);
792 /* fill with zeroes up to the end of the cluster */
793 while(s->directory.next%(0x10*s->sectors_per_cluster)) {
794 direntry_t* direntry=array_get_next(&(s->directory));
795 memset(direntry,0,sizeof(direntry_t));
798 /* TODO: if there are more entries, bootsector has to be adjusted! */
799 #define ROOT_ENTRIES (0x02 * 0x10 * s->sectors_per_cluster)
800 if (mapping_index == 0 && s->directory.next < ROOT_ENTRIES) {
801 /* root directory */
802 int cur = s->directory.next;
803 array_ensure_allocated(&(s->directory), ROOT_ENTRIES - 1);
804 s->directory.next = ROOT_ENTRIES;
805 memset(array_get(&(s->directory), cur), 0,
806 (ROOT_ENTRIES - cur) * sizeof(direntry_t));
809 /* reget the mapping, since s->mapping was possibly realloc()ed */
810 mapping = array_get(&(s->mapping), mapping_index);
811 first_cluster += (s->directory.next - mapping->info.dir.first_dir_index)
812 * 0x20 / s->cluster_size;
813 mapping->end = first_cluster;
815 direntry = array_get(&(s->directory), mapping->dir_index);
816 set_begin_of_direntry(direntry, mapping->begin);
818 return 0;
821 static inline uint32_t sector2cluster(BDRVVVFATState* s,off_t sector_num)
823 return (sector_num-s->faked_sectors)/s->sectors_per_cluster;
826 static inline off_t cluster2sector(BDRVVVFATState* s, uint32_t cluster_num)
828 return s->faked_sectors + s->sectors_per_cluster * cluster_num;
831 static int init_directories(BDRVVVFATState* s,
832 const char *dirname, int heads, int secs,
833 Error **errp)
835 bootsector_t* bootsector;
836 mapping_t* mapping;
837 unsigned int i;
838 unsigned int cluster;
840 memset(&(s->first_sectors[0]),0,0x40*0x200);
842 s->cluster_size=s->sectors_per_cluster*0x200;
843 s->cluster_buffer=g_malloc(s->cluster_size);
846 * The formula: sc = spf+1+spf*spc*(512*8/fat_type),
847 * where sc is sector_count,
848 * spf is sectors_per_fat,
849 * spc is sectors_per_clusters, and
850 * fat_type = 12, 16 or 32.
852 i = 1+s->sectors_per_cluster*0x200*8/s->fat_type;
853 s->sectors_per_fat=(s->sector_count+i)/i; /* round up */
855 array_init(&(s->mapping),sizeof(mapping_t));
856 array_init(&(s->directory),sizeof(direntry_t));
858 /* add volume label */
860 direntry_t* entry=array_get_next(&(s->directory));
861 entry->attributes=0x28; /* archive | volume label */
862 memcpy(entry->name, s->volume_label, sizeof(entry->name));
865 /* Now build FAT, and write back information into directory */
866 init_fat(s);
868 s->faked_sectors=s->first_sectors_number+s->sectors_per_fat*2;
869 s->cluster_count=sector2cluster(s, s->sector_count);
871 mapping = array_get_next(&(s->mapping));
872 mapping->begin = 0;
873 mapping->dir_index = 0;
874 mapping->info.dir.parent_mapping_index = -1;
875 mapping->first_mapping_index = -1;
876 mapping->path = g_strdup(dirname);
877 i = strlen(mapping->path);
878 if (i > 0 && mapping->path[i - 1] == '/')
879 mapping->path[i - 1] = '\0';
880 mapping->mode = MODE_DIRECTORY;
881 mapping->read_only = 0;
882 s->path = mapping->path;
884 for (i = 0, cluster = 0; i < s->mapping.next; i++) {
885 /* MS-DOS expects the FAT to be 0 for the root directory
886 * (except for the media byte). */
887 /* LATER TODO: still true for FAT32? */
888 int fix_fat = (i != 0);
889 mapping = array_get(&(s->mapping), i);
891 if (mapping->mode & MODE_DIRECTORY) {
892 mapping->begin = cluster;
893 if(read_directory(s, i)) {
894 error_setg(errp, "Could not read directory %s",
895 mapping->path);
896 return -1;
898 mapping = array_get(&(s->mapping), i);
899 } else {
900 assert(mapping->mode == MODE_UNDEFINED);
901 mapping->mode=MODE_NORMAL;
902 mapping->begin = cluster;
903 if (mapping->end > 0) {
904 direntry_t* direntry = array_get(&(s->directory),
905 mapping->dir_index);
907 mapping->end = cluster + 1 + (mapping->end-1)/s->cluster_size;
908 set_begin_of_direntry(direntry, mapping->begin);
909 } else {
910 mapping->end = cluster + 1;
911 fix_fat = 0;
915 assert(mapping->begin < mapping->end);
917 /* next free cluster */
918 cluster = mapping->end;
920 if(cluster > s->cluster_count) {
921 error_setg(errp,
922 "Directory does not fit in FAT%d (capacity %.2f MB)",
923 s->fat_type, s->sector_count / 2000.0);
924 return -1;
927 /* fix fat for entry */
928 if (fix_fat) {
929 int j;
930 for(j = mapping->begin; j < mapping->end - 1; j++)
931 fat_set(s, j, j+1);
932 fat_set(s, mapping->end - 1, s->max_fat_value);
936 mapping = array_get(&(s->mapping), 0);
937 s->sectors_of_root_directory = mapping->end * s->sectors_per_cluster;
938 s->last_cluster_of_root_directory = mapping->end;
940 /* the FAT signature */
941 fat_set(s,0,s->max_fat_value);
942 fat_set(s,1,s->max_fat_value);
944 s->current_mapping = NULL;
946 bootsector=(bootsector_t*)(s->first_sectors+(s->first_sectors_number-1)*0x200);
947 bootsector->jump[0]=0xeb;
948 bootsector->jump[1]=0x3e;
949 bootsector->jump[2]=0x90;
950 memcpy(bootsector->name,"QEMU ",8);
951 bootsector->sector_size=cpu_to_le16(0x200);
952 bootsector->sectors_per_cluster=s->sectors_per_cluster;
953 bootsector->reserved_sectors=cpu_to_le16(1);
954 bootsector->number_of_fats=0x2; /* number of FATs */
955 bootsector->root_entries=cpu_to_le16(s->sectors_of_root_directory*0x10);
956 bootsector->total_sectors16=s->sector_count>0xffff?0:cpu_to_le16(s->sector_count);
957 bootsector->media_type=(s->first_sectors_number>1?0xf8:0xf0); /* media descriptor (f8=hd, f0=3.5 fd)*/
958 s->fat.pointer[0] = bootsector->media_type;
959 bootsector->sectors_per_fat=cpu_to_le16(s->sectors_per_fat);
960 bootsector->sectors_per_track = cpu_to_le16(secs);
961 bootsector->number_of_heads = cpu_to_le16(heads);
962 bootsector->hidden_sectors=cpu_to_le32(s->first_sectors_number==1?0:0x3f);
963 bootsector->total_sectors=cpu_to_le32(s->sector_count>0xffff?s->sector_count:0);
965 /* LATER TODO: if FAT32, this is wrong */
966 bootsector->u.fat16.drive_number=s->first_sectors_number==1?0:0x80; /* fda=0, hda=0x80 */
967 bootsector->u.fat16.current_head=0;
968 bootsector->u.fat16.signature=0x29;
969 bootsector->u.fat16.id=cpu_to_le32(0xfabe1afd);
971 memcpy(bootsector->u.fat16.volume_label, s->volume_label,
972 sizeof(bootsector->u.fat16.volume_label));
973 memcpy(bootsector->fat_type,(s->fat_type==12?"FAT12 ":s->fat_type==16?"FAT16 ":"FAT32 "),8);
974 bootsector->magic[0]=0x55; bootsector->magic[1]=0xaa;
976 return 0;
979 #ifdef DEBUG
980 static BDRVVVFATState *vvv = NULL;
981 #endif
983 static int enable_write_target(BlockDriverState *bs, Error **errp);
984 static int is_consistent(BDRVVVFATState *s);
986 static QemuOptsList runtime_opts = {
987 .name = "vvfat",
988 .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
989 .desc = {
991 .name = "dir",
992 .type = QEMU_OPT_STRING,
993 .help = "Host directory to map to the vvfat device",
996 .name = "fat-type",
997 .type = QEMU_OPT_NUMBER,
998 .help = "FAT type (12, 16 or 32)",
1001 .name = "floppy",
1002 .type = QEMU_OPT_BOOL,
1003 .help = "Create a floppy rather than a hard disk image",
1006 .name = "label",
1007 .type = QEMU_OPT_STRING,
1008 .help = "Use a volume label other than QEMU VVFAT",
1011 .name = "rw",
1012 .type = QEMU_OPT_BOOL,
1013 .help = "Make the image writable",
1015 { /* end of list */ }
1019 static void vvfat_parse_filename(const char *filename, QDict *options,
1020 Error **errp)
1022 int fat_type = 0;
1023 bool floppy = false;
1024 bool rw = false;
1025 int i;
1027 if (!strstart(filename, "fat:", NULL)) {
1028 error_setg(errp, "File name string must start with 'fat:'");
1029 return;
1032 /* Parse options */
1033 if (strstr(filename, ":32:")) {
1034 fat_type = 32;
1035 } else if (strstr(filename, ":16:")) {
1036 fat_type = 16;
1037 } else if (strstr(filename, ":12:")) {
1038 fat_type = 12;
1041 if (strstr(filename, ":floppy:")) {
1042 floppy = true;
1045 if (strstr(filename, ":rw:")) {
1046 rw = true;
1049 /* Get the directory name without options */
1050 i = strrchr(filename, ':') - filename;
1051 assert(i >= 3);
1052 if (filename[i - 2] == ':' && qemu_isalpha(filename[i - 1])) {
1053 /* workaround for DOS drive names */
1054 filename += i - 1;
1055 } else {
1056 filename += i + 1;
1059 /* Fill in the options QDict */
1060 qdict_put(options, "dir", qstring_from_str(filename));
1061 qdict_put(options, "fat-type", qint_from_int(fat_type));
1062 qdict_put(options, "floppy", qbool_from_bool(floppy));
1063 qdict_put(options, "rw", qbool_from_bool(rw));
1066 static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
1067 Error **errp)
1069 BDRVVVFATState *s = bs->opaque;
1070 int cyls, heads, secs;
1071 bool floppy;
1072 const char *dirname, *label;
1073 QemuOpts *opts;
1074 Error *local_err = NULL;
1075 int ret;
1077 #ifdef DEBUG
1078 vvv = s;
1079 #endif
1081 opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
1082 qemu_opts_absorb_qdict(opts, options, &local_err);
1083 if (local_err) {
1084 error_propagate(errp, local_err);
1085 ret = -EINVAL;
1086 goto fail;
1089 dirname = qemu_opt_get(opts, "dir");
1090 if (!dirname) {
1091 error_setg(errp, "vvfat block driver requires a 'dir' option");
1092 ret = -EINVAL;
1093 goto fail;
1096 s->fat_type = qemu_opt_get_number(opts, "fat-type", 0);
1097 floppy = qemu_opt_get_bool(opts, "floppy", false);
1099 memset(s->volume_label, ' ', sizeof(s->volume_label));
1100 label = qemu_opt_get(opts, "label");
1101 if (label) {
1102 size_t label_length = strlen(label);
1103 if (label_length > 11) {
1104 error_setg(errp, "vvfat label cannot be longer than 11 bytes");
1105 ret = -EINVAL;
1106 goto fail;
1108 memcpy(s->volume_label, label, label_length);
1109 } else {
1110 memcpy(s->volume_label, "QEMU VVFAT", 10);
1113 if (floppy) {
1114 /* 1.44MB or 2.88MB floppy. 2.88MB can be FAT12 (default) or FAT16. */
1115 if (!s->fat_type) {
1116 s->fat_type = 12;
1117 secs = 36;
1118 s->sectors_per_cluster = 2;
1119 } else {
1120 secs = s->fat_type == 12 ? 18 : 36;
1121 s->sectors_per_cluster = 1;
1123 s->first_sectors_number = 1;
1124 cyls = 80;
1125 heads = 2;
1126 } else {
1127 /* 32MB or 504MB disk*/
1128 if (!s->fat_type) {
1129 s->fat_type = 16;
1131 s->first_sectors_number = 0x40;
1132 cyls = s->fat_type == 12 ? 64 : 1024;
1133 heads = 16;
1134 secs = 63;
1137 switch (s->fat_type) {
1138 case 32:
1139 fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. "
1140 "You are welcome to do so!\n");
1141 break;
1142 case 16:
1143 case 12:
1144 break;
1145 default:
1146 error_setg(errp, "Valid FAT types are only 12, 16 and 32");
1147 ret = -EINVAL;
1148 goto fail;
1152 s->bs = bs;
1154 /* LATER TODO: if FAT32, adjust */
1155 s->sectors_per_cluster=0x10;
1157 s->current_cluster=0xffffffff;
1159 /* read only is the default for safety */
1160 bs->read_only = true;
1161 s->qcow = NULL;
1162 s->qcow_filename = NULL;
1163 s->fat2 = NULL;
1164 s->downcase_short_names = 1;
1166 fprintf(stderr, "vvfat %s chs %d,%d,%d\n",
1167 dirname, cyls, heads, secs);
1169 s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1);
1171 if (qemu_opt_get_bool(opts, "rw", false)) {
1172 ret = enable_write_target(bs, errp);
1173 if (ret < 0) {
1174 goto fail;
1176 bs->read_only = false;
1179 bs->total_sectors = cyls * heads * secs;
1181 if (init_directories(s, dirname, heads, secs, errp)) {
1182 ret = -EIO;
1183 goto fail;
1186 s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
1188 if (s->first_sectors_number == 0x40) {
1189 init_mbr(s, cyls, heads, secs);
1192 // assert(is_consistent(s));
1193 qemu_co_mutex_init(&s->lock);
1195 /* Disable migration when vvfat is used rw */
1196 if (s->qcow) {
1197 error_setg(&s->migration_blocker,
1198 "The vvfat (rw) format used by node '%s' "
1199 "does not support live migration",
1200 bdrv_get_device_or_node_name(bs));
1201 migrate_add_blocker(s->migration_blocker);
1204 ret = 0;
1205 fail:
1206 qemu_opts_del(opts);
1207 return ret;
1210 static void vvfat_refresh_limits(BlockDriverState *bs, Error **errp)
1212 bs->bl.request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O */
1215 static inline void vvfat_close_current_file(BDRVVVFATState *s)
1217 if(s->current_mapping) {
1218 s->current_mapping = NULL;
1219 if (s->current_fd) {
1220 qemu_close(s->current_fd);
1221 s->current_fd = 0;
1224 s->current_cluster = -1;
1227 /* mappings between index1 and index2-1 are supposed to be ordered
1228 * return value is the index of the last mapping for which end>cluster_num
1230 static inline int find_mapping_for_cluster_aux(BDRVVVFATState* s,int cluster_num,int index1,int index2)
1232 while(1) {
1233 int index3;
1234 mapping_t* mapping;
1235 index3=(index1+index2)/2;
1236 mapping=array_get(&(s->mapping),index3);
1237 assert(mapping->begin < mapping->end);
1238 if(mapping->begin>=cluster_num) {
1239 assert(index2!=index3 || index2==0);
1240 if(index2==index3)
1241 return index1;
1242 index2=index3;
1243 } else {
1244 if(index1==index3)
1245 return mapping->end<=cluster_num ? index2 : index1;
1246 index1=index3;
1248 assert(index1<=index2);
1249 DLOG(mapping=array_get(&(s->mapping),index1);
1250 assert(mapping->begin<=cluster_num);
1251 assert(index2 >= s->mapping.next ||
1252 ((mapping = array_get(&(s->mapping),index2)) &&
1253 mapping->end>cluster_num)));
1257 static inline mapping_t* find_mapping_for_cluster(BDRVVVFATState* s,int cluster_num)
1259 int index=find_mapping_for_cluster_aux(s,cluster_num,0,s->mapping.next);
1260 mapping_t* mapping;
1261 if(index>=s->mapping.next)
1262 return NULL;
1263 mapping=array_get(&(s->mapping),index);
1264 if(mapping->begin>cluster_num)
1265 return NULL;
1266 assert(mapping->begin<=cluster_num && mapping->end>cluster_num);
1267 return mapping;
1270 static int open_file(BDRVVVFATState* s,mapping_t* mapping)
1272 if(!mapping)
1273 return -1;
1274 if(!s->current_mapping ||
1275 strcmp(s->current_mapping->path,mapping->path)) {
1276 /* open file */
1277 int fd = qemu_open(mapping->path, O_RDONLY | O_BINARY | O_LARGEFILE);
1278 if(fd<0)
1279 return -1;
1280 vvfat_close_current_file(s);
1281 s->current_fd = fd;
1282 s->current_mapping = mapping;
1284 return 0;
1287 static inline int read_cluster(BDRVVVFATState *s,int cluster_num)
1289 if(s->current_cluster != cluster_num) {
1290 int result=0;
1291 off_t offset;
1292 assert(!s->current_mapping || s->current_fd || (s->current_mapping->mode & MODE_DIRECTORY));
1293 if(!s->current_mapping
1294 || s->current_mapping->begin>cluster_num
1295 || s->current_mapping->end<=cluster_num) {
1296 /* binary search of mappings for file */
1297 mapping_t* mapping=find_mapping_for_cluster(s,cluster_num);
1299 assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
1301 if (mapping && mapping->mode & MODE_DIRECTORY) {
1302 vvfat_close_current_file(s);
1303 s->current_mapping = mapping;
1304 read_cluster_directory:
1305 offset = s->cluster_size*(cluster_num-s->current_mapping->begin);
1306 s->cluster = (unsigned char*)s->directory.pointer+offset
1307 + 0x20*s->current_mapping->info.dir.first_dir_index;
1308 assert(((s->cluster-(unsigned char*)s->directory.pointer)%s->cluster_size)==0);
1309 assert((char*)s->cluster+s->cluster_size <= s->directory.pointer+s->directory.next*s->directory.item_size);
1310 s->current_cluster = cluster_num;
1311 return 0;
1314 if(open_file(s,mapping))
1315 return -2;
1316 } else if (s->current_mapping->mode & MODE_DIRECTORY)
1317 goto read_cluster_directory;
1319 assert(s->current_fd);
1321 offset=s->cluster_size*(cluster_num-s->current_mapping->begin)+s->current_mapping->info.file.offset;
1322 if(lseek(s->current_fd, offset, SEEK_SET)!=offset)
1323 return -3;
1324 s->cluster=s->cluster_buffer;
1325 result=read(s->current_fd,s->cluster,s->cluster_size);
1326 if(result<0) {
1327 s->current_cluster = -1;
1328 return -1;
1330 s->current_cluster = cluster_num;
1332 return 0;
1335 #ifdef DEBUG
1336 static void print_direntry(const direntry_t* direntry)
1338 int j = 0;
1339 char buffer[1024];
1341 fprintf(stderr, "direntry %p: ", direntry);
1342 if(!direntry)
1343 return;
1344 if(is_long_name(direntry)) {
1345 unsigned char* c=(unsigned char*)direntry;
1346 int i;
1347 for(i=1;i<11 && c[i] && c[i]!=0xff;i+=2)
1348 #define ADD_CHAR(c) {buffer[j] = (c); if (buffer[j] < ' ') buffer[j] = 0xb0; j++;}
1349 ADD_CHAR(c[i]);
1350 for(i=14;i<26 && c[i] && c[i]!=0xff;i+=2)
1351 ADD_CHAR(c[i]);
1352 for(i=28;i<32 && c[i] && c[i]!=0xff;i+=2)
1353 ADD_CHAR(c[i]);
1354 buffer[j] = 0;
1355 fprintf(stderr, "%s\n", buffer);
1356 } else {
1357 int i;
1358 for(i=0;i<11;i++)
1359 ADD_CHAR(direntry->name[i]);
1360 buffer[j] = 0;
1361 fprintf(stderr,"%s attributes=0x%02x begin=%d size=%d\n",
1362 buffer,
1363 direntry->attributes,
1364 begin_of_direntry(direntry),le32_to_cpu(direntry->size));
1368 static void print_mapping(const mapping_t* mapping)
1370 fprintf(stderr, "mapping (%p): begin, end = %d, %d, dir_index = %d, "
1371 "first_mapping_index = %d, name = %s, mode = 0x%x, " ,
1372 mapping, mapping->begin, mapping->end, mapping->dir_index,
1373 mapping->first_mapping_index, mapping->path, mapping->mode);
1375 if (mapping->mode & MODE_DIRECTORY)
1376 fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
1377 else
1378 fprintf(stderr, "offset = %d\n", mapping->info.file.offset);
1380 #endif
1382 static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
1383 uint8_t *buf, int nb_sectors)
1385 BDRVVVFATState *s = bs->opaque;
1386 int i;
1388 for(i=0;i<nb_sectors;i++,sector_num++) {
1389 if (sector_num >= bs->total_sectors)
1390 return -1;
1391 if (s->qcow) {
1392 int n;
1393 if (bdrv_is_allocated(s->qcow->bs, sector_num, nb_sectors-i, &n)) {
1394 DLOG(fprintf(stderr, "sectors %d+%d allocated\n",
1395 (int)sector_num, n));
1396 if (bdrv_read(s->qcow, sector_num, buf + i * 0x200, n)) {
1397 return -1;
1399 i += n - 1;
1400 sector_num += n - 1;
1401 continue;
1403 DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num));
1405 if(sector_num<s->faked_sectors) {
1406 if(sector_num<s->first_sectors_number)
1407 memcpy(buf+i*0x200,&(s->first_sectors[sector_num*0x200]),0x200);
1408 else if(sector_num-s->first_sectors_number<s->sectors_per_fat)
1409 memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number)*0x200]),0x200);
1410 else if(sector_num-s->first_sectors_number-s->sectors_per_fat<s->sectors_per_fat)
1411 memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number-s->sectors_per_fat)*0x200]),0x200);
1412 } else {
1413 uint32_t sector=sector_num-s->faked_sectors,
1414 sector_offset_in_cluster=(sector%s->sectors_per_cluster),
1415 cluster_num=sector/s->sectors_per_cluster;
1416 if(cluster_num > s->cluster_count || read_cluster(s, cluster_num) != 0) {
1417 /* LATER TODO: strict: return -1; */
1418 memset(buf+i*0x200,0,0x200);
1419 continue;
1421 memcpy(buf+i*0x200,s->cluster+sector_offset_in_cluster*0x200,0x200);
1424 return 0;
1427 static int coroutine_fn
1428 vvfat_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
1429 QEMUIOVector *qiov, int flags)
1431 int ret;
1432 BDRVVVFATState *s = bs->opaque;
1433 uint64_t sector_num = offset >> BDRV_SECTOR_BITS;
1434 int nb_sectors = bytes >> BDRV_SECTOR_BITS;
1435 void *buf;
1437 assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
1438 assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
1440 buf = g_try_malloc(bytes);
1441 if (bytes && buf == NULL) {
1442 return -ENOMEM;
1445 qemu_co_mutex_lock(&s->lock);
1446 ret = vvfat_read(bs, sector_num, buf, nb_sectors);
1447 qemu_co_mutex_unlock(&s->lock);
1449 qemu_iovec_from_buf(qiov, 0, buf, bytes);
1450 g_free(buf);
1452 return ret;
1455 /* LATER TODO: statify all functions */
1458 * Idea of the write support (use snapshot):
1460 * 1. check if all data is consistent, recording renames, modifications,
1461 * new files and directories (in s->commits).
1463 * 2. if the data is not consistent, stop committing
1465 * 3. handle renames, and create new files and directories (do not yet
1466 * write their contents)
1468 * 4. walk the directories, fixing the mapping and direntries, and marking
1469 * the handled mappings as not deleted
1471 * 5. commit the contents of the files
1473 * 6. handle deleted files and directories
1477 typedef struct commit_t {
1478 char* path;
1479 union {
1480 struct { uint32_t cluster; } rename;
1481 struct { int dir_index; uint32_t modified_offset; } writeout;
1482 struct { uint32_t first_cluster; } new_file;
1483 struct { uint32_t cluster; } mkdir;
1484 } param;
1485 /* DELETEs and RMDIRs are handled differently: see handle_deletes() */
1486 enum {
1487 ACTION_RENAME, ACTION_WRITEOUT, ACTION_NEW_FILE, ACTION_MKDIR
1488 } action;
1489 } commit_t;
1491 static void clear_commits(BDRVVVFATState* s)
1493 int i;
1494 DLOG(fprintf(stderr, "clear_commits (%d commits)\n", s->commits.next));
1495 for (i = 0; i < s->commits.next; i++) {
1496 commit_t* commit = array_get(&(s->commits), i);
1497 assert(commit->path || commit->action == ACTION_WRITEOUT);
1498 if (commit->action != ACTION_WRITEOUT) {
1499 assert(commit->path);
1500 g_free(commit->path);
1501 } else
1502 assert(commit->path == NULL);
1504 s->commits.next = 0;
1507 static void schedule_rename(BDRVVVFATState* s,
1508 uint32_t cluster, char* new_path)
1510 commit_t* commit = array_get_next(&(s->commits));
1511 commit->path = new_path;
1512 commit->param.rename.cluster = cluster;
1513 commit->action = ACTION_RENAME;
1516 static void schedule_writeout(BDRVVVFATState* s,
1517 int dir_index, uint32_t modified_offset)
1519 commit_t* commit = array_get_next(&(s->commits));
1520 commit->path = NULL;
1521 commit->param.writeout.dir_index = dir_index;
1522 commit->param.writeout.modified_offset = modified_offset;
1523 commit->action = ACTION_WRITEOUT;
1526 static void schedule_new_file(BDRVVVFATState* s,
1527 char* path, uint32_t first_cluster)
1529 commit_t* commit = array_get_next(&(s->commits));
1530 commit->path = path;
1531 commit->param.new_file.first_cluster = first_cluster;
1532 commit->action = ACTION_NEW_FILE;
1535 static void schedule_mkdir(BDRVVVFATState* s, uint32_t cluster, char* path)
1537 commit_t* commit = array_get_next(&(s->commits));
1538 commit->path = path;
1539 commit->param.mkdir.cluster = cluster;
1540 commit->action = ACTION_MKDIR;
1543 typedef struct {
1545 * Since the sequence number is at most 0x3f, and the filename
1546 * length is at most 13 times the sequence number, the maximal
1547 * filename length is 0x3f * 13 bytes.
1549 unsigned char name[0x3f * 13 + 1];
1550 int checksum, len;
1551 int sequence_number;
1552 } long_file_name;
1554 static void lfn_init(long_file_name* lfn)
1556 lfn->sequence_number = lfn->len = 0;
1557 lfn->checksum = 0x100;
1560 /* return 0 if parsed successfully, > 0 if no long name, < 0 if error */
1561 static int parse_long_name(long_file_name* lfn,
1562 const direntry_t* direntry)
1564 int i, j, offset;
1565 const unsigned char* pointer = (const unsigned char*)direntry;
1567 if (!is_long_name(direntry))
1568 return 1;
1570 if (pointer[0] & 0x40) {
1571 lfn->sequence_number = pointer[0] & 0x3f;
1572 lfn->checksum = pointer[13];
1573 lfn->name[0] = 0;
1574 lfn->name[lfn->sequence_number * 13] = 0;
1575 } else if ((pointer[0] & 0x3f) != --lfn->sequence_number)
1576 return -1;
1577 else if (pointer[13] != lfn->checksum)
1578 return -2;
1579 else if (pointer[12] || pointer[26] || pointer[27])
1580 return -3;
1582 offset = 13 * (lfn->sequence_number - 1);
1583 for (i = 0, j = 1; i < 13; i++, j+=2) {
1584 if (j == 11)
1585 j = 14;
1586 else if (j == 26)
1587 j = 28;
1589 if (pointer[j+1] == 0)
1590 lfn->name[offset + i] = pointer[j];
1591 else if (pointer[j+1] != 0xff || (pointer[0] & 0x40) == 0)
1592 return -4;
1593 else
1594 lfn->name[offset + i] = 0;
1597 if (pointer[0] & 0x40)
1598 lfn->len = offset + strlen((char*)lfn->name + offset);
1600 return 0;
1603 /* returns 0 if successful, >0 if no short_name, and <0 on error */
1604 static int parse_short_name(BDRVVVFATState* s,
1605 long_file_name* lfn, direntry_t* direntry)
1607 int i, j;
1609 if (!is_short_name(direntry))
1610 return 1;
1612 for (j = 7; j >= 0 && direntry->name[j] == ' '; j--);
1613 for (i = 0; i <= j; i++) {
1614 if (direntry->name[i] <= ' ' || direntry->name[i] > 0x7f)
1615 return -1;
1616 else if (s->downcase_short_names)
1617 lfn->name[i] = qemu_tolower(direntry->name[i]);
1618 else
1619 lfn->name[i] = direntry->name[i];
1622 for (j = 2; j >= 0 && direntry->name[8 + j] == ' '; j--) {
1624 if (j >= 0) {
1625 lfn->name[i++] = '.';
1626 lfn->name[i + j + 1] = '\0';
1627 for (;j >= 0; j--) {
1628 uint8_t c = direntry->name[8 + j];
1629 if (c <= ' ' || c > 0x7f) {
1630 return -2;
1631 } else if (s->downcase_short_names) {
1632 lfn->name[i + j] = qemu_tolower(c);
1633 } else {
1634 lfn->name[i + j] = c;
1637 } else
1638 lfn->name[i + j + 1] = '\0';
1640 lfn->len = strlen((char*)lfn->name);
1642 return 0;
1645 static inline uint32_t modified_fat_get(BDRVVVFATState* s,
1646 unsigned int cluster)
1648 if (cluster < s->last_cluster_of_root_directory) {
1649 if (cluster + 1 == s->last_cluster_of_root_directory)
1650 return s->max_fat_value;
1651 else
1652 return cluster + 1;
1655 if (s->fat_type==32) {
1656 uint32_t* entry=((uint32_t*)s->fat2)+cluster;
1657 return le32_to_cpu(*entry);
1658 } else if (s->fat_type==16) {
1659 uint16_t* entry=((uint16_t*)s->fat2)+cluster;
1660 return le16_to_cpu(*entry);
1661 } else {
1662 const uint8_t* x=s->fat2+cluster*3/2;
1663 return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
1667 static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num)
1669 int was_modified = 0;
1670 int i, dummy;
1672 if (s->qcow == NULL) {
1673 return 0;
1676 for (i = 0; !was_modified && i < s->sectors_per_cluster; i++) {
1677 was_modified = bdrv_is_allocated(s->qcow->bs,
1678 cluster2sector(s, cluster_num) + i,
1679 1, &dummy);
1682 return was_modified;
1685 static const char* get_basename(const char* path)
1687 char* basename = strrchr(path, '/');
1688 if (basename == NULL)
1689 return path;
1690 else
1691 return basename + 1; /* strip '/' */
1695 * The array s->used_clusters holds the states of the clusters. If it is
1696 * part of a file, it has bit 2 set, in case of a directory, bit 1. If it
1697 * was modified, bit 3 is set.
1698 * If any cluster is allocated, but not part of a file or directory, this
1699 * driver refuses to commit.
1701 typedef enum {
1702 USED_DIRECTORY = 1, USED_FILE = 2, USED_ANY = 3, USED_ALLOCATED = 4
1703 } used_t;
1706 * get_cluster_count_for_direntry() not only determines how many clusters
1707 * are occupied by direntry, but also if it was renamed or modified.
1709 * A file is thought to be renamed *only* if there already was a file with
1710 * exactly the same first cluster, but a different name.
1712 * Further, the files/directories handled by this function are
1713 * assumed to be *not* deleted (and *only* those).
1715 static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
1716 direntry_t* direntry, const char* path)
1719 * This is a little bit tricky:
1720 * IF the guest OS just inserts a cluster into the file chain,
1721 * and leaves the rest alone, (i.e. the original file had clusters
1722 * 15 -> 16, but now has 15 -> 32 -> 16), then the following happens:
1724 * - do_commit will write the cluster into the file at the given
1725 * offset, but
1727 * - the cluster which is overwritten should be moved to a later
1728 * position in the file.
1730 * I am not aware that any OS does something as braindead, but this
1731 * situation could happen anyway when not committing for a long time.
1732 * Just to be sure that this does not bite us, detect it, and copy the
1733 * contents of the clusters to-be-overwritten into the qcow.
1735 int copy_it = 0;
1736 int was_modified = 0;
1737 int32_t ret = 0;
1739 uint32_t cluster_num = begin_of_direntry(direntry);
1740 uint32_t offset = 0;
1741 int first_mapping_index = -1;
1742 mapping_t* mapping = NULL;
1743 const char* basename2 = NULL;
1745 vvfat_close_current_file(s);
1747 /* the root directory */
1748 if (cluster_num == 0)
1749 return 0;
1751 /* write support */
1752 if (s->qcow) {
1753 basename2 = get_basename(path);
1755 mapping = find_mapping_for_cluster(s, cluster_num);
1757 if (mapping) {
1758 const char* basename;
1760 assert(mapping->mode & MODE_DELETED);
1761 mapping->mode &= ~MODE_DELETED;
1763 basename = get_basename(mapping->path);
1765 assert(mapping->mode & MODE_NORMAL);
1767 /* rename */
1768 if (strcmp(basename, basename2))
1769 schedule_rename(s, cluster_num, g_strdup(path));
1770 } else if (is_file(direntry))
1771 /* new file */
1772 schedule_new_file(s, g_strdup(path), cluster_num);
1773 else {
1774 abort();
1775 return 0;
1779 while(1) {
1780 if (s->qcow) {
1781 if (!copy_it && cluster_was_modified(s, cluster_num)) {
1782 if (mapping == NULL ||
1783 mapping->begin > cluster_num ||
1784 mapping->end <= cluster_num)
1785 mapping = find_mapping_for_cluster(s, cluster_num);
1788 if (mapping &&
1789 (mapping->mode & MODE_DIRECTORY) == 0) {
1791 /* was modified in qcow */
1792 if (offset != mapping->info.file.offset + s->cluster_size
1793 * (cluster_num - mapping->begin)) {
1794 /* offset of this cluster in file chain has changed */
1795 abort();
1796 copy_it = 1;
1797 } else if (offset == 0) {
1798 const char* basename = get_basename(mapping->path);
1800 if (strcmp(basename, basename2))
1801 copy_it = 1;
1802 first_mapping_index = array_index(&(s->mapping), mapping);
1805 if (mapping->first_mapping_index != first_mapping_index
1806 && mapping->info.file.offset > 0) {
1807 abort();
1808 copy_it = 1;
1811 /* need to write out? */
1812 if (!was_modified && is_file(direntry)) {
1813 was_modified = 1;
1814 schedule_writeout(s, mapping->dir_index, offset);
1819 if (copy_it) {
1820 int i, dummy;
1822 * This is horribly inefficient, but that is okay, since
1823 * it is rarely executed, if at all.
1825 int64_t offset = cluster2sector(s, cluster_num);
1827 vvfat_close_current_file(s);
1828 for (i = 0; i < s->sectors_per_cluster; i++) {
1829 int res;
1831 res = bdrv_is_allocated(s->qcow->bs, offset + i, 1, &dummy);
1832 if (!res) {
1833 res = vvfat_read(s->bs, offset, s->cluster_buffer, 1);
1834 if (res) {
1835 return -1;
1837 res = bdrv_write(s->qcow, offset, s->cluster_buffer, 1);
1838 if (res) {
1839 return -2;
1846 ret++;
1847 if (s->used_clusters[cluster_num] & USED_ANY)
1848 return 0;
1849 s->used_clusters[cluster_num] = USED_FILE;
1851 cluster_num = modified_fat_get(s, cluster_num);
1853 if (fat_eof(s, cluster_num))
1854 return ret;
1855 else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
1856 return -1;
1858 offset += s->cluster_size;
1863 * This function looks at the modified data (qcow).
1864 * It returns 0 upon inconsistency or error, and the number of clusters
1865 * used by the directory, its subdirectories and their files.
1867 static int check_directory_consistency(BDRVVVFATState *s,
1868 int cluster_num, const char* path)
1870 int ret = 0;
1871 unsigned char* cluster = g_malloc(s->cluster_size);
1872 direntry_t* direntries = (direntry_t*)cluster;
1873 mapping_t* mapping = find_mapping_for_cluster(s, cluster_num);
1875 long_file_name lfn;
1876 int path_len = strlen(path);
1877 char path2[PATH_MAX + 1];
1879 assert(path_len < PATH_MAX); /* len was tested before! */
1880 pstrcpy(path2, sizeof(path2), path);
1881 path2[path_len] = '/';
1882 path2[path_len + 1] = '\0';
1884 if (mapping) {
1885 const char* basename = get_basename(mapping->path);
1886 const char* basename2 = get_basename(path);
1888 assert(mapping->mode & MODE_DIRECTORY);
1890 assert(mapping->mode & MODE_DELETED);
1891 mapping->mode &= ~MODE_DELETED;
1893 if (strcmp(basename, basename2))
1894 schedule_rename(s, cluster_num, g_strdup(path));
1895 } else
1896 /* new directory */
1897 schedule_mkdir(s, cluster_num, g_strdup(path));
1899 lfn_init(&lfn);
1900 do {
1901 int i;
1902 int subret = 0;
1904 ret++;
1906 if (s->used_clusters[cluster_num] & USED_ANY) {
1907 fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
1908 goto fail;
1910 s->used_clusters[cluster_num] = USED_DIRECTORY;
1912 DLOG(fprintf(stderr, "read cluster %d (sector %d)\n", (int)cluster_num, (int)cluster2sector(s, cluster_num)));
1913 subret = vvfat_read(s->bs, cluster2sector(s, cluster_num), cluster,
1914 s->sectors_per_cluster);
1915 if (subret) {
1916 fprintf(stderr, "Error fetching direntries\n");
1917 fail:
1918 g_free(cluster);
1919 return 0;
1922 for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
1923 int cluster_count = 0;
1925 DLOG(fprintf(stderr, "check direntry %d:\n", i); print_direntry(direntries + i));
1926 if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
1927 is_free(direntries + i))
1928 continue;
1930 subret = parse_long_name(&lfn, direntries + i);
1931 if (subret < 0) {
1932 fprintf(stderr, "Error in long name\n");
1933 goto fail;
1935 if (subret == 0 || is_free(direntries + i))
1936 continue;
1938 if (fat_chksum(direntries+i) != lfn.checksum) {
1939 subret = parse_short_name(s, &lfn, direntries + i);
1940 if (subret < 0) {
1941 fprintf(stderr, "Error in short name (%d)\n", subret);
1942 goto fail;
1944 if (subret > 0 || !strcmp((char*)lfn.name, ".")
1945 || !strcmp((char*)lfn.name, ".."))
1946 continue;
1948 lfn.checksum = 0x100; /* cannot use long name twice */
1950 if (path_len + 1 + lfn.len >= PATH_MAX) {
1951 fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
1952 goto fail;
1954 pstrcpy(path2 + path_len + 1, sizeof(path2) - path_len - 1,
1955 (char*)lfn.name);
1957 if (is_directory(direntries + i)) {
1958 if (begin_of_direntry(direntries + i) == 0) {
1959 DLOG(fprintf(stderr, "invalid begin for directory: %s\n", path2); print_direntry(direntries + i));
1960 goto fail;
1962 cluster_count = check_directory_consistency(s,
1963 begin_of_direntry(direntries + i), path2);
1964 if (cluster_count == 0) {
1965 DLOG(fprintf(stderr, "problem in directory %s:\n", path2); print_direntry(direntries + i));
1966 goto fail;
1968 } else if (is_file(direntries + i)) {
1969 /* check file size with FAT */
1970 cluster_count = get_cluster_count_for_direntry(s, direntries + i, path2);
1971 if (cluster_count !=
1972 DIV_ROUND_UP(le32_to_cpu(direntries[i].size), s->cluster_size)) {
1973 DLOG(fprintf(stderr, "Cluster count mismatch\n"));
1974 goto fail;
1976 } else
1977 abort(); /* cluster_count = 0; */
1979 ret += cluster_count;
1982 cluster_num = modified_fat_get(s, cluster_num);
1983 } while(!fat_eof(s, cluster_num));
1985 g_free(cluster);
1986 return ret;
1989 /* returns 1 on success */
1990 static int is_consistent(BDRVVVFATState* s)
1992 int i, check;
1993 int used_clusters_count = 0;
1995 DLOG(checkpoint());
1997 * - get modified FAT
1998 * - compare the two FATs (TODO)
1999 * - get buffer for marking used clusters
2000 * - recurse direntries from root (using bs->bdrv_read to make
2001 * sure to get the new data)
2002 * - check that the FAT agrees with the size
2003 * - count the number of clusters occupied by this directory and
2004 * its files
2005 * - check that the cumulative used cluster count agrees with the
2006 * FAT
2007 * - if all is fine, return number of used clusters
2009 if (s->fat2 == NULL) {
2010 int size = 0x200 * s->sectors_per_fat;
2011 s->fat2 = g_malloc(size);
2012 memcpy(s->fat2, s->fat.pointer, size);
2014 check = vvfat_read(s->bs,
2015 s->first_sectors_number, s->fat2, s->sectors_per_fat);
2016 if (check) {
2017 fprintf(stderr, "Could not copy fat\n");
2018 return 0;
2020 assert (s->used_clusters);
2021 for (i = 0; i < sector2cluster(s, s->sector_count); i++)
2022 s->used_clusters[i] &= ~USED_ANY;
2024 clear_commits(s);
2026 /* mark every mapped file/directory as deleted.
2027 * (check_directory_consistency() will unmark those still present). */
2028 if (s->qcow)
2029 for (i = 0; i < s->mapping.next; i++) {
2030 mapping_t* mapping = array_get(&(s->mapping), i);
2031 if (mapping->first_mapping_index < 0)
2032 mapping->mode |= MODE_DELETED;
2035 used_clusters_count = check_directory_consistency(s, 0, s->path);
2036 if (used_clusters_count <= 0) {
2037 DLOG(fprintf(stderr, "problem in directory\n"));
2038 return 0;
2041 check = s->last_cluster_of_root_directory;
2042 for (i = check; i < sector2cluster(s, s->sector_count); i++) {
2043 if (modified_fat_get(s, i)) {
2044 if(!s->used_clusters[i]) {
2045 DLOG(fprintf(stderr, "FAT was modified (%d), but cluster is not used?\n", i));
2046 return 0;
2048 check++;
2051 if (s->used_clusters[i] == USED_ALLOCATED) {
2052 /* allocated, but not used... */
2053 DLOG(fprintf(stderr, "unused, modified cluster: %d\n", i));
2054 return 0;
2058 if (check != used_clusters_count)
2059 return 0;
2061 return used_clusters_count;
2064 static inline void adjust_mapping_indices(BDRVVVFATState* s,
2065 int offset, int adjust)
2067 int i;
2069 for (i = 0; i < s->mapping.next; i++) {
2070 mapping_t* mapping = array_get(&(s->mapping), i);
2072 #define ADJUST_MAPPING_INDEX(name) \
2073 if (mapping->name >= offset) \
2074 mapping->name += adjust
2076 ADJUST_MAPPING_INDEX(first_mapping_index);
2077 if (mapping->mode & MODE_DIRECTORY)
2078 ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
2082 /* insert or update mapping */
2083 static mapping_t* insert_mapping(BDRVVVFATState* s,
2084 uint32_t begin, uint32_t end)
2087 * - find mapping where mapping->begin >= begin,
2088 * - if mapping->begin > begin: insert
2089 * - adjust all references to mappings!
2090 * - else: adjust
2091 * - replace name
2093 int index = find_mapping_for_cluster_aux(s, begin, 0, s->mapping.next);
2094 mapping_t* mapping = NULL;
2095 mapping_t* first_mapping = array_get(&(s->mapping), 0);
2097 if (index < s->mapping.next && (mapping = array_get(&(s->mapping), index))
2098 && mapping->begin < begin) {
2099 mapping->end = begin;
2100 index++;
2101 mapping = array_get(&(s->mapping), index);
2103 if (index >= s->mapping.next || mapping->begin > begin) {
2104 mapping = array_insert(&(s->mapping), index, 1);
2105 mapping->path = NULL;
2106 adjust_mapping_indices(s, index, +1);
2109 mapping->begin = begin;
2110 mapping->end = end;
2112 DLOG(mapping_t* next_mapping;
2113 assert(index + 1 >= s->mapping.next ||
2114 ((next_mapping = array_get(&(s->mapping), index + 1)) &&
2115 next_mapping->begin >= end)));
2117 if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
2118 s->current_mapping = array_get(&(s->mapping),
2119 s->current_mapping - first_mapping);
2121 return mapping;
2124 static int remove_mapping(BDRVVVFATState* s, int mapping_index)
2126 mapping_t* mapping = array_get(&(s->mapping), mapping_index);
2127 mapping_t* first_mapping = array_get(&(s->mapping), 0);
2129 /* free mapping */
2130 if (mapping->first_mapping_index < 0) {
2131 g_free(mapping->path);
2134 /* remove from s->mapping */
2135 array_remove(&(s->mapping), mapping_index);
2137 /* adjust all references to mappings */
2138 adjust_mapping_indices(s, mapping_index, -1);
2140 if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
2141 s->current_mapping = array_get(&(s->mapping),
2142 s->current_mapping - first_mapping);
2144 return 0;
2147 static void adjust_dirindices(BDRVVVFATState* s, int offset, int adjust)
2149 int i;
2150 for (i = 0; i < s->mapping.next; i++) {
2151 mapping_t* mapping = array_get(&(s->mapping), i);
2152 if (mapping->dir_index >= offset)
2153 mapping->dir_index += adjust;
2154 if ((mapping->mode & MODE_DIRECTORY) &&
2155 mapping->info.dir.first_dir_index >= offset)
2156 mapping->info.dir.first_dir_index += adjust;
2160 static direntry_t* insert_direntries(BDRVVVFATState* s,
2161 int dir_index, int count)
2164 * make room in s->directory,
2165 * adjust_dirindices
2167 direntry_t* result = array_insert(&(s->directory), dir_index, count);
2168 if (result == NULL)
2169 return NULL;
2170 adjust_dirindices(s, dir_index, count);
2171 return result;
2174 static int remove_direntries(BDRVVVFATState* s, int dir_index, int count)
2176 int ret = array_remove_slice(&(s->directory), dir_index, count);
2177 if (ret)
2178 return ret;
2179 adjust_dirindices(s, dir_index, -count);
2180 return 0;
2184 * Adapt the mappings of the cluster chain starting at first cluster
2185 * (i.e. if a file starts at first_cluster, the chain is followed according
2186 * to the modified fat, and the corresponding entries in s->mapping are
2187 * adjusted)
2189 static int commit_mappings(BDRVVVFATState* s,
2190 uint32_t first_cluster, int dir_index)
2192 mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2193 direntry_t* direntry = array_get(&(s->directory), dir_index);
2194 uint32_t cluster = first_cluster;
2196 vvfat_close_current_file(s);
2198 assert(mapping);
2199 assert(mapping->begin == first_cluster);
2200 mapping->first_mapping_index = -1;
2201 mapping->dir_index = dir_index;
2202 mapping->mode = (dir_index <= 0 || is_directory(direntry)) ?
2203 MODE_DIRECTORY : MODE_NORMAL;
2205 while (!fat_eof(s, cluster)) {
2206 uint32_t c, c1;
2208 for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
2209 c = c1, c1 = modified_fat_get(s, c1));
2211 c++;
2212 if (c > mapping->end) {
2213 int index = array_index(&(s->mapping), mapping);
2214 int i, max_i = s->mapping.next - index;
2215 for (i = 1; i < max_i && mapping[i].begin < c; i++);
2216 while (--i > 0)
2217 remove_mapping(s, index + 1);
2219 assert(mapping == array_get(&(s->mapping), s->mapping.next - 1)
2220 || mapping[1].begin >= c);
2221 mapping->end = c;
2223 if (!fat_eof(s, c1)) {
2224 int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next);
2225 mapping_t* next_mapping = i >= s->mapping.next ? NULL :
2226 array_get(&(s->mapping), i);
2228 if (next_mapping == NULL || next_mapping->begin > c1) {
2229 int i1 = array_index(&(s->mapping), mapping);
2231 next_mapping = insert_mapping(s, c1, c1+1);
2233 if (c1 < c)
2234 i1++;
2235 mapping = array_get(&(s->mapping), i1);
2238 next_mapping->dir_index = mapping->dir_index;
2239 next_mapping->first_mapping_index =
2240 mapping->first_mapping_index < 0 ?
2241 array_index(&(s->mapping), mapping) :
2242 mapping->first_mapping_index;
2243 next_mapping->path = mapping->path;
2244 next_mapping->mode = mapping->mode;
2245 next_mapping->read_only = mapping->read_only;
2246 if (mapping->mode & MODE_DIRECTORY) {
2247 next_mapping->info.dir.parent_mapping_index =
2248 mapping->info.dir.parent_mapping_index;
2249 next_mapping->info.dir.first_dir_index =
2250 mapping->info.dir.first_dir_index +
2251 0x10 * s->sectors_per_cluster *
2252 (mapping->end - mapping->begin);
2253 } else
2254 next_mapping->info.file.offset = mapping->info.file.offset +
2255 mapping->end - mapping->begin;
2257 mapping = next_mapping;
2260 cluster = c1;
2263 return 0;
2266 static int commit_direntries(BDRVVVFATState* s,
2267 int dir_index, int parent_mapping_index)
2269 direntry_t* direntry = array_get(&(s->directory), dir_index);
2270 uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
2271 mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2273 int factor = 0x10 * s->sectors_per_cluster;
2274 int old_cluster_count, new_cluster_count;
2275 int current_dir_index = mapping->info.dir.first_dir_index;
2276 int first_dir_index = current_dir_index;
2277 int ret, i;
2278 uint32_t c;
2280 DLOG(fprintf(stderr, "commit_direntries for %s, parent_mapping_index %d\n", mapping->path, parent_mapping_index));
2282 assert(direntry);
2283 assert(mapping);
2284 assert(mapping->begin == first_cluster);
2285 assert(mapping->info.dir.first_dir_index < s->directory.next);
2286 assert(mapping->mode & MODE_DIRECTORY);
2287 assert(dir_index == 0 || is_directory(direntry));
2289 mapping->info.dir.parent_mapping_index = parent_mapping_index;
2291 if (first_cluster == 0) {
2292 old_cluster_count = new_cluster_count =
2293 s->last_cluster_of_root_directory;
2294 } else {
2295 for (old_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2296 c = fat_get(s, c))
2297 old_cluster_count++;
2299 for (new_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2300 c = modified_fat_get(s, c))
2301 new_cluster_count++;
2304 if (new_cluster_count > old_cluster_count) {
2305 if (insert_direntries(s,
2306 current_dir_index + factor * old_cluster_count,
2307 factor * (new_cluster_count - old_cluster_count)) == NULL)
2308 return -1;
2309 } else if (new_cluster_count < old_cluster_count)
2310 remove_direntries(s,
2311 current_dir_index + factor * new_cluster_count,
2312 factor * (old_cluster_count - new_cluster_count));
2314 for (c = first_cluster; !fat_eof(s, c); c = modified_fat_get(s, c)) {
2315 direntry_t *first_direntry;
2316 void* direntry = array_get(&(s->directory), current_dir_index);
2317 int ret = vvfat_read(s->bs, cluster2sector(s, c), direntry,
2318 s->sectors_per_cluster);
2319 if (ret)
2320 return ret;
2322 /* The first directory entry on the filesystem is the volume name */
2323 first_direntry = (direntry_t*) s->directory.pointer;
2324 assert(!memcmp(first_direntry->name, s->volume_label, 11));
2326 current_dir_index += factor;
2329 ret = commit_mappings(s, first_cluster, dir_index);
2330 if (ret)
2331 return ret;
2333 /* recurse */
2334 for (i = 0; i < factor * new_cluster_count; i++) {
2335 direntry = array_get(&(s->directory), first_dir_index + i);
2336 if (is_directory(direntry) && !is_dot(direntry)) {
2337 mapping = find_mapping_for_cluster(s, first_cluster);
2338 assert(mapping->mode & MODE_DIRECTORY);
2339 ret = commit_direntries(s, first_dir_index + i,
2340 array_index(&(s->mapping), mapping));
2341 if (ret)
2342 return ret;
2346 return 0;
2349 /* commit one file (adjust contents, adjust mapping),
2350 return first_mapping_index */
2351 static int commit_one_file(BDRVVVFATState* s,
2352 int dir_index, uint32_t offset)
2354 direntry_t* direntry = array_get(&(s->directory), dir_index);
2355 uint32_t c = begin_of_direntry(direntry);
2356 uint32_t first_cluster = c;
2357 mapping_t* mapping = find_mapping_for_cluster(s, c);
2358 uint32_t size = filesize_of_direntry(direntry);
2359 char* cluster = g_malloc(s->cluster_size);
2360 uint32_t i;
2361 int fd = 0;
2363 assert(offset < size);
2364 assert((offset % s->cluster_size) == 0);
2366 for (i = s->cluster_size; i < offset; i += s->cluster_size)
2367 c = modified_fat_get(s, c);
2369 fd = qemu_open(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666);
2370 if (fd < 0) {
2371 fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path,
2372 strerror(errno), errno);
2373 g_free(cluster);
2374 return fd;
2376 if (offset > 0) {
2377 if (lseek(fd, offset, SEEK_SET) != offset) {
2378 qemu_close(fd);
2379 g_free(cluster);
2380 return -3;
2384 while (offset < size) {
2385 uint32_t c1;
2386 int rest_size = (size - offset > s->cluster_size ?
2387 s->cluster_size : size - offset);
2388 int ret;
2390 c1 = modified_fat_get(s, c);
2392 assert((size - offset == 0 && fat_eof(s, c)) ||
2393 (size > offset && c >=2 && !fat_eof(s, c)));
2395 ret = vvfat_read(s->bs, cluster2sector(s, c),
2396 (uint8_t*)cluster, (rest_size + 0x1ff) / 0x200);
2398 if (ret < 0) {
2399 qemu_close(fd);
2400 g_free(cluster);
2401 return ret;
2404 if (write(fd, cluster, rest_size) < 0) {
2405 qemu_close(fd);
2406 g_free(cluster);
2407 return -2;
2410 offset += rest_size;
2411 c = c1;
2414 if (ftruncate(fd, size)) {
2415 perror("ftruncate()");
2416 qemu_close(fd);
2417 g_free(cluster);
2418 return -4;
2420 qemu_close(fd);
2421 g_free(cluster);
2423 return commit_mappings(s, first_cluster, dir_index);
2426 #ifdef DEBUG
2427 /* test, if all mappings point to valid direntries */
2428 static void check1(BDRVVVFATState* s)
2430 int i;
2431 for (i = 0; i < s->mapping.next; i++) {
2432 mapping_t* mapping = array_get(&(s->mapping), i);
2433 if (mapping->mode & MODE_DELETED) {
2434 fprintf(stderr, "deleted\n");
2435 continue;
2437 assert(mapping->dir_index < s->directory.next);
2438 direntry_t* direntry = array_get(&(s->directory), mapping->dir_index);
2439 assert(mapping->begin == begin_of_direntry(direntry) || mapping->first_mapping_index >= 0);
2440 if (mapping->mode & MODE_DIRECTORY) {
2441 assert(mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster * (mapping->end - mapping->begin) <= s->directory.next);
2442 assert((mapping->info.dir.first_dir_index % (0x10 * s->sectors_per_cluster)) == 0);
2447 /* test, if all direntries have mappings */
2448 static void check2(BDRVVVFATState* s)
2450 int i;
2451 int first_mapping = -1;
2453 for (i = 0; i < s->directory.next; i++) {
2454 direntry_t* direntry = array_get(&(s->directory), i);
2456 if (is_short_name(direntry) && begin_of_direntry(direntry)) {
2457 mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
2458 assert(mapping);
2459 assert(mapping->dir_index == i || is_dot(direntry));
2460 assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry));
2463 if ((i % (0x10 * s->sectors_per_cluster)) == 0) {
2464 /* cluster start */
2465 int j, count = 0;
2467 for (j = 0; j < s->mapping.next; j++) {
2468 mapping_t* mapping = array_get(&(s->mapping), j);
2469 if (mapping->mode & MODE_DELETED)
2470 continue;
2471 if (mapping->mode & MODE_DIRECTORY) {
2472 if (mapping->info.dir.first_dir_index <= i && mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster > i) {
2473 assert(++count == 1);
2474 if (mapping->first_mapping_index == -1)
2475 first_mapping = array_index(&(s->mapping), mapping);
2476 else
2477 assert(first_mapping == mapping->first_mapping_index);
2478 if (mapping->info.dir.parent_mapping_index < 0)
2479 assert(j == 0);
2480 else {
2481 mapping_t* parent = array_get(&(s->mapping), mapping->info.dir.parent_mapping_index);
2482 assert(parent->mode & MODE_DIRECTORY);
2483 assert(parent->info.dir.first_dir_index < mapping->info.dir.first_dir_index);
2488 if (count == 0)
2489 first_mapping = -1;
2493 #endif
2495 static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2497 int i;
2499 #ifdef DEBUG
2500 fprintf(stderr, "handle_renames\n");
2501 for (i = 0; i < s->commits.next; i++) {
2502 commit_t* commit = array_get(&(s->commits), i);
2503 fprintf(stderr, "%d, %s (%d, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action);
2505 #endif
2507 for (i = 0; i < s->commits.next;) {
2508 commit_t* commit = array_get(&(s->commits), i);
2509 if (commit->action == ACTION_RENAME) {
2510 mapping_t* mapping = find_mapping_for_cluster(s,
2511 commit->param.rename.cluster);
2512 char* old_path = mapping->path;
2514 assert(commit->path);
2515 mapping->path = commit->path;
2516 if (rename(old_path, mapping->path))
2517 return -2;
2519 if (mapping->mode & MODE_DIRECTORY) {
2520 int l1 = strlen(mapping->path);
2521 int l2 = strlen(old_path);
2522 int diff = l1 - l2;
2523 direntry_t* direntry = array_get(&(s->directory),
2524 mapping->info.dir.first_dir_index);
2525 uint32_t c = mapping->begin;
2526 int i = 0;
2528 /* recurse */
2529 while (!fat_eof(s, c)) {
2530 do {
2531 direntry_t* d = direntry + i;
2533 if (is_file(d) || (is_directory(d) && !is_dot(d))) {
2534 mapping_t* m = find_mapping_for_cluster(s,
2535 begin_of_direntry(d));
2536 int l = strlen(m->path);
2537 char* new_path = g_malloc(l + diff + 1);
2539 assert(!strncmp(m->path, mapping->path, l2));
2541 pstrcpy(new_path, l + diff + 1, mapping->path);
2542 pstrcpy(new_path + l1, l + diff + 1 - l1,
2543 m->path + l2);
2545 schedule_rename(s, m->begin, new_path);
2547 i++;
2548 } while((i % (0x10 * s->sectors_per_cluster)) != 0);
2549 c = fat_get(s, c);
2553 g_free(old_path);
2554 array_remove(&(s->commits), i);
2555 continue;
2556 } else if (commit->action == ACTION_MKDIR) {
2557 mapping_t* mapping;
2558 int j, parent_path_len;
2560 #ifdef __MINGW32__
2561 if (mkdir(commit->path))
2562 return -5;
2563 #else
2564 if (mkdir(commit->path, 0755))
2565 return -5;
2566 #endif
2568 mapping = insert_mapping(s, commit->param.mkdir.cluster,
2569 commit->param.mkdir.cluster + 1);
2570 if (mapping == NULL)
2571 return -6;
2573 mapping->mode = MODE_DIRECTORY;
2574 mapping->read_only = 0;
2575 mapping->path = commit->path;
2576 j = s->directory.next;
2577 assert(j);
2578 insert_direntries(s, s->directory.next,
2579 0x10 * s->sectors_per_cluster);
2580 mapping->info.dir.first_dir_index = j;
2582 parent_path_len = strlen(commit->path)
2583 - strlen(get_basename(commit->path)) - 1;
2584 for (j = 0; j < s->mapping.next; j++) {
2585 mapping_t* m = array_get(&(s->mapping), j);
2586 if (m->first_mapping_index < 0 && m != mapping &&
2587 !strncmp(m->path, mapping->path, parent_path_len) &&
2588 strlen(m->path) == parent_path_len)
2589 break;
2591 assert(j < s->mapping.next);
2592 mapping->info.dir.parent_mapping_index = j;
2594 array_remove(&(s->commits), i);
2595 continue;
2598 i++;
2600 return 0;
2604 * TODO: make sure that the short name is not matching *another* file
2606 static int handle_commits(BDRVVVFATState* s)
2608 int i, fail = 0;
2610 vvfat_close_current_file(s);
2612 for (i = 0; !fail && i < s->commits.next; i++) {
2613 commit_t* commit = array_get(&(s->commits), i);
2614 switch(commit->action) {
2615 case ACTION_RENAME: case ACTION_MKDIR:
2616 abort();
2617 fail = -2;
2618 break;
2619 case ACTION_WRITEOUT: {
2620 #ifndef NDEBUG
2621 /* these variables are only used by assert() below */
2622 direntry_t* entry = array_get(&(s->directory),
2623 commit->param.writeout.dir_index);
2624 uint32_t begin = begin_of_direntry(entry);
2625 mapping_t* mapping = find_mapping_for_cluster(s, begin);
2626 #endif
2628 assert(mapping);
2629 assert(mapping->begin == begin);
2630 assert(commit->path == NULL);
2632 if (commit_one_file(s, commit->param.writeout.dir_index,
2633 commit->param.writeout.modified_offset))
2634 fail = -3;
2636 break;
2638 case ACTION_NEW_FILE: {
2639 int begin = commit->param.new_file.first_cluster;
2640 mapping_t* mapping = find_mapping_for_cluster(s, begin);
2641 direntry_t* entry;
2642 int i;
2644 /* find direntry */
2645 for (i = 0; i < s->directory.next; i++) {
2646 entry = array_get(&(s->directory), i);
2647 if (is_file(entry) && begin_of_direntry(entry) == begin)
2648 break;
2651 if (i >= s->directory.next) {
2652 fail = -6;
2653 continue;
2656 /* make sure there exists an initial mapping */
2657 if (mapping && mapping->begin != begin) {
2658 mapping->end = begin;
2659 mapping = NULL;
2661 if (mapping == NULL) {
2662 mapping = insert_mapping(s, begin, begin+1);
2664 /* most members will be fixed in commit_mappings() */
2665 assert(commit->path);
2666 mapping->path = commit->path;
2667 mapping->read_only = 0;
2668 mapping->mode = MODE_NORMAL;
2669 mapping->info.file.offset = 0;
2671 if (commit_one_file(s, i, 0))
2672 fail = -7;
2674 break;
2676 default:
2677 abort();
2680 if (i > 0 && array_remove_slice(&(s->commits), 0, i))
2681 return -1;
2682 return fail;
2685 static int handle_deletes(BDRVVVFATState* s)
2687 int i, deferred = 1, deleted = 1;
2689 /* delete files corresponding to mappings marked as deleted */
2690 /* handle DELETEs and unused mappings (modified_fat_get(s, mapping->begin) == 0) */
2691 while (deferred && deleted) {
2692 deferred = 0;
2693 deleted = 0;
2695 for (i = 1; i < s->mapping.next; i++) {
2696 mapping_t* mapping = array_get(&(s->mapping), i);
2697 if (mapping->mode & MODE_DELETED) {
2698 direntry_t* entry = array_get(&(s->directory),
2699 mapping->dir_index);
2701 if (is_free(entry)) {
2702 /* remove file/directory */
2703 if (mapping->mode & MODE_DIRECTORY) {
2704 int j, next_dir_index = s->directory.next,
2705 first_dir_index = mapping->info.dir.first_dir_index;
2707 if (rmdir(mapping->path) < 0) {
2708 if (errno == ENOTEMPTY) {
2709 deferred++;
2710 continue;
2711 } else
2712 return -5;
2715 for (j = 1; j < s->mapping.next; j++) {
2716 mapping_t* m = array_get(&(s->mapping), j);
2717 if (m->mode & MODE_DIRECTORY &&
2718 m->info.dir.first_dir_index >
2719 first_dir_index &&
2720 m->info.dir.first_dir_index <
2721 next_dir_index)
2722 next_dir_index =
2723 m->info.dir.first_dir_index;
2725 remove_direntries(s, first_dir_index,
2726 next_dir_index - first_dir_index);
2728 deleted++;
2730 } else {
2731 if (unlink(mapping->path))
2732 return -4;
2733 deleted++;
2735 DLOG(fprintf(stderr, "DELETE (%d)\n", i); print_mapping(mapping); print_direntry(entry));
2736 remove_mapping(s, i);
2741 return 0;
2745 * synchronize mapping with new state:
2747 * - copy FAT (with bdrv_read)
2748 * - mark all filenames corresponding to mappings as deleted
2749 * - recurse direntries from root (using bs->bdrv_read)
2750 * - delete files corresponding to mappings marked as deleted
2752 static int do_commit(BDRVVVFATState* s)
2754 int ret = 0;
2756 /* the real meat are the commits. Nothing to do? Move along! */
2757 if (s->commits.next == 0)
2758 return 0;
2760 vvfat_close_current_file(s);
2762 ret = handle_renames_and_mkdirs(s);
2763 if (ret) {
2764 fprintf(stderr, "Error handling renames (%d)\n", ret);
2765 abort();
2766 return ret;
2769 /* copy FAT (with bdrv_read) */
2770 memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
2772 /* recurse direntries from root (using bs->bdrv_read) */
2773 ret = commit_direntries(s, 0, -1);
2774 if (ret) {
2775 fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
2776 abort();
2777 return ret;
2780 ret = handle_commits(s);
2781 if (ret) {
2782 fprintf(stderr, "Error handling commits (%d)\n", ret);
2783 abort();
2784 return ret;
2787 ret = handle_deletes(s);
2788 if (ret) {
2789 fprintf(stderr, "Error deleting\n");
2790 abort();
2791 return ret;
2794 if (s->qcow->bs->drv->bdrv_make_empty) {
2795 s->qcow->bs->drv->bdrv_make_empty(s->qcow->bs);
2798 memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
2800 DLOG(checkpoint());
2801 return 0;
2804 static int try_commit(BDRVVVFATState* s)
2806 vvfat_close_current_file(s);
2807 DLOG(checkpoint());
2808 if(!is_consistent(s))
2809 return -1;
2810 return do_commit(s);
2813 static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
2814 const uint8_t *buf, int nb_sectors)
2816 BDRVVVFATState *s = bs->opaque;
2817 int i, ret;
2819 DLOG(checkpoint());
2821 /* Check if we're operating in read-only mode */
2822 if (s->qcow == NULL) {
2823 return -EACCES;
2826 vvfat_close_current_file(s);
2829 * Some sanity checks:
2830 * - do not allow writing to the boot sector
2831 * - do not allow to write non-ASCII filenames
2834 if (sector_num < s->first_sectors_number)
2835 return -1;
2837 for (i = sector2cluster(s, sector_num);
2838 i <= sector2cluster(s, sector_num + nb_sectors - 1);) {
2839 mapping_t* mapping = find_mapping_for_cluster(s, i);
2840 if (mapping) {
2841 if (mapping->read_only) {
2842 fprintf(stderr, "Tried to write to write-protected file %s\n",
2843 mapping->path);
2844 return -1;
2847 if (mapping->mode & MODE_DIRECTORY) {
2848 int begin = cluster2sector(s, i);
2849 int end = begin + s->sectors_per_cluster, k;
2850 int dir_index;
2851 const direntry_t* direntries;
2852 long_file_name lfn;
2854 lfn_init(&lfn);
2856 if (begin < sector_num)
2857 begin = sector_num;
2858 if (end > sector_num + nb_sectors)
2859 end = sector_num + nb_sectors;
2860 dir_index = mapping->dir_index +
2861 0x10 * (begin - mapping->begin * s->sectors_per_cluster);
2862 direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
2864 for (k = 0; k < (end - begin) * 0x10; k++) {
2865 /* do not allow non-ASCII filenames */
2866 if (parse_long_name(&lfn, direntries + k) < 0) {
2867 fprintf(stderr, "Warning: non-ASCII filename\n");
2868 return -1;
2870 /* no access to the direntry of a read-only file */
2871 else if (is_short_name(direntries+k) &&
2872 (direntries[k].attributes & 1)) {
2873 if (memcmp(direntries + k,
2874 array_get(&(s->directory), dir_index + k),
2875 sizeof(direntry_t))) {
2876 fprintf(stderr, "Warning: tried to write to write-protected file\n");
2877 return -1;
2882 i = mapping->end;
2883 } else
2884 i++;
2888 * Use qcow backend. Commit later.
2890 DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
2891 ret = bdrv_write(s->qcow, sector_num, buf, nb_sectors);
2892 if (ret < 0) {
2893 fprintf(stderr, "Error writing to qcow backend\n");
2894 return ret;
2897 for (i = sector2cluster(s, sector_num);
2898 i <= sector2cluster(s, sector_num + nb_sectors - 1); i++)
2899 if (i >= 0)
2900 s->used_clusters[i] |= USED_ALLOCATED;
2902 DLOG(checkpoint());
2903 /* TODO: add timeout */
2904 try_commit(s);
2906 DLOG(checkpoint());
2907 return 0;
2910 static int coroutine_fn
2911 vvfat_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
2912 QEMUIOVector *qiov, int flags)
2914 int ret;
2915 BDRVVVFATState *s = bs->opaque;
2916 uint64_t sector_num = offset >> BDRV_SECTOR_BITS;
2917 int nb_sectors = bytes >> BDRV_SECTOR_BITS;
2918 void *buf;
2920 assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
2921 assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
2923 buf = g_try_malloc(bytes);
2924 if (bytes && buf == NULL) {
2925 return -ENOMEM;
2927 qemu_iovec_to_buf(qiov, 0, buf, bytes);
2929 qemu_co_mutex_lock(&s->lock);
2930 ret = vvfat_write(bs, sector_num, buf, nb_sectors);
2931 qemu_co_mutex_unlock(&s->lock);
2933 g_free(buf);
2935 return ret;
2938 static int64_t coroutine_fn vvfat_co_get_block_status(BlockDriverState *bs,
2939 int64_t sector_num, int nb_sectors, int *n, BlockDriverState **file)
2941 BDRVVVFATState* s = bs->opaque;
2942 *n = s->sector_count - sector_num;
2943 if (*n > nb_sectors) {
2944 *n = nb_sectors;
2945 } else if (*n < 0) {
2946 return 0;
2948 return BDRV_BLOCK_DATA;
2951 static int coroutine_fn
2952 write_target_commit(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
2953 QEMUIOVector *qiov, int flags)
2955 BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
2956 return try_commit(s);
2959 static void write_target_close(BlockDriverState *bs) {
2960 BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
2961 bdrv_unref_child(s->bs, s->qcow);
2962 g_free(s->qcow_filename);
2965 static BlockDriver vvfat_write_target = {
2966 .format_name = "vvfat_write_target",
2967 .bdrv_co_pwritev = write_target_commit,
2968 .bdrv_close = write_target_close,
2971 static void vvfat_qcow_options(int *child_flags, QDict *child_options,
2972 int parent_flags, QDict *parent_options)
2974 *child_flags = BDRV_O_RDWR | BDRV_O_NO_FLUSH;
2977 static const BdrvChildRole child_vvfat_qcow = {
2978 .inherit_options = vvfat_qcow_options,
2981 static int enable_write_target(BlockDriverState *bs, Error **errp)
2983 BDRVVVFATState *s = bs->opaque;
2984 BlockDriver *bdrv_qcow = NULL;
2985 BlockDriverState *backing;
2986 QemuOpts *opts = NULL;
2987 int ret;
2988 int size = sector2cluster(s, s->sector_count);
2989 QDict *options;
2991 s->used_clusters = calloc(size, 1);
2993 array_init(&(s->commits), sizeof(commit_t));
2995 s->qcow_filename = g_malloc(PATH_MAX);
2996 ret = get_tmp_filename(s->qcow_filename, PATH_MAX);
2997 if (ret < 0) {
2998 error_setg_errno(errp, -ret, "can't create temporary file");
2999 goto err;
3002 bdrv_qcow = bdrv_find_format("qcow");
3003 if (!bdrv_qcow) {
3004 error_setg(errp, "Failed to locate qcow driver");
3005 ret = -ENOENT;
3006 goto err;
3009 opts = qemu_opts_create(bdrv_qcow->create_opts, NULL, 0, &error_abort);
3010 qemu_opt_set_number(opts, BLOCK_OPT_SIZE, s->sector_count * 512,
3011 &error_abort);
3012 qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, "fat:", &error_abort);
3014 ret = bdrv_create(bdrv_qcow, s->qcow_filename, opts, errp);
3015 qemu_opts_del(opts);
3016 if (ret < 0) {
3017 goto err;
3020 options = qdict_new();
3021 qdict_put(options, "write-target.driver", qstring_from_str("qcow"));
3022 s->qcow = bdrv_open_child(s->qcow_filename, options, "write-target", bs,
3023 &child_vvfat_qcow, false, errp);
3024 QDECREF(options);
3025 if (!s->qcow) {
3026 ret = -EINVAL;
3027 goto err;
3030 #ifndef _WIN32
3031 unlink(s->qcow_filename);
3032 #endif
3034 backing = bdrv_new();
3035 bdrv_set_backing_hd(s->bs, backing);
3036 bdrv_unref(backing);
3038 s->bs->backing->bs->drv = &vvfat_write_target;
3039 s->bs->backing->bs->opaque = g_new(void *, 1);
3040 *(void**)s->bs->backing->bs->opaque = s;
3042 return 0;
3044 err:
3045 g_free(s->qcow_filename);
3046 s->qcow_filename = NULL;
3047 return ret;
3050 static void vvfat_close(BlockDriverState *bs)
3052 BDRVVVFATState *s = bs->opaque;
3054 vvfat_close_current_file(s);
3055 array_free(&(s->fat));
3056 array_free(&(s->directory));
3057 array_free(&(s->mapping));
3058 g_free(s->cluster_buffer);
3060 if (s->qcow) {
3061 migrate_del_blocker(s->migration_blocker);
3062 error_free(s->migration_blocker);
3066 static BlockDriver bdrv_vvfat = {
3067 .format_name = "vvfat",
3068 .protocol_name = "fat",
3069 .instance_size = sizeof(BDRVVVFATState),
3071 .bdrv_parse_filename = vvfat_parse_filename,
3072 .bdrv_file_open = vvfat_open,
3073 .bdrv_refresh_limits = vvfat_refresh_limits,
3074 .bdrv_close = vvfat_close,
3076 .bdrv_co_preadv = vvfat_co_preadv,
3077 .bdrv_co_pwritev = vvfat_co_pwritev,
3078 .bdrv_co_get_block_status = vvfat_co_get_block_status,
3081 static void bdrv_vvfat_init(void)
3083 bdrv_register(&bdrv_vvfat);
3086 block_init(bdrv_vvfat_init);
3088 #ifdef DEBUG
3089 static void checkpoint(void) {
3090 assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2);
3091 check1(vvv);
3092 check2(vvv);
3093 assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY));
3094 #if 0
3095 if (((direntry_t*)vvv->directory.pointer)[1].attributes != 0xf)
3096 fprintf(stderr, "Nonono!\n");
3097 mapping_t* mapping;
3098 direntry_t* direntry;
3099 assert(vvv->mapping.size >= vvv->mapping.item_size * vvv->mapping.next);
3100 assert(vvv->directory.size >= vvv->directory.item_size * vvv->directory.next);
3101 if (vvv->mapping.next<47)
3102 return;
3103 assert((mapping = array_get(&(vvv->mapping), 47)));
3104 assert(mapping->dir_index < vvv->directory.next);
3105 direntry = array_get(&(vvv->directory), mapping->dir_index);
3106 assert(!memcmp(direntry->name, "USB H ", 11) || direntry->name[0]==0);
3107 #endif
3109 #endif