1 /* vim:set shiftwidth=4 ts=4: */
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
26 #include "qemu/osdep.h"
28 #include "qapi/error.h"
29 #include "block/block_int.h"
30 #include "block/qdict.h"
31 #include "qemu/module.h"
32 #include "qemu/option.h"
33 #include "qemu/bswap.h"
34 #include "migration/blocker.h"
35 #include "qapi/qmp/qdict.h"
36 #include "qapi/qmp/qstring.h"
37 #include "qemu/ctype.h"
38 #include "qemu/cutils.h"
39 #include "qemu/error-report.h"
48 /* TODO: add ":bootsector=blabla.img:" */
49 /* LATER TODO: add automatic boot sector generation from
50 BOOTEASY.ASM and Ranish Partition Manager
51 Note that DOS assumes the system files to be the first files in the
52 file system (test if the boot sector still relies on that fact)! */
53 /* MAYBE TODO: write block-visofs.c */
54 /* TODO: call try_commit() only after a timeout */
62 static void checkpoint(void);
70 /* bootsector OEM name. see related compatibility problems at:
71 * https://jdebp.eu/FGA/volume-boot-block-oem-name-field.html
72 * http://seasip.info/Misc/oemid.html
74 #define BOOTSECTOR_OEM_NAME "MSWIN4.1"
76 #define DIR_DELETED 0xe5
77 #define DIR_KANJI DIR_DELETED
78 #define DIR_KANJI_FAKE 0x05
81 /* dynamic array functions */
82 typedef struct array_t
{
84 unsigned int size
,next
,item_size
;
87 static inline void array_init(array_t
* array
,unsigned int item_size
)
89 array
->pointer
= NULL
;
92 array
->item_size
=item_size
;
95 static inline void array_free(array_t
* array
)
97 g_free(array
->pointer
);
98 array
->size
=array
->next
=0;
101 /* does not automatically grow */
102 static inline void* array_get(array_t
* array
,unsigned int index
) {
103 assert(index
< array
->next
);
104 assert(array
->pointer
);
105 return array
->pointer
+ index
* array
->item_size
;
108 static inline void array_ensure_allocated(array_t
*array
, int index
)
110 if((index
+ 1) * array
->item_size
> array
->size
) {
111 int new_size
= (index
+ 32) * array
->item_size
;
112 array
->pointer
= g_realloc(array
->pointer
, new_size
);
113 assert(array
->pointer
);
114 memset(array
->pointer
+ array
->size
, 0, new_size
- array
->size
);
115 array
->size
= new_size
;
116 array
->next
= index
+ 1;
120 static inline void* array_get_next(array_t
* array
) {
121 unsigned int next
= array
->next
;
123 array_ensure_allocated(array
, next
);
124 array
->next
= next
+ 1;
125 return array_get(array
, next
);
128 static inline void* array_insert(array_t
* array
,unsigned int index
,unsigned int count
) {
129 if((array
->next
+count
)*array
->item_size
>array
->size
) {
130 int increment
=count
*array
->item_size
;
131 array
->pointer
=g_realloc(array
->pointer
,array
->size
+increment
);
134 array
->size
+=increment
;
136 memmove(array
->pointer
+(index
+count
)*array
->item_size
,
137 array
->pointer
+index
*array
->item_size
,
138 (array
->next
-index
)*array
->item_size
);
140 return array
->pointer
+index
*array
->item_size
;
143 /* this performs a "roll", so that the element which was at index_from becomes
144 * index_to, but the order of all other elements is preserved. */
145 static inline int array_roll(array_t
* array
,int index_to
,int index_from
,int count
)
153 index_to
<0 || index_to
>=array
->next
||
154 index_from
<0 || index_from
>=array
->next
)
157 if(index_to
==index_from
)
161 from
=array
->pointer
+index_from
*is
;
162 to
=array
->pointer
+index_to
*is
;
163 buf
=g_malloc(is
*count
);
164 memcpy(buf
,from
,is
*count
);
166 if(index_to
<index_from
)
167 memmove(to
+is
*count
,to
,from
-to
);
169 memmove(from
,from
+is
*count
,to
-from
);
171 memcpy(to
,buf
,is
*count
);
178 static inline int array_remove_slice(array_t
* array
,int index
, int count
)
182 assert(index
+ count
<= array
->next
);
183 if(array_roll(array
,array
->next
-1,index
,count
))
185 array
->next
-= count
;
189 static int array_remove(array_t
* array
,int index
)
191 return array_remove_slice(array
, index
, 1);
194 /* return the index for a given member */
195 static int array_index(array_t
* array
, void* pointer
)
197 size_t offset
= (char*)pointer
- array
->pointer
;
198 assert((offset
% array
->item_size
) == 0);
199 assert(offset
/array
->item_size
< array
->next
);
200 return offset
/array
->item_size
;
203 /* These structures are used to fake a disk and the VFAT filesystem.
204 * For this reason we need to use QEMU_PACKED. */
206 typedef struct bootsector_t
{
209 uint16_t sector_size
;
210 uint8_t sectors_per_cluster
;
211 uint16_t reserved_sectors
;
212 uint8_t number_of_fats
;
213 uint16_t root_entries
;
214 uint16_t total_sectors16
;
216 uint16_t sectors_per_fat
;
217 uint16_t sectors_per_track
;
218 uint16_t number_of_heads
;
219 uint32_t hidden_sectors
;
220 uint32_t total_sectors
;
223 uint8_t drive_number
;
227 uint8_t volume_label
[11];
229 uint8_t ignored
[0x1c0];
232 uint32_t sectors_per_fat
;
235 uint32_t first_cluster_of_root_dir
;
236 uint16_t info_sector
;
237 uint16_t backup_boot_sector
;
238 uint8_t reserved
[12];
239 uint8_t drive_number
;
243 uint8_t volume_label
[11];
245 uint8_t ignored
[0x1a4];
249 } QEMU_PACKED bootsector_t
;
257 typedef struct partition_t
{
258 uint8_t attributes
; /* 0x80 = bootable */
260 uint8_t fs_type
; /* 0x1 = FAT12, 0x6 = FAT16, 0xe = FAT16_LBA, 0xb = FAT32, 0xc = FAT32_LBA */
262 uint32_t start_sector_long
;
263 uint32_t length_sector_long
;
264 } QEMU_PACKED partition_t
;
266 typedef struct mbr_t
{
267 uint8_t ignored
[0x1b8];
270 partition_t partition
[4];
274 typedef struct direntry_t
{
286 } QEMU_PACKED direntry_t
;
288 /* this structure are used to transparently access the files */
290 typedef struct mapping_t
{
291 /* begin is the first cluster, end is the last+1 */
293 /* as s->directory is growable, no pointer may be used here */
294 unsigned int dir_index
;
295 /* the clusters of a file may be in any order; this points to the first */
296 int first_mapping_index
;
299 * - the offset in the file (in clusters) for a file, or
300 * - the next cluster of the directory for a directory
306 int parent_mapping_index
;
310 /* path contains the full path, i.e. it always starts with s->path */
324 static void print_direntry(const struct direntry_t
*);
325 static void print_mapping(const struct mapping_t
* mapping
);
328 /* here begins the real VVFAT driver */
330 typedef struct BDRVVVFATState
{
332 BlockDriverState
* bs
; /* pointer to parent */
333 unsigned char first_sectors
[0x40*0x200];
335 int fat_type
; /* 16 or 32 */
336 array_t fat
,directory
,mapping
;
337 char volume_label
[11];
339 uint32_t offset_to_bootsector
; /* 0 for floppy, 0x3f for disk */
341 unsigned int cluster_size
;
342 unsigned int sectors_per_cluster
;
343 unsigned int sectors_per_fat
;
344 uint32_t last_cluster_of_root_directory
;
345 /* how many entries are available in root directory (0 for FAT32) */
346 uint16_t root_entries
;
347 uint32_t sector_count
; /* total number of sectors of the partition */
348 uint32_t cluster_count
; /* total number of clusters of this partition */
349 uint32_t max_fat_value
;
350 uint32_t offset_to_fat
;
351 uint32_t offset_to_root_dir
;
354 mapping_t
* current_mapping
;
355 unsigned char* cluster
; /* points to current cluster */
356 unsigned char* cluster_buffer
; /* points to a buffer to hold temp data */
357 unsigned int current_cluster
;
366 int downcase_short_names
;
368 Error
*migration_blocker
;
371 /* take the sector position spos and convert it to Cylinder/Head/Sector position
372 * if the position is outside the specified geometry, fill maximum value for CHS
373 * and return 1 to signal overflow.
375 static int sector2CHS(mbr_chs_t
*chs
, int spos
, int cyls
, int heads
, int secs
)
378 sector
= spos
% secs
; spos
/= secs
;
379 head
= spos
% heads
; spos
/= heads
;
382 it happens if 32bit sector positions are used, while CHS is only 24bit.
383 Windows/Dos is said to take 1023/255/63 as nonrepresentable CHS */
386 chs
->cylinder
= 0xFF;
389 chs
->head
= (uint8_t)head
;
390 chs
->sector
= (uint8_t)( (sector
+1) | ((spos
>>8)<<6) );
391 chs
->cylinder
= (uint8_t)spos
;
395 static void init_mbr(BDRVVVFATState
*s
, int cyls
, int heads
, int secs
)
397 /* TODO: if the files mbr.img and bootsect.img exist, use them */
398 mbr_t
* real_mbr
=(mbr_t
*)s
->first_sectors
;
399 partition_t
* partition
= &(real_mbr
->partition
[0]);
402 memset(s
->first_sectors
,0,512);
404 /* Win NT Disk Signature */
405 real_mbr
->nt_id
= cpu_to_le32(0xbe1afdfa);
407 partition
->attributes
=0x80; /* bootable */
409 /* LBA is used when partition is outside the CHS geometry */
410 lba
= sector2CHS(&partition
->start_CHS
, s
->offset_to_bootsector
,
412 lba
|= sector2CHS(&partition
->end_CHS
, s
->bs
->total_sectors
- 1,
415 /*LBA partitions are identified only by start/length_sector_long not by CHS*/
416 partition
->start_sector_long
= cpu_to_le32(s
->offset_to_bootsector
);
417 partition
->length_sector_long
= cpu_to_le32(s
->bs
->total_sectors
418 - s
->offset_to_bootsector
);
420 /* FAT12/FAT16/FAT32 */
421 /* DOS uses different types when partition is LBA,
422 probably to prevent older versions from using CHS on them */
423 partition
->fs_type
= s
->fat_type
== 12 ? 0x1 :
424 s
->fat_type
== 16 ? (lba
? 0xe : 0x06) :
425 /*s->fat_type == 32*/ (lba
? 0xc : 0x0b);
427 real_mbr
->magic
[0]=0x55; real_mbr
->magic
[1]=0xaa;
430 /* direntry functions */
432 static direntry_t
*create_long_filename(BDRVVVFATState
*s
, const char *filename
)
434 int number_of_entries
, i
;
438 gunichar2
*longname
= g_utf8_to_utf16(filename
, -1, NULL
, &length
, NULL
);
440 fprintf(stderr
, "vvfat: invalid UTF-8 name: %s\n", filename
);
444 number_of_entries
= DIV_ROUND_UP(length
* 2, 26);
446 for(i
=0;i
<number_of_entries
;i
++) {
447 entry
=array_get_next(&(s
->directory
));
448 entry
->attributes
=0xf;
449 entry
->reserved
[0]=0;
451 entry
->name
[0]=(number_of_entries
-i
)|(i
==0?0x40:0);
453 for(i
=0;i
<26*number_of_entries
;i
++) {
455 if(offset
<10) offset
=1+offset
;
456 else if(offset
<22) offset
=14+offset
-10;
457 else offset
=28+offset
-22;
458 entry
=array_get(&(s
->directory
),s
->directory
.next
-1-(i
/26));
459 if (i
>= 2 * length
+ 2) {
460 entry
->name
[offset
] = 0xff;
461 } else if (i
% 2 == 0) {
462 entry
->name
[offset
] = longname
[i
/ 2] & 0xff;
464 entry
->name
[offset
] = longname
[i
/ 2] >> 8;
468 return array_get(&(s
->directory
),s
->directory
.next
-number_of_entries
);
471 static char is_free(const direntry_t
* direntry
)
473 return direntry
->name
[0] == DIR_DELETED
|| direntry
->name
[0] == DIR_FREE
;
476 static char is_volume_label(const direntry_t
* direntry
)
478 return direntry
->attributes
== 0x28;
481 static char is_long_name(const direntry_t
* direntry
)
483 return direntry
->attributes
== 0xf;
486 static char is_short_name(const direntry_t
* direntry
)
488 return !is_volume_label(direntry
) && !is_long_name(direntry
)
489 && !is_free(direntry
);
492 static char is_directory(const direntry_t
* direntry
)
494 return direntry
->attributes
& 0x10 && direntry
->name
[0] != DIR_DELETED
;
497 static inline char is_dot(const direntry_t
* direntry
)
499 return is_short_name(direntry
) && direntry
->name
[0] == '.';
502 static char is_file(const direntry_t
* direntry
)
504 return is_short_name(direntry
) && !is_directory(direntry
);
507 static inline uint32_t begin_of_direntry(const direntry_t
* direntry
)
509 return le16_to_cpu(direntry
->begin
)|(le16_to_cpu(direntry
->begin_hi
)<<16);
512 static inline uint32_t filesize_of_direntry(const direntry_t
* direntry
)
514 return le32_to_cpu(direntry
->size
);
517 static void set_begin_of_direntry(direntry_t
* direntry
, uint32_t begin
)
519 direntry
->begin
= cpu_to_le16(begin
& 0xffff);
520 direntry
->begin_hi
= cpu_to_le16((begin
>> 16) & 0xffff);
523 static uint8_t to_valid_short_char(gunichar c
)
525 c
= g_unichar_toupper(c
);
526 if ((c
>= '0' && c
<= '9') ||
527 (c
>= 'A' && c
<= 'Z') ||
528 strchr("$%'-_@~`!(){}^#&", c
) != 0) {
535 static direntry_t
*create_short_filename(BDRVVVFATState
*s
,
536 const char *filename
,
537 unsigned int directory_start
)
540 direntry_t
*entry
= array_get_next(&(s
->directory
));
541 const gchar
*p
, *last_dot
= NULL
;
543 bool lossy_conversion
= false;
549 memset(entry
->name
, 0x20, sizeof(entry
->name
));
551 /* copy filename and search last dot */
552 for (p
= filename
; ; p
= g_utf8_next_char(p
)) {
553 c
= g_utf8_get_char(p
);
556 } else if (c
== '.') {
558 /* '.' at start of filename */
559 lossy_conversion
= true;
562 lossy_conversion
= true;
566 } else if (!last_dot
) {
567 /* first part of the name; copy it */
568 uint8_t v
= to_valid_short_char(c
);
570 entry
->name
[j
++] = v
;
572 lossy_conversion
= true;
577 /* copy extension (if any) */
580 for (p
= g_utf8_next_char(last_dot
); ; p
= g_utf8_next_char(p
)) {
581 c
= g_utf8_get_char(p
);
585 /* extension; copy it */
586 uint8_t v
= to_valid_short_char(c
);
588 entry
->name
[8 + (j
++)] = v
;
590 lossy_conversion
= true;
596 if (entry
->name
[0] == DIR_KANJI
) {
597 entry
->name
[0] = DIR_KANJI_FAKE
;
600 /* numeric-tail generation */
601 for (j
= 0; j
< 8; j
++) {
602 if (entry
->name
[j
] == ' ') {
606 for (i
= lossy_conversion
? 1 : 0; i
< 999999; i
++) {
609 int len
= snprintf(tail
, sizeof(tail
), "~%u", (unsigned)i
);
611 memcpy(entry
->name
+ MIN(j
, 8 - len
), tail
, len
);
613 for (entry1
= array_get(&(s
->directory
), directory_start
);
614 entry1
< entry
; entry1
++) {
615 if (!is_long_name(entry1
) &&
616 !memcmp(entry1
->name
, entry
->name
, 11)) {
617 break; /* found dupe */
620 if (entry1
== entry
) {
630 static inline uint8_t fat_chksum(const direntry_t
* entry
)
635 for (i
= 0; i
< ARRAY_SIZE(entry
->name
); i
++) {
636 chksum
= (((chksum
& 0xfe) >> 1) |
637 ((chksum
& 0x01) ? 0x80 : 0)) + entry
->name
[i
];
643 /* if return_time==0, this returns the fat_date, else the fat_time */
644 static uint16_t fat_datetime(time_t time
,int return_time
) {
648 localtime_r(&time
,t
);
650 return cpu_to_le16((t
->tm_sec
/2)|(t
->tm_min
<<5)|(t
->tm_hour
<<11));
651 return cpu_to_le16((t
->tm_mday
)|((t
->tm_mon
+1)<<5)|((t
->tm_year
-80)<<9));
654 static inline void fat_set(BDRVVVFATState
* s
,unsigned int cluster
,uint32_t value
)
656 if(s
->fat_type
==32) {
657 uint32_t* entry
=array_get(&(s
->fat
),cluster
);
658 *entry
=cpu_to_le32(value
);
659 } else if(s
->fat_type
==16) {
660 uint16_t* entry
=array_get(&(s
->fat
),cluster
);
661 *entry
=cpu_to_le16(value
&0xffff);
663 int offset
= (cluster
*3/2);
664 unsigned char* p
= array_get(&(s
->fat
), offset
);
668 p
[1] = (p
[1]&0xf0) | ((value
>>8)&0xf);
671 p
[0] = (p
[0]&0xf) | ((value
&0xf)<<4);
678 static inline uint32_t fat_get(BDRVVVFATState
* s
,unsigned int cluster
)
680 if(s
->fat_type
==32) {
681 uint32_t* entry
=array_get(&(s
->fat
),cluster
);
682 return le32_to_cpu(*entry
);
683 } else if(s
->fat_type
==16) {
684 uint16_t* entry
=array_get(&(s
->fat
),cluster
);
685 return le16_to_cpu(*entry
);
687 const uint8_t* x
=(uint8_t*)(s
->fat
.pointer
)+cluster
*3/2;
688 return ((x
[0]|(x
[1]<<8))>>(cluster
&1?4:0))&0x0fff;
692 static inline int fat_eof(BDRVVVFATState
* s
,uint32_t fat_entry
)
694 if(fat_entry
>s
->max_fat_value
-8)
699 static inline void init_fat(BDRVVVFATState
* s
)
701 if (s
->fat_type
== 12) {
702 array_init(&(s
->fat
),1);
703 array_ensure_allocated(&(s
->fat
),
704 s
->sectors_per_fat
* 0x200 * 3 / 2 - 1);
706 array_init(&(s
->fat
),(s
->fat_type
==32?4:2));
707 array_ensure_allocated(&(s
->fat
),
708 s
->sectors_per_fat
* 0x200 / s
->fat
.item_size
- 1);
710 memset(s
->fat
.pointer
,0,s
->fat
.size
);
712 switch(s
->fat_type
) {
713 case 12: s
->max_fat_value
=0xfff; break;
714 case 16: s
->max_fat_value
=0xffff; break;
715 case 32: s
->max_fat_value
=0x0fffffff; break;
716 default: s
->max_fat_value
=0; /* error... */
721 static inline direntry_t
* create_short_and_long_name(BDRVVVFATState
* s
,
722 unsigned int directory_start
, const char* filename
, int is_dot
)
724 int long_index
= s
->directory
.next
;
725 direntry_t
* entry
= NULL
;
726 direntry_t
* entry_long
= NULL
;
729 entry
=array_get_next(&(s
->directory
));
730 memset(entry
->name
, 0x20, sizeof(entry
->name
));
731 memcpy(entry
->name
,filename
,strlen(filename
));
735 entry_long
=create_long_filename(s
,filename
);
736 entry
= create_short_filename(s
, filename
, directory_start
);
738 /* calculate checksum; propagate to long name */
740 uint8_t chksum
=fat_chksum(entry
);
742 /* calculate anew, because realloc could have taken place */
743 entry_long
=array_get(&(s
->directory
),long_index
);
744 while(entry_long
<entry
&& is_long_name(entry_long
)) {
745 entry_long
->reserved
[1]=chksum
;
754 * Read a directory. (the index of the corresponding mapping must be passed).
756 static int read_directory(BDRVVVFATState
* s
, int mapping_index
)
758 mapping_t
* mapping
= array_get(&(s
->mapping
), mapping_index
);
759 direntry_t
* direntry
;
760 const char* dirname
= mapping
->path
;
761 int first_cluster
= mapping
->begin
;
762 int parent_index
= mapping
->info
.dir
.parent_mapping_index
;
763 mapping_t
* parent_mapping
= (mapping_t
*)
764 (parent_index
>= 0 ? array_get(&(s
->mapping
), parent_index
) : NULL
);
765 int first_cluster_of_parent
= parent_mapping
? parent_mapping
->begin
: -1;
767 DIR* dir
=opendir(dirname
);
768 struct dirent
* entry
;
771 assert(mapping
->mode
& MODE_DIRECTORY
);
774 mapping
->end
= mapping
->begin
;
778 i
= mapping
->info
.dir
.first_dir_index
=
779 first_cluster
== 0 ? 0 : s
->directory
.next
;
781 if (first_cluster
!= 0) {
782 /* create the top entries of a subdirectory */
783 (void)create_short_and_long_name(s
, i
, ".", 1);
784 (void)create_short_and_long_name(s
, i
, "..", 1);
787 /* actually read the directory, and allocate the mappings */
788 while((entry
=readdir(dir
))) {
789 unsigned int length
=strlen(dirname
)+2+strlen(entry
->d_name
);
791 direntry_t
* direntry
;
793 int is_dot
=!strcmp(entry
->d_name
,".");
794 int is_dotdot
=!strcmp(entry
->d_name
,"..");
796 if (first_cluster
== 0 && s
->directory
.next
>= s
->root_entries
- 1) {
797 fprintf(stderr
, "Too many entries in root directory\n");
802 if(first_cluster
== 0 && (is_dotdot
|| is_dot
))
805 buffer
= g_malloc(length
);
806 snprintf(buffer
,length
,"%s/%s",dirname
,entry
->d_name
);
808 if(stat(buffer
,&st
)<0) {
813 /* create directory entry for this file */
814 if (!is_dot
&& !is_dotdot
) {
815 direntry
= create_short_and_long_name(s
, i
, entry
->d_name
, 0);
817 direntry
= array_get(&(s
->directory
), is_dot
? i
: i
+ 1);
819 direntry
->attributes
=(S_ISDIR(st
.st_mode
)?0x10:0x20);
820 direntry
->reserved
[0]=direntry
->reserved
[1]=0;
821 direntry
->ctime
=fat_datetime(st
.st_ctime
,1);
822 direntry
->cdate
=fat_datetime(st
.st_ctime
,0);
823 direntry
->adate
=fat_datetime(st
.st_atime
,0);
824 direntry
->begin_hi
=0;
825 direntry
->mtime
=fat_datetime(st
.st_mtime
,1);
826 direntry
->mdate
=fat_datetime(st
.st_mtime
,0);
828 set_begin_of_direntry(direntry
, first_cluster_of_parent
);
830 set_begin_of_direntry(direntry
, first_cluster
);
832 direntry
->begin
=0; /* do that later */
833 if (st
.st_size
> 0x7fffffff) {
834 fprintf(stderr
, "File %s is larger than 2GB\n", buffer
);
839 direntry
->size
=cpu_to_le32(S_ISDIR(st
.st_mode
)?0:st
.st_size
);
841 /* create mapping for this file */
842 if(!is_dot
&& !is_dotdot
&& (S_ISDIR(st
.st_mode
) || st
.st_size
)) {
843 s
->current_mapping
= array_get_next(&(s
->mapping
));
844 s
->current_mapping
->begin
=0;
845 s
->current_mapping
->end
=st
.st_size
;
847 * we get the direntry of the most recent direntry, which
848 * contains the short name and all the relevant information.
850 s
->current_mapping
->dir_index
=s
->directory
.next
-1;
851 s
->current_mapping
->first_mapping_index
= -1;
852 if (S_ISDIR(st
.st_mode
)) {
853 s
->current_mapping
->mode
= MODE_DIRECTORY
;
854 s
->current_mapping
->info
.dir
.parent_mapping_index
=
857 s
->current_mapping
->mode
= MODE_UNDEFINED
;
858 s
->current_mapping
->info
.file
.offset
= 0;
860 s
->current_mapping
->path
=buffer
;
861 s
->current_mapping
->read_only
=
862 (st
.st_mode
& (S_IWUSR
| S_IWGRP
| S_IWOTH
)) == 0;
869 /* fill with zeroes up to the end of the cluster */
870 while(s
->directory
.next
%(0x10*s
->sectors_per_cluster
)) {
871 direntry_t
* direntry
=array_get_next(&(s
->directory
));
872 memset(direntry
,0,sizeof(direntry_t
));
875 if (s
->fat_type
!= 32 &&
876 mapping_index
== 0 &&
877 s
->directory
.next
< s
->root_entries
) {
879 int cur
= s
->directory
.next
;
880 array_ensure_allocated(&(s
->directory
), s
->root_entries
- 1);
881 s
->directory
.next
= s
->root_entries
;
882 memset(array_get(&(s
->directory
), cur
), 0,
883 (s
->root_entries
- cur
) * sizeof(direntry_t
));
886 /* re-get the mapping, since s->mapping was possibly realloc()ed */
887 mapping
= array_get(&(s
->mapping
), mapping_index
);
888 first_cluster
+= (s
->directory
.next
- mapping
->info
.dir
.first_dir_index
)
889 * 0x20 / s
->cluster_size
;
890 mapping
->end
= first_cluster
;
892 direntry
= array_get(&(s
->directory
), mapping
->dir_index
);
893 set_begin_of_direntry(direntry
, mapping
->begin
);
898 static inline uint32_t sector2cluster(BDRVVVFATState
* s
,off_t sector_num
)
900 return (sector_num
- s
->offset_to_root_dir
) / s
->sectors_per_cluster
;
903 static inline off_t
cluster2sector(BDRVVVFATState
* s
, uint32_t cluster_num
)
905 return s
->offset_to_root_dir
+ s
->sectors_per_cluster
* cluster_num
;
908 static int init_directories(BDRVVVFATState
* s
,
909 const char *dirname
, int heads
, int secs
,
912 bootsector_t
* bootsector
;
915 unsigned int cluster
;
917 memset(&(s
->first_sectors
[0]),0,0x40*0x200);
919 s
->cluster_size
=s
->sectors_per_cluster
*0x200;
920 s
->cluster_buffer
=g_malloc(s
->cluster_size
);
923 * The formula: sc = spf+1+spf*spc*(512*8/fat_type),
924 * where sc is sector_count,
925 * spf is sectors_per_fat,
926 * spc is sectors_per_clusters, and
927 * fat_type = 12, 16 or 32.
929 i
= 1+s
->sectors_per_cluster
*0x200*8/s
->fat_type
;
930 s
->sectors_per_fat
=(s
->sector_count
+i
)/i
; /* round up */
932 s
->offset_to_fat
= s
->offset_to_bootsector
+ 1;
933 s
->offset_to_root_dir
= s
->offset_to_fat
+ s
->sectors_per_fat
* 2;
935 array_init(&(s
->mapping
),sizeof(mapping_t
));
936 array_init(&(s
->directory
),sizeof(direntry_t
));
938 /* add volume label */
940 direntry_t
* entry
=array_get_next(&(s
->directory
));
941 entry
->attributes
=0x28; /* archive | volume label */
942 memcpy(entry
->name
, s
->volume_label
, sizeof(entry
->name
));
945 /* Now build FAT, and write back information into directory */
948 /* TODO: if there are more entries, bootsector has to be adjusted! */
949 s
->root_entries
= 0x02 * 0x10 * s
->sectors_per_cluster
;
950 s
->cluster_count
=sector2cluster(s
, s
->sector_count
);
952 mapping
= array_get_next(&(s
->mapping
));
954 mapping
->dir_index
= 0;
955 mapping
->info
.dir
.parent_mapping_index
= -1;
956 mapping
->first_mapping_index
= -1;
957 mapping
->path
= g_strdup(dirname
);
958 i
= strlen(mapping
->path
);
959 if (i
> 0 && mapping
->path
[i
- 1] == '/')
960 mapping
->path
[i
- 1] = '\0';
961 mapping
->mode
= MODE_DIRECTORY
;
962 mapping
->read_only
= 0;
963 s
->path
= mapping
->path
;
965 for (i
= 0, cluster
= 0; i
< s
->mapping
.next
; i
++) {
966 /* MS-DOS expects the FAT to be 0 for the root directory
967 * (except for the media byte). */
968 /* LATER TODO: still true for FAT32? */
969 int fix_fat
= (i
!= 0);
970 mapping
= array_get(&(s
->mapping
), i
);
972 if (mapping
->mode
& MODE_DIRECTORY
) {
973 char *path
= mapping
->path
;
974 mapping
->begin
= cluster
;
975 if(read_directory(s
, i
)) {
976 error_setg(errp
, "Could not read directory %s", path
);
979 mapping
= array_get(&(s
->mapping
), i
);
981 assert(mapping
->mode
== MODE_UNDEFINED
);
982 mapping
->mode
=MODE_NORMAL
;
983 mapping
->begin
= cluster
;
984 if (mapping
->end
> 0) {
985 direntry_t
* direntry
= array_get(&(s
->directory
),
988 mapping
->end
= cluster
+ 1 + (mapping
->end
-1)/s
->cluster_size
;
989 set_begin_of_direntry(direntry
, mapping
->begin
);
991 mapping
->end
= cluster
+ 1;
996 assert(mapping
->begin
< mapping
->end
);
998 /* next free cluster */
999 cluster
= mapping
->end
;
1001 if(cluster
> s
->cluster_count
) {
1003 "Directory does not fit in FAT%d (capacity %.2f MB)",
1004 s
->fat_type
, s
->sector_count
/ 2000.0);
1008 /* fix fat for entry */
1011 for(j
= mapping
->begin
; j
< mapping
->end
- 1; j
++)
1013 fat_set(s
, mapping
->end
- 1, s
->max_fat_value
);
1017 mapping
= array_get(&(s
->mapping
), 0);
1018 s
->last_cluster_of_root_directory
= mapping
->end
;
1020 /* the FAT signature */
1021 fat_set(s
,0,s
->max_fat_value
);
1022 fat_set(s
,1,s
->max_fat_value
);
1024 s
->current_mapping
= NULL
;
1026 bootsector
= (bootsector_t
*)(s
->first_sectors
1027 + s
->offset_to_bootsector
* 0x200);
1028 bootsector
->jump
[0]=0xeb;
1029 bootsector
->jump
[1]=0x3e;
1030 bootsector
->jump
[2]=0x90;
1031 memcpy(bootsector
->name
, BOOTSECTOR_OEM_NAME
, 8);
1032 bootsector
->sector_size
=cpu_to_le16(0x200);
1033 bootsector
->sectors_per_cluster
=s
->sectors_per_cluster
;
1034 bootsector
->reserved_sectors
=cpu_to_le16(1);
1035 bootsector
->number_of_fats
=0x2; /* number of FATs */
1036 bootsector
->root_entries
= cpu_to_le16(s
->root_entries
);
1037 bootsector
->total_sectors16
=s
->sector_count
>0xffff?0:cpu_to_le16(s
->sector_count
);
1038 /* media descriptor: hard disk=0xf8, floppy=0xf0 */
1039 bootsector
->media_type
= (s
->offset_to_bootsector
> 0 ? 0xf8 : 0xf0);
1040 s
->fat
.pointer
[0] = bootsector
->media_type
;
1041 bootsector
->sectors_per_fat
=cpu_to_le16(s
->sectors_per_fat
);
1042 bootsector
->sectors_per_track
= cpu_to_le16(secs
);
1043 bootsector
->number_of_heads
= cpu_to_le16(heads
);
1044 bootsector
->hidden_sectors
= cpu_to_le32(s
->offset_to_bootsector
);
1045 bootsector
->total_sectors
=cpu_to_le32(s
->sector_count
>0xffff?s
->sector_count
:0);
1047 /* LATER TODO: if FAT32, this is wrong */
1048 /* drive_number: fda=0, hda=0x80 */
1049 bootsector
->u
.fat16
.drive_number
= s
->offset_to_bootsector
== 0 ? 0 : 0x80;
1050 bootsector
->u
.fat16
.signature
=0x29;
1051 bootsector
->u
.fat16
.id
=cpu_to_le32(0xfabe1afd);
1053 memcpy(bootsector
->u
.fat16
.volume_label
, s
->volume_label
,
1054 sizeof(bootsector
->u
.fat16
.volume_label
));
1055 memcpy(bootsector
->u
.fat16
.fat_type
,
1056 s
->fat_type
== 12 ? "FAT12 " : "FAT16 ", 8);
1057 bootsector
->magic
[0]=0x55; bootsector
->magic
[1]=0xaa;
1063 static BDRVVVFATState
*vvv
= NULL
;
1066 static int enable_write_target(BlockDriverState
*bs
, Error
**errp
);
1067 static int is_consistent(BDRVVVFATState
*s
);
1069 static QemuOptsList runtime_opts
= {
1071 .head
= QTAILQ_HEAD_INITIALIZER(runtime_opts
.head
),
1075 .type
= QEMU_OPT_STRING
,
1076 .help
= "Host directory to map to the vvfat device",
1080 .type
= QEMU_OPT_NUMBER
,
1081 .help
= "FAT type (12, 16 or 32)",
1085 .type
= QEMU_OPT_BOOL
,
1086 .help
= "Create a floppy rather than a hard disk image",
1090 .type
= QEMU_OPT_STRING
,
1091 .help
= "Use a volume label other than QEMU VVFAT",
1095 .type
= QEMU_OPT_BOOL
,
1096 .help
= "Make the image writable",
1098 { /* end of list */ }
1102 static void vvfat_parse_filename(const char *filename
, QDict
*options
,
1106 bool floppy
= false;
1110 if (!strstart(filename
, "fat:", NULL
)) {
1111 error_setg(errp
, "File name string must start with 'fat:'");
1116 if (strstr(filename
, ":32:")) {
1118 } else if (strstr(filename
, ":16:")) {
1120 } else if (strstr(filename
, ":12:")) {
1124 if (strstr(filename
, ":floppy:")) {
1128 if (strstr(filename
, ":rw:")) {
1132 /* Get the directory name without options */
1133 i
= strrchr(filename
, ':') - filename
;
1135 if (filename
[i
- 2] == ':' && qemu_isalpha(filename
[i
- 1])) {
1136 /* workaround for DOS drive names */
1142 /* Fill in the options QDict */
1143 qdict_put_str(options
, "dir", filename
);
1144 qdict_put_int(options
, "fat-type", fat_type
);
1145 qdict_put_bool(options
, "floppy", floppy
);
1146 qdict_put_bool(options
, "rw", rw
);
1149 static int vvfat_open(BlockDriverState
*bs
, QDict
*options
, int flags
,
1152 BDRVVVFATState
*s
= bs
->opaque
;
1153 int cyls
, heads
, secs
;
1155 const char *dirname
, *label
;
1157 Error
*local_err
= NULL
;
1164 opts
= qemu_opts_create(&runtime_opts
, NULL
, 0, &error_abort
);
1165 qemu_opts_absorb_qdict(opts
, options
, &local_err
);
1167 error_propagate(errp
, local_err
);
1172 dirname
= qemu_opt_get(opts
, "dir");
1174 error_setg(errp
, "vvfat block driver requires a 'dir' option");
1179 s
->fat_type
= qemu_opt_get_number(opts
, "fat-type", 0);
1180 floppy
= qemu_opt_get_bool(opts
, "floppy", false);
1182 memset(s
->volume_label
, ' ', sizeof(s
->volume_label
));
1183 label
= qemu_opt_get(opts
, "label");
1185 size_t label_length
= strlen(label
);
1186 if (label_length
> 11) {
1187 error_setg(errp
, "vvfat label cannot be longer than 11 bytes");
1191 memcpy(s
->volume_label
, label
, label_length
);
1193 memcpy(s
->volume_label
, "QEMU VVFAT", 10);
1197 /* 1.44MB or 2.88MB floppy. 2.88MB can be FAT12 (default) or FAT16. */
1201 s
->sectors_per_cluster
= 2;
1203 secs
= s
->fat_type
== 12 ? 18 : 36;
1204 s
->sectors_per_cluster
= 1;
1209 /* 32MB or 504MB disk*/
1213 s
->offset_to_bootsector
= 0x3f;
1214 cyls
= s
->fat_type
== 12 ? 64 : 1024;
1219 switch (s
->fat_type
) {
1221 warn_report("FAT32 has not been tested. You are welcome to do so!");
1227 error_setg(errp
, "Valid FAT types are only 12, 16 and 32");
1235 /* LATER TODO: if FAT32, adjust */
1236 s
->sectors_per_cluster
=0x10;
1238 s
->current_cluster
=0xffffffff;
1241 s
->qcow_filename
= NULL
;
1243 s
->downcase_short_names
= 1;
1245 DLOG(fprintf(stderr
, "vvfat %s chs %d,%d,%d\n",
1246 dirname
, cyls
, heads
, secs
));
1248 s
->sector_count
= cyls
* heads
* secs
- s
->offset_to_bootsector
;
1250 if (qemu_opt_get_bool(opts
, "rw", false)) {
1251 if (!bdrv_is_read_only(bs
)) {
1252 ret
= enable_write_target(bs
, errp
);
1259 "Unable to set VVFAT to 'rw' when drive is read-only");
1263 ret
= bdrv_apply_auto_read_only(bs
, NULL
, errp
);
1269 bs
->total_sectors
= cyls
* heads
* secs
;
1271 if (init_directories(s
, dirname
, heads
, secs
, errp
)) {
1276 s
->sector_count
= s
->offset_to_root_dir
1277 + s
->sectors_per_cluster
* s
->cluster_count
;
1279 /* Disable migration when vvfat is used rw */
1281 error_setg(&s
->migration_blocker
,
1282 "The vvfat (rw) format used by node '%s' "
1283 "does not support live migration",
1284 bdrv_get_device_or_node_name(bs
));
1285 ret
= migrate_add_blocker(s
->migration_blocker
, &local_err
);
1287 error_propagate(errp
, local_err
);
1288 error_free(s
->migration_blocker
);
1293 if (s
->offset_to_bootsector
> 0) {
1294 init_mbr(s
, cyls
, heads
, secs
);
1297 qemu_co_mutex_init(&s
->lock
);
1301 qemu_opts_del(opts
);
1305 static void vvfat_refresh_limits(BlockDriverState
*bs
, Error
**errp
)
1307 bs
->bl
.request_alignment
= BDRV_SECTOR_SIZE
; /* No sub-sector I/O */
1310 static inline void vvfat_close_current_file(BDRVVVFATState
*s
)
1312 if(s
->current_mapping
) {
1313 s
->current_mapping
= NULL
;
1314 if (s
->current_fd
) {
1315 qemu_close(s
->current_fd
);
1319 s
->current_cluster
= -1;
1322 /* mappings between index1 and index2-1 are supposed to be ordered
1323 * return value is the index of the last mapping for which end>cluster_num
1325 static inline int find_mapping_for_cluster_aux(BDRVVVFATState
* s
,int cluster_num
,int index1
,int index2
)
1330 index3
=(index1
+index2
)/2;
1331 mapping
=array_get(&(s
->mapping
),index3
);
1332 assert(mapping
->begin
< mapping
->end
);
1333 if(mapping
->begin
>=cluster_num
) {
1334 assert(index2
!=index3
|| index2
==0);
1340 return mapping
->end
<=cluster_num
? index2
: index1
;
1343 assert(index1
<=index2
);
1344 DLOG(mapping
=array_get(&(s
->mapping
),index1
);
1345 assert(mapping
->begin
<=cluster_num
);
1346 assert(index2
>= s
->mapping
.next
||
1347 ((mapping
= array_get(&(s
->mapping
),index2
)) &&
1348 mapping
->end
>cluster_num
)));
1352 static inline mapping_t
* find_mapping_for_cluster(BDRVVVFATState
* s
,int cluster_num
)
1354 int index
=find_mapping_for_cluster_aux(s
,cluster_num
,0,s
->mapping
.next
);
1356 if(index
>=s
->mapping
.next
)
1358 mapping
=array_get(&(s
->mapping
),index
);
1359 if(mapping
->begin
>cluster_num
)
1361 assert(mapping
->begin
<=cluster_num
&& mapping
->end
>cluster_num
);
1365 static int open_file(BDRVVVFATState
* s
,mapping_t
* mapping
)
1369 if(!s
->current_mapping
||
1370 strcmp(s
->current_mapping
->path
,mapping
->path
)) {
1372 int fd
= qemu_open(mapping
->path
, O_RDONLY
| O_BINARY
| O_LARGEFILE
);
1375 vvfat_close_current_file(s
);
1377 s
->current_mapping
= mapping
;
1382 static inline int read_cluster(BDRVVVFATState
*s
,int cluster_num
)
1384 if(s
->current_cluster
!= cluster_num
) {
1387 assert(!s
->current_mapping
|| s
->current_fd
|| (s
->current_mapping
->mode
& MODE_DIRECTORY
));
1388 if(!s
->current_mapping
1389 || s
->current_mapping
->begin
>cluster_num
1390 || s
->current_mapping
->end
<=cluster_num
) {
1391 /* binary search of mappings for file */
1392 mapping_t
* mapping
=find_mapping_for_cluster(s
,cluster_num
);
1394 assert(!mapping
|| (cluster_num
>=mapping
->begin
&& cluster_num
<mapping
->end
));
1396 if (mapping
&& mapping
->mode
& MODE_DIRECTORY
) {
1397 vvfat_close_current_file(s
);
1398 s
->current_mapping
= mapping
;
1399 read_cluster_directory
:
1400 offset
= s
->cluster_size
*(cluster_num
-s
->current_mapping
->begin
);
1401 s
->cluster
= (unsigned char*)s
->directory
.pointer
+offset
1402 + 0x20*s
->current_mapping
->info
.dir
.first_dir_index
;
1403 assert(((s
->cluster
-(unsigned char*)s
->directory
.pointer
)%s
->cluster_size
)==0);
1404 assert((char*)s
->cluster
+s
->cluster_size
<= s
->directory
.pointer
+s
->directory
.next
*s
->directory
.item_size
);
1405 s
->current_cluster
= cluster_num
;
1409 if(open_file(s
,mapping
))
1411 } else if (s
->current_mapping
->mode
& MODE_DIRECTORY
)
1412 goto read_cluster_directory
;
1414 assert(s
->current_fd
);
1416 offset
=s
->cluster_size
*(cluster_num
-s
->current_mapping
->begin
)+s
->current_mapping
->info
.file
.offset
;
1417 if(lseek(s
->current_fd
, offset
, SEEK_SET
)!=offset
)
1419 s
->cluster
=s
->cluster_buffer
;
1420 result
=read(s
->current_fd
,s
->cluster
,s
->cluster_size
);
1422 s
->current_cluster
= -1;
1425 s
->current_cluster
= cluster_num
;
1431 static void print_direntry(const direntry_t
* direntry
)
1436 fprintf(stderr
, "direntry %p: ", direntry
);
1439 if(is_long_name(direntry
)) {
1440 unsigned char* c
=(unsigned char*)direntry
;
1442 for(i
=1;i
<11 && c
[i
] && c
[i
]!=0xff;i
+=2)
1443 #define ADD_CHAR(c) {buffer[j] = (c); if (buffer[j] < ' ') buffer[j] = 0xb0; j++;}
1445 for(i
=14;i
<26 && c
[i
] && c
[i
]!=0xff;i
+=2)
1447 for(i
=28;i
<32 && c
[i
] && c
[i
]!=0xff;i
+=2)
1450 fprintf(stderr
, "%s\n", buffer
);
1454 ADD_CHAR(direntry
->name
[i
]);
1456 fprintf(stderr
,"%s attributes=0x%02x begin=%d size=%d\n",
1458 direntry
->attributes
,
1459 begin_of_direntry(direntry
),le32_to_cpu(direntry
->size
));
1463 static void print_mapping(const mapping_t
* mapping
)
1465 fprintf(stderr
, "mapping (%p): begin, end = %d, %d, dir_index = %d, "
1466 "first_mapping_index = %d, name = %s, mode = 0x%x, " ,
1467 mapping
, mapping
->begin
, mapping
->end
, mapping
->dir_index
,
1468 mapping
->first_mapping_index
, mapping
->path
, mapping
->mode
);
1470 if (mapping
->mode
& MODE_DIRECTORY
)
1471 fprintf(stderr
, "parent_mapping_index = %d, first_dir_index = %d\n", mapping
->info
.dir
.parent_mapping_index
, mapping
->info
.dir
.first_dir_index
);
1473 fprintf(stderr
, "offset = %d\n", mapping
->info
.file
.offset
);
1477 static int vvfat_read(BlockDriverState
*bs
, int64_t sector_num
,
1478 uint8_t *buf
, int nb_sectors
)
1480 BDRVVVFATState
*s
= bs
->opaque
;
1483 for(i
=0;i
<nb_sectors
;i
++,sector_num
++) {
1484 if (sector_num
>= bs
->total_sectors
)
1489 ret
= bdrv_is_allocated(s
->qcow
->bs
, sector_num
* BDRV_SECTOR_SIZE
,
1490 (nb_sectors
- i
) * BDRV_SECTOR_SIZE
, &n
);
1495 DLOG(fprintf(stderr
, "sectors %" PRId64
"+%" PRId64
1496 " allocated\n", sector_num
,
1497 n
>> BDRV_SECTOR_BITS
));
1498 if (bdrv_pread(s
->qcow
, sector_num
* BDRV_SECTOR_SIZE
,
1499 buf
+ i
* 0x200, n
) < 0) {
1502 i
+= (n
>> BDRV_SECTOR_BITS
) - 1;
1503 sector_num
+= (n
>> BDRV_SECTOR_BITS
) - 1;
1506 DLOG(fprintf(stderr
, "sector %" PRId64
" not allocated\n",
1509 if (sector_num
< s
->offset_to_root_dir
) {
1510 if (sector_num
< s
->offset_to_fat
) {
1511 memcpy(buf
+ i
* 0x200,
1512 &(s
->first_sectors
[sector_num
* 0x200]),
1514 } else if (sector_num
< s
->offset_to_fat
+ s
->sectors_per_fat
) {
1515 memcpy(buf
+ i
* 0x200,
1516 &(s
->fat
.pointer
[(sector_num
1517 - s
->offset_to_fat
) * 0x200]),
1519 } else if (sector_num
< s
->offset_to_root_dir
) {
1520 memcpy(buf
+ i
* 0x200,
1521 &(s
->fat
.pointer
[(sector_num
- s
->offset_to_fat
1522 - s
->sectors_per_fat
) * 0x200]),
1526 uint32_t sector
= sector_num
- s
->offset_to_root_dir
,
1527 sector_offset_in_cluster
=(sector
%s
->sectors_per_cluster
),
1528 cluster_num
=sector
/s
->sectors_per_cluster
;
1529 if(cluster_num
> s
->cluster_count
|| read_cluster(s
, cluster_num
) != 0) {
1530 /* LATER TODO: strict: return -1; */
1531 memset(buf
+i
*0x200,0,0x200);
1534 memcpy(buf
+i
*0x200,s
->cluster
+sector_offset_in_cluster
*0x200,0x200);
1540 static int coroutine_fn
1541 vvfat_co_preadv(BlockDriverState
*bs
, uint64_t offset
, uint64_t bytes
,
1542 QEMUIOVector
*qiov
, int flags
)
1545 BDRVVVFATState
*s
= bs
->opaque
;
1546 uint64_t sector_num
= offset
>> BDRV_SECTOR_BITS
;
1547 int nb_sectors
= bytes
>> BDRV_SECTOR_BITS
;
1550 assert((offset
& (BDRV_SECTOR_SIZE
- 1)) == 0);
1551 assert((bytes
& (BDRV_SECTOR_SIZE
- 1)) == 0);
1553 buf
= g_try_malloc(bytes
);
1554 if (bytes
&& buf
== NULL
) {
1558 qemu_co_mutex_lock(&s
->lock
);
1559 ret
= vvfat_read(bs
, sector_num
, buf
, nb_sectors
);
1560 qemu_co_mutex_unlock(&s
->lock
);
1562 qemu_iovec_from_buf(qiov
, 0, buf
, bytes
);
1568 /* LATER TODO: statify all functions */
1571 * Idea of the write support (use snapshot):
1573 * 1. check if all data is consistent, recording renames, modifications,
1574 * new files and directories (in s->commits).
1576 * 2. if the data is not consistent, stop committing
1578 * 3. handle renames, and create new files and directories (do not yet
1579 * write their contents)
1581 * 4. walk the directories, fixing the mapping and direntries, and marking
1582 * the handled mappings as not deleted
1584 * 5. commit the contents of the files
1586 * 6. handle deleted files and directories
1590 typedef struct commit_t
{
1593 struct { uint32_t cluster
; } rename
;
1594 struct { int dir_index
; uint32_t modified_offset
; } writeout
;
1595 struct { uint32_t first_cluster
; } new_file
;
1596 struct { uint32_t cluster
; } mkdir
;
1598 /* DELETEs and RMDIRs are handled differently: see handle_deletes() */
1600 ACTION_RENAME
, ACTION_WRITEOUT
, ACTION_NEW_FILE
, ACTION_MKDIR
1604 static void clear_commits(BDRVVVFATState
* s
)
1607 DLOG(fprintf(stderr
, "clear_commits (%d commits)\n", s
->commits
.next
));
1608 for (i
= 0; i
< s
->commits
.next
; i
++) {
1609 commit_t
* commit
= array_get(&(s
->commits
), i
);
1610 assert(commit
->path
|| commit
->action
== ACTION_WRITEOUT
);
1611 if (commit
->action
!= ACTION_WRITEOUT
) {
1612 assert(commit
->path
);
1613 g_free(commit
->path
);
1615 assert(commit
->path
== NULL
);
1617 s
->commits
.next
= 0;
1620 static void schedule_rename(BDRVVVFATState
* s
,
1621 uint32_t cluster
, char* new_path
)
1623 commit_t
* commit
= array_get_next(&(s
->commits
));
1624 commit
->path
= new_path
;
1625 commit
->param
.rename
.cluster
= cluster
;
1626 commit
->action
= ACTION_RENAME
;
1629 static void schedule_writeout(BDRVVVFATState
* s
,
1630 int dir_index
, uint32_t modified_offset
)
1632 commit_t
* commit
= array_get_next(&(s
->commits
));
1633 commit
->path
= NULL
;
1634 commit
->param
.writeout
.dir_index
= dir_index
;
1635 commit
->param
.writeout
.modified_offset
= modified_offset
;
1636 commit
->action
= ACTION_WRITEOUT
;
1639 static void schedule_new_file(BDRVVVFATState
* s
,
1640 char* path
, uint32_t first_cluster
)
1642 commit_t
* commit
= array_get_next(&(s
->commits
));
1643 commit
->path
= path
;
1644 commit
->param
.new_file
.first_cluster
= first_cluster
;
1645 commit
->action
= ACTION_NEW_FILE
;
1648 static void schedule_mkdir(BDRVVVFATState
* s
, uint32_t cluster
, char* path
)
1650 commit_t
* commit
= array_get_next(&(s
->commits
));
1651 commit
->path
= path
;
1652 commit
->param
.mkdir
.cluster
= cluster
;
1653 commit
->action
= ACTION_MKDIR
;
1658 * Since the sequence number is at most 0x3f, and the filename
1659 * length is at most 13 times the sequence number, the maximal
1660 * filename length is 0x3f * 13 bytes.
1662 unsigned char name
[0x3f * 13 + 1];
1663 gunichar2 name2
[0x3f * 13 + 1];
1665 int sequence_number
;
1668 static void lfn_init(long_file_name
* lfn
)
1670 lfn
->sequence_number
= lfn
->len
= 0;
1671 lfn
->checksum
= 0x100;
1674 /* return 0 if parsed successfully, > 0 if no long name, < 0 if error */
1675 static int parse_long_name(long_file_name
* lfn
,
1676 const direntry_t
* direntry
)
1679 const unsigned char* pointer
= (const unsigned char*)direntry
;
1681 if (!is_long_name(direntry
))
1684 if (pointer
[0] & 0x40) {
1685 /* first entry; do some initialization */
1686 lfn
->sequence_number
= pointer
[0] & 0x3f;
1687 lfn
->checksum
= pointer
[13];
1689 lfn
->name
[lfn
->sequence_number
* 13] = 0;
1690 } else if ((pointer
[0] & 0x3f) != --lfn
->sequence_number
) {
1691 /* not the expected sequence number */
1693 } else if (pointer
[13] != lfn
->checksum
) {
1694 /* not the expected checksum */
1696 } else if (pointer
[12] || pointer
[26] || pointer
[27]) {
1697 /* invalid zero fields */
1701 offset
= 13 * (lfn
->sequence_number
- 1);
1702 for (i
= 0, j
= 1; i
< 13; i
++, j
+=2) {
1708 if (pointer
[j
] == 0 && pointer
[j
+ 1] == 0) {
1709 /* end of long file name */
1712 gunichar2 c
= (pointer
[j
+ 1] << 8) + pointer
[j
];
1713 lfn
->name2
[offset
+ i
] = c
;
1716 if (pointer
[0] & 0x40) {
1717 /* first entry; set len */
1718 lfn
->len
= offset
+ i
;
1720 if ((pointer
[0] & 0x3f) == 0x01) {
1721 /* last entry; finalize entry */
1723 gchar
*utf8
= g_utf16_to_utf8(lfn
->name2
, lfn
->len
, NULL
, &olen
, NULL
);
1728 memcpy(lfn
->name
, utf8
, olen
+ 1);
1735 /* returns 0 if successful, >0 if no short_name, and <0 on error */
1736 static int parse_short_name(BDRVVVFATState
* s
,
1737 long_file_name
* lfn
, direntry_t
* direntry
)
1741 if (!is_short_name(direntry
))
1744 for (j
= 7; j
>= 0 && direntry
->name
[j
] == ' '; j
--);
1745 for (i
= 0; i
<= j
; i
++) {
1746 uint8_t c
= direntry
->name
[i
];
1747 if (c
!= to_valid_short_char(c
)) {
1749 } else if (s
->downcase_short_names
) {
1750 lfn
->name
[i
] = qemu_tolower(direntry
->name
[i
]);
1752 lfn
->name
[i
] = direntry
->name
[i
];
1756 for (j
= 2; j
>= 0 && direntry
->name
[8 + j
] == ' '; j
--) {
1759 lfn
->name
[i
++] = '.';
1760 lfn
->name
[i
+ j
+ 1] = '\0';
1761 for (;j
>= 0; j
--) {
1762 uint8_t c
= direntry
->name
[8 + j
];
1763 if (c
!= to_valid_short_char(c
)) {
1765 } else if (s
->downcase_short_names
) {
1766 lfn
->name
[i
+ j
] = qemu_tolower(c
);
1768 lfn
->name
[i
+ j
] = c
;
1772 lfn
->name
[i
+ j
+ 1] = '\0';
1774 if (lfn
->name
[0] == DIR_KANJI_FAKE
) {
1775 lfn
->name
[0] = DIR_KANJI
;
1777 lfn
->len
= strlen((char*)lfn
->name
);
1782 static inline uint32_t modified_fat_get(BDRVVVFATState
* s
,
1783 unsigned int cluster
)
1785 if (cluster
< s
->last_cluster_of_root_directory
) {
1786 if (cluster
+ 1 == s
->last_cluster_of_root_directory
)
1787 return s
->max_fat_value
;
1792 if (s
->fat_type
==32) {
1793 uint32_t* entry
=((uint32_t*)s
->fat2
)+cluster
;
1794 return le32_to_cpu(*entry
);
1795 } else if (s
->fat_type
==16) {
1796 uint16_t* entry
=((uint16_t*)s
->fat2
)+cluster
;
1797 return le16_to_cpu(*entry
);
1799 const uint8_t* x
=s
->fat2
+cluster
*3/2;
1800 return ((x
[0]|(x
[1]<<8))>>(cluster
&1?4:0))&0x0fff;
1804 static inline bool cluster_was_modified(BDRVVVFATState
*s
,
1805 uint32_t cluster_num
)
1807 int was_modified
= 0;
1810 if (s
->qcow
== NULL
) {
1814 for (i
= 0; !was_modified
&& i
< s
->sectors_per_cluster
; i
++) {
1815 was_modified
= bdrv_is_allocated(s
->qcow
->bs
,
1816 (cluster2sector(s
, cluster_num
) +
1817 i
) * BDRV_SECTOR_SIZE
,
1818 BDRV_SECTOR_SIZE
, NULL
);
1822 * Note that this treats failures to learn allocation status the
1823 * same as if an allocation has occurred. It's as safe as
1824 * anything else, given that a failure to learn allocation status
1825 * will probably result in more failures.
1827 return !!was_modified
;
1830 static const char* get_basename(const char* path
)
1832 char* basename
= strrchr(path
, '/');
1833 if (basename
== NULL
)
1836 return basename
+ 1; /* strip '/' */
1840 * The array s->used_clusters holds the states of the clusters. If it is
1841 * part of a file, it has bit 2 set, in case of a directory, bit 1. If it
1842 * was modified, bit 3 is set.
1843 * If any cluster is allocated, but not part of a file or directory, this
1844 * driver refuses to commit.
1847 USED_DIRECTORY
= 1, USED_FILE
= 2, USED_ANY
= 3, USED_ALLOCATED
= 4
1851 * get_cluster_count_for_direntry() not only determines how many clusters
1852 * are occupied by direntry, but also if it was renamed or modified.
1854 * A file is thought to be renamed *only* if there already was a file with
1855 * exactly the same first cluster, but a different name.
1857 * Further, the files/directories handled by this function are
1858 * assumed to be *not* deleted (and *only* those).
1860 static uint32_t get_cluster_count_for_direntry(BDRVVVFATState
* s
,
1861 direntry_t
* direntry
, const char* path
)
1864 * This is a little bit tricky:
1865 * IF the guest OS just inserts a cluster into the file chain,
1866 * and leaves the rest alone, (i.e. the original file had clusters
1867 * 15 -> 16, but now has 15 -> 32 -> 16), then the following happens:
1869 * - do_commit will write the cluster into the file at the given
1872 * - the cluster which is overwritten should be moved to a later
1873 * position in the file.
1875 * I am not aware that any OS does something as braindead, but this
1876 * situation could happen anyway when not committing for a long time.
1877 * Just to be sure that this does not bite us, detect it, and copy the
1878 * contents of the clusters to-be-overwritten into the qcow.
1881 int was_modified
= 0;
1884 uint32_t cluster_num
= begin_of_direntry(direntry
);
1885 uint32_t offset
= 0;
1886 int first_mapping_index
= -1;
1887 mapping_t
* mapping
= NULL
;
1888 const char* basename2
= NULL
;
1890 vvfat_close_current_file(s
);
1892 /* the root directory */
1893 if (cluster_num
== 0)
1898 basename2
= get_basename(path
);
1900 mapping
= find_mapping_for_cluster(s
, cluster_num
);
1903 const char* basename
;
1905 assert(mapping
->mode
& MODE_DELETED
);
1906 mapping
->mode
&= ~MODE_DELETED
;
1908 basename
= get_basename(mapping
->path
);
1910 assert(mapping
->mode
& MODE_NORMAL
);
1913 if (strcmp(basename
, basename2
))
1914 schedule_rename(s
, cluster_num
, g_strdup(path
));
1915 } else if (is_file(direntry
))
1917 schedule_new_file(s
, g_strdup(path
), cluster_num
);
1926 if (!copy_it
&& cluster_was_modified(s
, cluster_num
)) {
1927 if (mapping
== NULL
||
1928 mapping
->begin
> cluster_num
||
1929 mapping
->end
<= cluster_num
)
1930 mapping
= find_mapping_for_cluster(s
, cluster_num
);
1934 (mapping
->mode
& MODE_DIRECTORY
) == 0) {
1936 /* was modified in qcow */
1937 if (offset
!= mapping
->info
.file
.offset
+ s
->cluster_size
1938 * (cluster_num
- mapping
->begin
)) {
1939 /* offset of this cluster in file chain has changed */
1942 } else if (offset
== 0) {
1943 const char* basename
= get_basename(mapping
->path
);
1945 if (strcmp(basename
, basename2
))
1947 first_mapping_index
= array_index(&(s
->mapping
), mapping
);
1950 if (mapping
->first_mapping_index
!= first_mapping_index
1951 && mapping
->info
.file
.offset
> 0) {
1956 /* need to write out? */
1957 if (!was_modified
&& is_file(direntry
)) {
1959 schedule_writeout(s
, mapping
->dir_index
, offset
);
1967 * This is horribly inefficient, but that is okay, since
1968 * it is rarely executed, if at all.
1970 int64_t offset
= cluster2sector(s
, cluster_num
);
1972 vvfat_close_current_file(s
);
1973 for (i
= 0; i
< s
->sectors_per_cluster
; i
++) {
1976 res
= bdrv_is_allocated(s
->qcow
->bs
,
1977 (offset
+ i
) * BDRV_SECTOR_SIZE
,
1978 BDRV_SECTOR_SIZE
, NULL
);
1983 res
= vvfat_read(s
->bs
, offset
, s
->cluster_buffer
, 1);
1987 res
= bdrv_pwrite(s
->qcow
, offset
* BDRV_SECTOR_SIZE
,
1988 s
->cluster_buffer
, BDRV_SECTOR_SIZE
);
1998 if (s
->used_clusters
[cluster_num
] & USED_ANY
)
2000 s
->used_clusters
[cluster_num
] = USED_FILE
;
2002 cluster_num
= modified_fat_get(s
, cluster_num
);
2004 if (fat_eof(s
, cluster_num
))
2006 else if (cluster_num
< 2 || cluster_num
> s
->max_fat_value
- 16)
2009 offset
+= s
->cluster_size
;
2014 * This function looks at the modified data (qcow).
2015 * It returns 0 upon inconsistency or error, and the number of clusters
2016 * used by the directory, its subdirectories and their files.
2018 static int check_directory_consistency(BDRVVVFATState
*s
,
2019 int cluster_num
, const char* path
)
2022 unsigned char* cluster
= g_malloc(s
->cluster_size
);
2023 direntry_t
* direntries
= (direntry_t
*)cluster
;
2024 mapping_t
* mapping
= find_mapping_for_cluster(s
, cluster_num
);
2027 int path_len
= strlen(path
);
2028 char path2
[PATH_MAX
+ 1];
2030 assert(path_len
< PATH_MAX
); /* len was tested before! */
2031 pstrcpy(path2
, sizeof(path2
), path
);
2032 path2
[path_len
] = '/';
2033 path2
[path_len
+ 1] = '\0';
2036 const char* basename
= get_basename(mapping
->path
);
2037 const char* basename2
= get_basename(path
);
2039 assert(mapping
->mode
& MODE_DIRECTORY
);
2041 assert(mapping
->mode
& MODE_DELETED
);
2042 mapping
->mode
&= ~MODE_DELETED
;
2044 if (strcmp(basename
, basename2
))
2045 schedule_rename(s
, cluster_num
, g_strdup(path
));
2048 schedule_mkdir(s
, cluster_num
, g_strdup(path
));
2057 if (s
->used_clusters
[cluster_num
] & USED_ANY
) {
2058 fprintf(stderr
, "cluster %d used more than once\n", (int)cluster_num
);
2061 s
->used_clusters
[cluster_num
] = USED_DIRECTORY
;
2063 DLOG(fprintf(stderr
, "read cluster %d (sector %d)\n", (int)cluster_num
, (int)cluster2sector(s
, cluster_num
)));
2064 subret
= vvfat_read(s
->bs
, cluster2sector(s
, cluster_num
), cluster
,
2065 s
->sectors_per_cluster
);
2067 fprintf(stderr
, "Error fetching direntries\n");
2073 for (i
= 0; i
< 0x10 * s
->sectors_per_cluster
; i
++) {
2074 int cluster_count
= 0;
2076 DLOG(fprintf(stderr
, "check direntry %d:\n", i
); print_direntry(direntries
+ i
));
2077 if (is_volume_label(direntries
+ i
) || is_dot(direntries
+ i
) ||
2078 is_free(direntries
+ i
))
2081 subret
= parse_long_name(&lfn
, direntries
+ i
);
2083 fprintf(stderr
, "Error in long name\n");
2086 if (subret
== 0 || is_free(direntries
+ i
))
2089 if (fat_chksum(direntries
+i
) != lfn
.checksum
) {
2090 subret
= parse_short_name(s
, &lfn
, direntries
+ i
);
2092 fprintf(stderr
, "Error in short name (%d)\n", subret
);
2095 if (subret
> 0 || !strcmp((char*)lfn
.name
, ".")
2096 || !strcmp((char*)lfn
.name
, ".."))
2099 lfn
.checksum
= 0x100; /* cannot use long name twice */
2101 if (path_len
+ 1 + lfn
.len
>= PATH_MAX
) {
2102 fprintf(stderr
, "Name too long: %s/%s\n", path
, lfn
.name
);
2105 pstrcpy(path2
+ path_len
+ 1, sizeof(path2
) - path_len
- 1,
2108 if (is_directory(direntries
+ i
)) {
2109 if (begin_of_direntry(direntries
+ i
) == 0) {
2110 DLOG(fprintf(stderr
, "invalid begin for directory: %s\n", path2
); print_direntry(direntries
+ i
));
2113 cluster_count
= check_directory_consistency(s
,
2114 begin_of_direntry(direntries
+ i
), path2
);
2115 if (cluster_count
== 0) {
2116 DLOG(fprintf(stderr
, "problem in directory %s:\n", path2
); print_direntry(direntries
+ i
));
2119 } else if (is_file(direntries
+ i
)) {
2120 /* check file size with FAT */
2121 cluster_count
= get_cluster_count_for_direntry(s
, direntries
+ i
, path2
);
2122 if (cluster_count
!=
2123 DIV_ROUND_UP(le32_to_cpu(direntries
[i
].size
), s
->cluster_size
)) {
2124 DLOG(fprintf(stderr
, "Cluster count mismatch\n"));
2128 abort(); /* cluster_count = 0; */
2130 ret
+= cluster_count
;
2133 cluster_num
= modified_fat_get(s
, cluster_num
);
2134 } while(!fat_eof(s
, cluster_num
));
2140 /* returns 1 on success */
2141 static int is_consistent(BDRVVVFATState
* s
)
2144 int used_clusters_count
= 0;
2148 * - get modified FAT
2149 * - compare the two FATs (TODO)
2150 * - get buffer for marking used clusters
2151 * - recurse direntries from root (using bs->bdrv_read to make
2152 * sure to get the new data)
2153 * - check that the FAT agrees with the size
2154 * - count the number of clusters occupied by this directory and
2156 * - check that the cumulative used cluster count agrees with the
2158 * - if all is fine, return number of used clusters
2160 if (s
->fat2
== NULL
) {
2161 int size
= 0x200 * s
->sectors_per_fat
;
2162 s
->fat2
= g_malloc(size
);
2163 memcpy(s
->fat2
, s
->fat
.pointer
, size
);
2165 check
= vvfat_read(s
->bs
,
2166 s
->offset_to_fat
, s
->fat2
, s
->sectors_per_fat
);
2168 fprintf(stderr
, "Could not copy fat\n");
2171 assert (s
->used_clusters
);
2172 for (i
= 0; i
< sector2cluster(s
, s
->sector_count
); i
++)
2173 s
->used_clusters
[i
] &= ~USED_ANY
;
2177 /* mark every mapped file/directory as deleted.
2178 * (check_directory_consistency() will unmark those still present). */
2180 for (i
= 0; i
< s
->mapping
.next
; i
++) {
2181 mapping_t
* mapping
= array_get(&(s
->mapping
), i
);
2182 if (mapping
->first_mapping_index
< 0)
2183 mapping
->mode
|= MODE_DELETED
;
2186 used_clusters_count
= check_directory_consistency(s
, 0, s
->path
);
2187 if (used_clusters_count
<= 0) {
2188 DLOG(fprintf(stderr
, "problem in directory\n"));
2192 check
= s
->last_cluster_of_root_directory
;
2193 for (i
= check
; i
< sector2cluster(s
, s
->sector_count
); i
++) {
2194 if (modified_fat_get(s
, i
)) {
2195 if(!s
->used_clusters
[i
]) {
2196 DLOG(fprintf(stderr
, "FAT was modified (%d), but cluster is not used?\n", i
));
2202 if (s
->used_clusters
[i
] == USED_ALLOCATED
) {
2203 /* allocated, but not used... */
2204 DLOG(fprintf(stderr
, "unused, modified cluster: %d\n", i
));
2209 if (check
!= used_clusters_count
)
2212 return used_clusters_count
;
2215 static inline void adjust_mapping_indices(BDRVVVFATState
* s
,
2216 int offset
, int adjust
)
2220 for (i
= 0; i
< s
->mapping
.next
; i
++) {
2221 mapping_t
* mapping
= array_get(&(s
->mapping
), i
);
2223 #define ADJUST_MAPPING_INDEX(name) \
2224 if (mapping->name >= offset) \
2225 mapping->name += adjust
2227 ADJUST_MAPPING_INDEX(first_mapping_index
);
2228 if (mapping
->mode
& MODE_DIRECTORY
)
2229 ADJUST_MAPPING_INDEX(info
.dir
.parent_mapping_index
);
2233 /* insert or update mapping */
2234 static mapping_t
* insert_mapping(BDRVVVFATState
* s
,
2235 uint32_t begin
, uint32_t end
)
2238 * - find mapping where mapping->begin >= begin,
2239 * - if mapping->begin > begin: insert
2240 * - adjust all references to mappings!
2244 int index
= find_mapping_for_cluster_aux(s
, begin
, 0, s
->mapping
.next
);
2245 mapping_t
* mapping
= NULL
;
2246 mapping_t
* first_mapping
= array_get(&(s
->mapping
), 0);
2248 if (index
< s
->mapping
.next
&& (mapping
= array_get(&(s
->mapping
), index
))
2249 && mapping
->begin
< begin
) {
2250 mapping
->end
= begin
;
2252 mapping
= array_get(&(s
->mapping
), index
);
2254 if (index
>= s
->mapping
.next
|| mapping
->begin
> begin
) {
2255 mapping
= array_insert(&(s
->mapping
), index
, 1);
2256 mapping
->path
= NULL
;
2257 adjust_mapping_indices(s
, index
, +1);
2260 mapping
->begin
= begin
;
2263 DLOG(mapping_t
* next_mapping
;
2264 assert(index
+ 1 >= s
->mapping
.next
||
2265 ((next_mapping
= array_get(&(s
->mapping
), index
+ 1)) &&
2266 next_mapping
->begin
>= end
)));
2268 if (s
->current_mapping
&& first_mapping
!= (mapping_t
*)s
->mapping
.pointer
)
2269 s
->current_mapping
= array_get(&(s
->mapping
),
2270 s
->current_mapping
- first_mapping
);
2275 static int remove_mapping(BDRVVVFATState
* s
, int mapping_index
)
2277 mapping_t
* mapping
= array_get(&(s
->mapping
), mapping_index
);
2278 mapping_t
* first_mapping
= array_get(&(s
->mapping
), 0);
2281 if (mapping
->first_mapping_index
< 0) {
2282 g_free(mapping
->path
);
2285 /* remove from s->mapping */
2286 array_remove(&(s
->mapping
), mapping_index
);
2288 /* adjust all references to mappings */
2289 adjust_mapping_indices(s
, mapping_index
, -1);
2291 if (s
->current_mapping
&& first_mapping
!= (mapping_t
*)s
->mapping
.pointer
)
2292 s
->current_mapping
= array_get(&(s
->mapping
),
2293 s
->current_mapping
- first_mapping
);
2298 static void adjust_dirindices(BDRVVVFATState
* s
, int offset
, int adjust
)
2301 for (i
= 0; i
< s
->mapping
.next
; i
++) {
2302 mapping_t
* mapping
= array_get(&(s
->mapping
), i
);
2303 if (mapping
->dir_index
>= offset
)
2304 mapping
->dir_index
+= adjust
;
2305 if ((mapping
->mode
& MODE_DIRECTORY
) &&
2306 mapping
->info
.dir
.first_dir_index
>= offset
)
2307 mapping
->info
.dir
.first_dir_index
+= adjust
;
2311 static direntry_t
* insert_direntries(BDRVVVFATState
* s
,
2312 int dir_index
, int count
)
2315 * make room in s->directory,
2318 direntry_t
* result
= array_insert(&(s
->directory
), dir_index
, count
);
2321 adjust_dirindices(s
, dir_index
, count
);
2325 static int remove_direntries(BDRVVVFATState
* s
, int dir_index
, int count
)
2327 int ret
= array_remove_slice(&(s
->directory
), dir_index
, count
);
2330 adjust_dirindices(s
, dir_index
, -count
);
2335 * Adapt the mappings of the cluster chain starting at first cluster
2336 * (i.e. if a file starts at first_cluster, the chain is followed according
2337 * to the modified fat, and the corresponding entries in s->mapping are
2340 static int commit_mappings(BDRVVVFATState
* s
,
2341 uint32_t first_cluster
, int dir_index
)
2343 mapping_t
* mapping
= find_mapping_for_cluster(s
, first_cluster
);
2344 direntry_t
* direntry
= array_get(&(s
->directory
), dir_index
);
2345 uint32_t cluster
= first_cluster
;
2347 vvfat_close_current_file(s
);
2350 assert(mapping
->begin
== first_cluster
);
2351 mapping
->first_mapping_index
= -1;
2352 mapping
->dir_index
= dir_index
;
2353 mapping
->mode
= (dir_index
<= 0 || is_directory(direntry
)) ?
2354 MODE_DIRECTORY
: MODE_NORMAL
;
2356 while (!fat_eof(s
, cluster
)) {
2359 for (c
= cluster
, c1
= modified_fat_get(s
, c
); c
+ 1 == c1
;
2360 c
= c1
, c1
= modified_fat_get(s
, c1
));
2363 if (c
> mapping
->end
) {
2364 int index
= array_index(&(s
->mapping
), mapping
);
2365 int i
, max_i
= s
->mapping
.next
- index
;
2366 for (i
= 1; i
< max_i
&& mapping
[i
].begin
< c
; i
++);
2368 remove_mapping(s
, index
+ 1);
2370 assert(mapping
== array_get(&(s
->mapping
), s
->mapping
.next
- 1)
2371 || mapping
[1].begin
>= c
);
2374 if (!fat_eof(s
, c1
)) {
2375 int i
= find_mapping_for_cluster_aux(s
, c1
, 0, s
->mapping
.next
);
2376 mapping_t
* next_mapping
= i
>= s
->mapping
.next
? NULL
:
2377 array_get(&(s
->mapping
), i
);
2379 if (next_mapping
== NULL
|| next_mapping
->begin
> c1
) {
2380 int i1
= array_index(&(s
->mapping
), mapping
);
2382 next_mapping
= insert_mapping(s
, c1
, c1
+1);
2386 mapping
= array_get(&(s
->mapping
), i1
);
2389 next_mapping
->dir_index
= mapping
->dir_index
;
2390 next_mapping
->first_mapping_index
=
2391 mapping
->first_mapping_index
< 0 ?
2392 array_index(&(s
->mapping
), mapping
) :
2393 mapping
->first_mapping_index
;
2394 next_mapping
->path
= mapping
->path
;
2395 next_mapping
->mode
= mapping
->mode
;
2396 next_mapping
->read_only
= mapping
->read_only
;
2397 if (mapping
->mode
& MODE_DIRECTORY
) {
2398 next_mapping
->info
.dir
.parent_mapping_index
=
2399 mapping
->info
.dir
.parent_mapping_index
;
2400 next_mapping
->info
.dir
.first_dir_index
=
2401 mapping
->info
.dir
.first_dir_index
+
2402 0x10 * s
->sectors_per_cluster
*
2403 (mapping
->end
- mapping
->begin
);
2405 next_mapping
->info
.file
.offset
= mapping
->info
.file
.offset
+
2406 mapping
->end
- mapping
->begin
;
2408 mapping
= next_mapping
;
2417 static int commit_direntries(BDRVVVFATState
* s
,
2418 int dir_index
, int parent_mapping_index
)
2420 direntry_t
* direntry
= array_get(&(s
->directory
), dir_index
);
2421 uint32_t first_cluster
= dir_index
== 0 ? 0 : begin_of_direntry(direntry
);
2422 mapping_t
* mapping
= find_mapping_for_cluster(s
, first_cluster
);
2423 int factor
= 0x10 * s
->sectors_per_cluster
;
2424 int old_cluster_count
, new_cluster_count
;
2425 int current_dir_index
;
2426 int first_dir_index
;
2432 assert(mapping
->begin
== first_cluster
);
2433 assert(mapping
->info
.dir
.first_dir_index
< s
->directory
.next
);
2434 assert(mapping
->mode
& MODE_DIRECTORY
);
2435 assert(dir_index
== 0 || is_directory(direntry
));
2437 DLOG(fprintf(stderr
, "commit_direntries for %s, parent_mapping_index %d\n",
2438 mapping
->path
, parent_mapping_index
));
2440 current_dir_index
= mapping
->info
.dir
.first_dir_index
;
2441 first_dir_index
= current_dir_index
;
2442 mapping
->info
.dir
.parent_mapping_index
= parent_mapping_index
;
2444 if (first_cluster
== 0) {
2445 old_cluster_count
= new_cluster_count
=
2446 s
->last_cluster_of_root_directory
;
2448 for (old_cluster_count
= 0, c
= first_cluster
; !fat_eof(s
, c
);
2450 old_cluster_count
++;
2452 for (new_cluster_count
= 0, c
= first_cluster
; !fat_eof(s
, c
);
2453 c
= modified_fat_get(s
, c
))
2454 new_cluster_count
++;
2457 if (new_cluster_count
> old_cluster_count
) {
2458 if (insert_direntries(s
,
2459 current_dir_index
+ factor
* old_cluster_count
,
2460 factor
* (new_cluster_count
- old_cluster_count
)) == NULL
)
2462 } else if (new_cluster_count
< old_cluster_count
)
2463 remove_direntries(s
,
2464 current_dir_index
+ factor
* new_cluster_count
,
2465 factor
* (old_cluster_count
- new_cluster_count
));
2467 for (c
= first_cluster
; !fat_eof(s
, c
); c
= modified_fat_get(s
, c
)) {
2468 direntry_t
*first_direntry
;
2469 void* direntry
= array_get(&(s
->directory
), current_dir_index
);
2470 int ret
= vvfat_read(s
->bs
, cluster2sector(s
, c
), direntry
,
2471 s
->sectors_per_cluster
);
2475 /* The first directory entry on the filesystem is the volume name */
2476 first_direntry
= (direntry_t
*) s
->directory
.pointer
;
2477 assert(!memcmp(first_direntry
->name
, s
->volume_label
, 11));
2479 current_dir_index
+= factor
;
2482 ret
= commit_mappings(s
, first_cluster
, dir_index
);
2487 for (i
= 0; i
< factor
* new_cluster_count
; i
++) {
2488 direntry
= array_get(&(s
->directory
), first_dir_index
+ i
);
2489 if (is_directory(direntry
) && !is_dot(direntry
)) {
2490 mapping
= find_mapping_for_cluster(s
, first_cluster
);
2491 if (mapping
== NULL
) {
2494 assert(mapping
->mode
& MODE_DIRECTORY
);
2495 ret
= commit_direntries(s
, first_dir_index
+ i
,
2496 array_index(&(s
->mapping
), mapping
));
2505 /* commit one file (adjust contents, adjust mapping),
2506 return first_mapping_index */
2507 static int commit_one_file(BDRVVVFATState
* s
,
2508 int dir_index
, uint32_t offset
)
2510 direntry_t
* direntry
= array_get(&(s
->directory
), dir_index
);
2511 uint32_t c
= begin_of_direntry(direntry
);
2512 uint32_t first_cluster
= c
;
2513 mapping_t
* mapping
= find_mapping_for_cluster(s
, c
);
2514 uint32_t size
= filesize_of_direntry(direntry
);
2519 assert(offset
< size
);
2520 assert((offset
% s
->cluster_size
) == 0);
2522 if (mapping
== NULL
) {
2526 for (i
= s
->cluster_size
; i
< offset
; i
+= s
->cluster_size
)
2527 c
= modified_fat_get(s
, c
);
2529 fd
= qemu_open(mapping
->path
, O_RDWR
| O_CREAT
| O_BINARY
, 0666);
2531 fprintf(stderr
, "Could not open %s... (%s, %d)\n", mapping
->path
,
2532 strerror(errno
), errno
);
2536 if (lseek(fd
, offset
, SEEK_SET
) != offset
) {
2542 cluster
= g_malloc(s
->cluster_size
);
2544 while (offset
< size
) {
2546 int rest_size
= (size
- offset
> s
->cluster_size
?
2547 s
->cluster_size
: size
- offset
);
2550 c1
= modified_fat_get(s
, c
);
2552 assert((size
- offset
== 0 && fat_eof(s
, c
)) ||
2553 (size
> offset
&& c
>=2 && !fat_eof(s
, c
)));
2555 ret
= vvfat_read(s
->bs
, cluster2sector(s
, c
),
2556 (uint8_t*)cluster
, DIV_ROUND_UP(rest_size
, 0x200));
2564 if (write(fd
, cluster
, rest_size
) < 0) {
2570 offset
+= rest_size
;
2574 if (ftruncate(fd
, size
)) {
2575 perror("ftruncate()");
2583 return commit_mappings(s
, first_cluster
, dir_index
);
2587 /* test, if all mappings point to valid direntries */
2588 static void check1(BDRVVVFATState
* s
)
2591 for (i
= 0; i
< s
->mapping
.next
; i
++) {
2592 mapping_t
* mapping
= array_get(&(s
->mapping
), i
);
2593 if (mapping
->mode
& MODE_DELETED
) {
2594 fprintf(stderr
, "deleted\n");
2597 assert(mapping
->dir_index
< s
->directory
.next
);
2598 direntry_t
* direntry
= array_get(&(s
->directory
), mapping
->dir_index
);
2599 assert(mapping
->begin
== begin_of_direntry(direntry
) || mapping
->first_mapping_index
>= 0);
2600 if (mapping
->mode
& MODE_DIRECTORY
) {
2601 assert(mapping
->info
.dir
.first_dir_index
+ 0x10 * s
->sectors_per_cluster
* (mapping
->end
- mapping
->begin
) <= s
->directory
.next
);
2602 assert((mapping
->info
.dir
.first_dir_index
% (0x10 * s
->sectors_per_cluster
)) == 0);
2607 /* test, if all direntries have mappings */
2608 static void check2(BDRVVVFATState
* s
)
2611 int first_mapping
= -1;
2613 for (i
= 0; i
< s
->directory
.next
; i
++) {
2614 direntry_t
* direntry
= array_get(&(s
->directory
), i
);
2616 if (is_short_name(direntry
) && begin_of_direntry(direntry
)) {
2617 mapping_t
* mapping
= find_mapping_for_cluster(s
, begin_of_direntry(direntry
));
2619 assert(mapping
->dir_index
== i
|| is_dot(direntry
));
2620 assert(mapping
->begin
== begin_of_direntry(direntry
) || is_dot(direntry
));
2623 if ((i
% (0x10 * s
->sectors_per_cluster
)) == 0) {
2627 for (j
= 0; j
< s
->mapping
.next
; j
++) {
2628 mapping_t
* mapping
= array_get(&(s
->mapping
), j
);
2629 if (mapping
->mode
& MODE_DELETED
)
2631 if (mapping
->mode
& MODE_DIRECTORY
) {
2632 if (mapping
->info
.dir
.first_dir_index
<= i
&& mapping
->info
.dir
.first_dir_index
+ 0x10 * s
->sectors_per_cluster
> i
) {
2633 assert(++count
== 1);
2634 if (mapping
->first_mapping_index
== -1)
2635 first_mapping
= array_index(&(s
->mapping
), mapping
);
2637 assert(first_mapping
== mapping
->first_mapping_index
);
2638 if (mapping
->info
.dir
.parent_mapping_index
< 0)
2641 mapping_t
* parent
= array_get(&(s
->mapping
), mapping
->info
.dir
.parent_mapping_index
);
2642 assert(parent
->mode
& MODE_DIRECTORY
);
2643 assert(parent
->info
.dir
.first_dir_index
< mapping
->info
.dir
.first_dir_index
);
2655 static int handle_renames_and_mkdirs(BDRVVVFATState
* s
)
2660 fprintf(stderr
, "handle_renames\n");
2661 for (i
= 0; i
< s
->commits
.next
; i
++) {
2662 commit_t
* commit
= array_get(&(s
->commits
), i
);
2663 fprintf(stderr
, "%d, %s (%d, %d)\n", i
, commit
->path
? commit
->path
: "(null)", commit
->param
.rename
.cluster
, commit
->action
);
2667 for (i
= 0; i
< s
->commits
.next
;) {
2668 commit_t
* commit
= array_get(&(s
->commits
), i
);
2669 if (commit
->action
== ACTION_RENAME
) {
2670 mapping_t
* mapping
= find_mapping_for_cluster(s
,
2671 commit
->param
.rename
.cluster
);
2674 if (mapping
== NULL
) {
2677 old_path
= mapping
->path
;
2678 assert(commit
->path
);
2679 mapping
->path
= commit
->path
;
2680 if (rename(old_path
, mapping
->path
))
2683 if (mapping
->mode
& MODE_DIRECTORY
) {
2684 int l1
= strlen(mapping
->path
);
2685 int l2
= strlen(old_path
);
2687 direntry_t
* direntry
= array_get(&(s
->directory
),
2688 mapping
->info
.dir
.first_dir_index
);
2689 uint32_t c
= mapping
->begin
;
2693 while (!fat_eof(s
, c
)) {
2695 direntry_t
* d
= direntry
+ i
;
2697 if (is_file(d
) || (is_directory(d
) && !is_dot(d
))) {
2700 mapping_t
* m
= find_mapping_for_cluster(s
,
2701 begin_of_direntry(d
));
2705 l
= strlen(m
->path
);
2706 new_path
= g_malloc(l
+ diff
+ 1);
2708 assert(!strncmp(m
->path
, mapping
->path
, l2
));
2710 pstrcpy(new_path
, l
+ diff
+ 1, mapping
->path
);
2711 pstrcpy(new_path
+ l1
, l
+ diff
+ 1 - l1
,
2714 schedule_rename(s
, m
->begin
, new_path
);
2717 } while((i
% (0x10 * s
->sectors_per_cluster
)) != 0);
2723 array_remove(&(s
->commits
), i
);
2725 } else if (commit
->action
== ACTION_MKDIR
) {
2727 int j
, parent_path_len
;
2730 if (mkdir(commit
->path
))
2733 if (mkdir(commit
->path
, 0755))
2737 mapping
= insert_mapping(s
, commit
->param
.mkdir
.cluster
,
2738 commit
->param
.mkdir
.cluster
+ 1);
2739 if (mapping
== NULL
)
2742 mapping
->mode
= MODE_DIRECTORY
;
2743 mapping
->read_only
= 0;
2744 mapping
->path
= commit
->path
;
2745 j
= s
->directory
.next
;
2747 insert_direntries(s
, s
->directory
.next
,
2748 0x10 * s
->sectors_per_cluster
);
2749 mapping
->info
.dir
.first_dir_index
= j
;
2751 parent_path_len
= strlen(commit
->path
)
2752 - strlen(get_basename(commit
->path
)) - 1;
2753 for (j
= 0; j
< s
->mapping
.next
; j
++) {
2754 mapping_t
* m
= array_get(&(s
->mapping
), j
);
2755 if (m
->first_mapping_index
< 0 && m
!= mapping
&&
2756 !strncmp(m
->path
, mapping
->path
, parent_path_len
) &&
2757 strlen(m
->path
) == parent_path_len
)
2760 assert(j
< s
->mapping
.next
);
2761 mapping
->info
.dir
.parent_mapping_index
= j
;
2763 array_remove(&(s
->commits
), i
);
2773 * TODO: make sure that the short name is not matching *another* file
2775 static int handle_commits(BDRVVVFATState
* s
)
2779 vvfat_close_current_file(s
);
2781 for (i
= 0; !fail
&& i
< s
->commits
.next
; i
++) {
2782 commit_t
* commit
= array_get(&(s
->commits
), i
);
2783 switch(commit
->action
) {
2784 case ACTION_RENAME
: case ACTION_MKDIR
:
2788 case ACTION_WRITEOUT
: {
2790 /* these variables are only used by assert() below */
2791 direntry_t
* entry
= array_get(&(s
->directory
),
2792 commit
->param
.writeout
.dir_index
);
2793 uint32_t begin
= begin_of_direntry(entry
);
2794 mapping_t
* mapping
= find_mapping_for_cluster(s
, begin
);
2798 assert(mapping
->begin
== begin
);
2799 assert(commit
->path
== NULL
);
2801 if (commit_one_file(s
, commit
->param
.writeout
.dir_index
,
2802 commit
->param
.writeout
.modified_offset
))
2807 case ACTION_NEW_FILE
: {
2808 int begin
= commit
->param
.new_file
.first_cluster
;
2809 mapping_t
* mapping
= find_mapping_for_cluster(s
, begin
);
2814 for (i
= 0; i
< s
->directory
.next
; i
++) {
2815 entry
= array_get(&(s
->directory
), i
);
2816 if (is_file(entry
) && begin_of_direntry(entry
) == begin
)
2820 if (i
>= s
->directory
.next
) {
2825 /* make sure there exists an initial mapping */
2826 if (mapping
&& mapping
->begin
!= begin
) {
2827 mapping
->end
= begin
;
2830 if (mapping
== NULL
) {
2831 mapping
= insert_mapping(s
, begin
, begin
+1);
2833 /* most members will be fixed in commit_mappings() */
2834 assert(commit
->path
);
2835 mapping
->path
= commit
->path
;
2836 mapping
->read_only
= 0;
2837 mapping
->mode
= MODE_NORMAL
;
2838 mapping
->info
.file
.offset
= 0;
2840 if (commit_one_file(s
, i
, 0))
2849 if (i
> 0 && array_remove_slice(&(s
->commits
), 0, i
))
2854 static int handle_deletes(BDRVVVFATState
* s
)
2856 int i
, deferred
= 1, deleted
= 1;
2858 /* delete files corresponding to mappings marked as deleted */
2859 /* handle DELETEs and unused mappings (modified_fat_get(s, mapping->begin) == 0) */
2860 while (deferred
&& deleted
) {
2864 for (i
= 1; i
< s
->mapping
.next
; i
++) {
2865 mapping_t
* mapping
= array_get(&(s
->mapping
), i
);
2866 if (mapping
->mode
& MODE_DELETED
) {
2867 direntry_t
* entry
= array_get(&(s
->directory
),
2868 mapping
->dir_index
);
2870 if (is_free(entry
)) {
2871 /* remove file/directory */
2872 if (mapping
->mode
& MODE_DIRECTORY
) {
2873 int j
, next_dir_index
= s
->directory
.next
,
2874 first_dir_index
= mapping
->info
.dir
.first_dir_index
;
2876 if (rmdir(mapping
->path
) < 0) {
2877 if (errno
== ENOTEMPTY
) {
2884 for (j
= 1; j
< s
->mapping
.next
; j
++) {
2885 mapping_t
* m
= array_get(&(s
->mapping
), j
);
2886 if (m
->mode
& MODE_DIRECTORY
&&
2887 m
->info
.dir
.first_dir_index
>
2889 m
->info
.dir
.first_dir_index
<
2892 m
->info
.dir
.first_dir_index
;
2894 remove_direntries(s
, first_dir_index
,
2895 next_dir_index
- first_dir_index
);
2900 if (unlink(mapping
->path
))
2904 DLOG(fprintf(stderr
, "DELETE (%d)\n", i
); print_mapping(mapping
); print_direntry(entry
));
2905 remove_mapping(s
, i
);
2914 * synchronize mapping with new state:
2916 * - copy FAT (with bdrv_read)
2917 * - mark all filenames corresponding to mappings as deleted
2918 * - recurse direntries from root (using bs->bdrv_read)
2919 * - delete files corresponding to mappings marked as deleted
2921 static int do_commit(BDRVVVFATState
* s
)
2925 /* the real meat are the commits. Nothing to do? Move along! */
2926 if (s
->commits
.next
== 0)
2929 vvfat_close_current_file(s
);
2931 ret
= handle_renames_and_mkdirs(s
);
2933 fprintf(stderr
, "Error handling renames (%d)\n", ret
);
2938 /* copy FAT (with bdrv_read) */
2939 memcpy(s
->fat
.pointer
, s
->fat2
, 0x200 * s
->sectors_per_fat
);
2941 /* recurse direntries from root (using bs->bdrv_read) */
2942 ret
= commit_direntries(s
, 0, -1);
2944 fprintf(stderr
, "Fatal: error while committing (%d)\n", ret
);
2949 ret
= handle_commits(s
);
2951 fprintf(stderr
, "Error handling commits (%d)\n", ret
);
2956 ret
= handle_deletes(s
);
2958 fprintf(stderr
, "Error deleting\n");
2963 if (s
->qcow
->bs
->drv
&& s
->qcow
->bs
->drv
->bdrv_make_empty
) {
2964 s
->qcow
->bs
->drv
->bdrv_make_empty(s
->qcow
->bs
);
2967 memset(s
->used_clusters
, 0, sector2cluster(s
, s
->sector_count
));
2973 static int try_commit(BDRVVVFATState
* s
)
2975 vvfat_close_current_file(s
);
2977 if(!is_consistent(s
))
2979 return do_commit(s
);
2982 static int vvfat_write(BlockDriverState
*bs
, int64_t sector_num
,
2983 const uint8_t *buf
, int nb_sectors
)
2985 BDRVVVFATState
*s
= bs
->opaque
;
2990 /* Check if we're operating in read-only mode */
2991 if (s
->qcow
== NULL
) {
2995 vvfat_close_current_file(s
);
2998 * Some sanity checks:
2999 * - do not allow writing to the boot sector
3002 if (sector_num
< s
->offset_to_fat
)
3005 for (i
= sector2cluster(s
, sector_num
);
3006 i
<= sector2cluster(s
, sector_num
+ nb_sectors
- 1);) {
3007 mapping_t
* mapping
= find_mapping_for_cluster(s
, i
);
3009 if (mapping
->read_only
) {
3010 fprintf(stderr
, "Tried to write to write-protected file %s\n",
3015 if (mapping
->mode
& MODE_DIRECTORY
) {
3016 int begin
= cluster2sector(s
, i
);
3017 int end
= begin
+ s
->sectors_per_cluster
, k
;
3019 const direntry_t
* direntries
;
3024 if (begin
< sector_num
)
3026 if (end
> sector_num
+ nb_sectors
)
3027 end
= sector_num
+ nb_sectors
;
3028 dir_index
= mapping
->dir_index
+
3029 0x10 * (begin
- mapping
->begin
* s
->sectors_per_cluster
);
3030 direntries
= (direntry_t
*)(buf
+ 0x200 * (begin
- sector_num
));
3032 for (k
= 0; k
< (end
- begin
) * 0x10; k
++) {
3033 /* no access to the direntry of a read-only file */
3034 if (is_short_name(direntries
+ k
) &&
3035 (direntries
[k
].attributes
& 1)) {
3036 if (memcmp(direntries
+ k
,
3037 array_get(&(s
->directory
), dir_index
+ k
),
3038 sizeof(direntry_t
))) {
3039 warn_report("tried to write to write-protected "
3052 * Use qcow backend. Commit later.
3054 DLOG(fprintf(stderr
, "Write to qcow backend: %d + %d\n", (int)sector_num
, nb_sectors
));
3055 ret
= bdrv_pwrite(s
->qcow
, sector_num
* BDRV_SECTOR_SIZE
, buf
,
3056 nb_sectors
* BDRV_SECTOR_SIZE
);
3058 fprintf(stderr
, "Error writing to qcow backend\n");
3062 for (i
= sector2cluster(s
, sector_num
);
3063 i
<= sector2cluster(s
, sector_num
+ nb_sectors
- 1); i
++)
3065 s
->used_clusters
[i
] |= USED_ALLOCATED
;
3068 /* TODO: add timeout */
3075 static int coroutine_fn
3076 vvfat_co_pwritev(BlockDriverState
*bs
, uint64_t offset
, uint64_t bytes
,
3077 QEMUIOVector
*qiov
, int flags
)
3080 BDRVVVFATState
*s
= bs
->opaque
;
3081 uint64_t sector_num
= offset
>> BDRV_SECTOR_BITS
;
3082 int nb_sectors
= bytes
>> BDRV_SECTOR_BITS
;
3085 assert((offset
& (BDRV_SECTOR_SIZE
- 1)) == 0);
3086 assert((bytes
& (BDRV_SECTOR_SIZE
- 1)) == 0);
3088 buf
= g_try_malloc(bytes
);
3089 if (bytes
&& buf
== NULL
) {
3092 qemu_iovec_to_buf(qiov
, 0, buf
, bytes
);
3094 qemu_co_mutex_lock(&s
->lock
);
3095 ret
= vvfat_write(bs
, sector_num
, buf
, nb_sectors
);
3096 qemu_co_mutex_unlock(&s
->lock
);
3103 static int coroutine_fn
vvfat_co_block_status(BlockDriverState
*bs
,
3104 bool want_zero
, int64_t offset
,
3105 int64_t bytes
, int64_t *n
,
3107 BlockDriverState
**file
)
3110 return BDRV_BLOCK_DATA
;
3113 static int coroutine_fn
3114 write_target_commit(BlockDriverState
*bs
, uint64_t offset
, uint64_t bytes
,
3115 QEMUIOVector
*qiov
, int flags
)
3119 BDRVVVFATState
* s
= *((BDRVVVFATState
**) bs
->opaque
);
3120 qemu_co_mutex_lock(&s
->lock
);
3121 ret
= try_commit(s
);
3122 qemu_co_mutex_unlock(&s
->lock
);
3127 static void write_target_close(BlockDriverState
*bs
) {
3128 BDRVVVFATState
* s
= *((BDRVVVFATState
**) bs
->opaque
);
3129 bdrv_unref_child(s
->bs
, s
->qcow
);
3130 g_free(s
->qcow_filename
);
3133 static BlockDriver vvfat_write_target
= {
3134 .format_name
= "vvfat_write_target",
3135 .instance_size
= sizeof(void*),
3136 .bdrv_co_pwritev
= write_target_commit
,
3137 .bdrv_close
= write_target_close
,
3140 static void vvfat_qcow_options(int *child_flags
, QDict
*child_options
,
3141 int parent_flags
, QDict
*parent_options
)
3143 qdict_set_default_str(child_options
, BDRV_OPT_READ_ONLY
, "off");
3144 qdict_set_default_str(child_options
, BDRV_OPT_AUTO_READ_ONLY
, "off");
3145 qdict_set_default_str(child_options
, BDRV_OPT_CACHE_NO_FLUSH
, "on");
3148 static const BdrvChildRole child_vvfat_qcow
= {
3149 .parent_is_bds
= true,
3150 .inherit_options
= vvfat_qcow_options
,
3153 static int enable_write_target(BlockDriverState
*bs
, Error
**errp
)
3155 BDRVVVFATState
*s
= bs
->opaque
;
3156 BlockDriver
*bdrv_qcow
= NULL
;
3157 BlockDriverState
*backing
;
3158 QemuOpts
*opts
= NULL
;
3160 int size
= sector2cluster(s
, s
->sector_count
);
3163 s
->used_clusters
= calloc(size
, 1);
3165 array_init(&(s
->commits
), sizeof(commit_t
));
3167 s
->qcow_filename
= g_malloc(PATH_MAX
);
3168 ret
= get_tmp_filename(s
->qcow_filename
, PATH_MAX
);
3170 error_setg_errno(errp
, -ret
, "can't create temporary file");
3174 bdrv_qcow
= bdrv_find_format("qcow");
3176 error_setg(errp
, "Failed to locate qcow driver");
3181 opts
= qemu_opts_create(bdrv_qcow
->create_opts
, NULL
, 0, &error_abort
);
3182 qemu_opt_set_number(opts
, BLOCK_OPT_SIZE
, s
->sector_count
* 512,
3184 qemu_opt_set(opts
, BLOCK_OPT_BACKING_FILE
, "fat:", &error_abort
);
3186 ret
= bdrv_create(bdrv_qcow
, s
->qcow_filename
, opts
, errp
);
3187 qemu_opts_del(opts
);
3192 options
= qdict_new();
3193 qdict_put_str(options
, "write-target.driver", "qcow");
3194 s
->qcow
= bdrv_open_child(s
->qcow_filename
, options
, "write-target", bs
,
3195 &child_vvfat_qcow
, false, errp
);
3196 qobject_unref(options
);
3203 unlink(s
->qcow_filename
);
3206 backing
= bdrv_new_open_driver(&vvfat_write_target
, NULL
, BDRV_O_ALLOW_RDWR
,
3208 *(void**) backing
->opaque
= s
;
3210 bdrv_set_backing_hd(s
->bs
, backing
, &error_abort
);
3211 bdrv_unref(backing
);
3216 g_free(s
->qcow_filename
);
3217 s
->qcow_filename
= NULL
;
3221 static void vvfat_child_perm(BlockDriverState
*bs
, BdrvChild
*c
,
3222 const BdrvChildRole
*role
,
3223 BlockReopenQueue
*reopen_queue
,
3224 uint64_t perm
, uint64_t shared
,
3225 uint64_t *nperm
, uint64_t *nshared
)
3227 BDRVVVFATState
*s
= bs
->opaque
;
3229 assert(c
== s
->qcow
|| role
== &child_backing
);
3232 /* This is a private node, nobody should try to attach to it */
3233 *nperm
= BLK_PERM_CONSISTENT_READ
| BLK_PERM_WRITE
;
3234 *nshared
= BLK_PERM_WRITE_UNCHANGED
;
3236 /* The backing file is there so 'commit' can use it. vvfat doesn't
3237 * access it in any way. */
3239 *nshared
= BLK_PERM_ALL
;
3243 static void vvfat_close(BlockDriverState
*bs
)
3245 BDRVVVFATState
*s
= bs
->opaque
;
3247 vvfat_close_current_file(s
);
3248 array_free(&(s
->fat
));
3249 array_free(&(s
->directory
));
3250 array_free(&(s
->mapping
));
3251 g_free(s
->cluster_buffer
);
3254 migrate_del_blocker(s
->migration_blocker
);
3255 error_free(s
->migration_blocker
);
3259 static const char *const vvfat_strong_runtime_opts
[] = {
3269 static BlockDriver bdrv_vvfat
= {
3270 .format_name
= "vvfat",
3271 .protocol_name
= "fat",
3272 .instance_size
= sizeof(BDRVVVFATState
),
3274 .bdrv_parse_filename
= vvfat_parse_filename
,
3275 .bdrv_file_open
= vvfat_open
,
3276 .bdrv_refresh_limits
= vvfat_refresh_limits
,
3277 .bdrv_close
= vvfat_close
,
3278 .bdrv_child_perm
= vvfat_child_perm
,
3280 .bdrv_co_preadv
= vvfat_co_preadv
,
3281 .bdrv_co_pwritev
= vvfat_co_pwritev
,
3282 .bdrv_co_block_status
= vvfat_co_block_status
,
3284 .strong_runtime_opts
= vvfat_strong_runtime_opts
,
3287 static void bdrv_vvfat_init(void)
3289 bdrv_register(&bdrv_vvfat
);
3292 block_init(bdrv_vvfat_init
);
3295 static void checkpoint(void)
3297 assert(((mapping_t
*)array_get(&(vvv
->mapping
), 0))->end
== 2);
3300 assert(!vvv
->current_mapping
|| vvv
->current_fd
|| (vvv
->current_mapping
->mode
& MODE_DIRECTORY
));