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 <glib/gstdio.h>
29
#include "qapi/error.h"
30
#include "block/block-io.h"
31
#include "block/block_int.h"
32
#include "block/qdict.h"
33
#include "qemu/module.h"
34
#include "qemu/option.h"
35
#include "qemu/bswap.h"
36
#include "migration/blocker.h"
37
#include "qapi/qmp/qdict.h"
38
#include "qapi/qmp/qstring.h"
39
#include "qemu/ctype.h"
40
#include "qemu/cutils.h"
41
#include "qemu/error-report.h"
50
/* TODO: add ":bootsector=blabla.img:" */
51
/* LATER TODO: add automatic boot sector generation from
52
BOOTEASY.ASM and Ranish Partition Manager
53
Note that DOS assumes the system files to be the first files in the
54
file system (test if the boot sector still relies on that fact)! */
55
/* MAYBE TODO: write block-visofs.c */
56
/* TODO: call try_commit() only after a timeout */
64
static void checkpoint(void);
72
/* bootsector OEM name. see related compatibility problems at:
73
* https://jdebp.eu/FGA/volume-boot-block-oem-name-field.html
74
* http://seasip.info/Misc/oemid.html
76
#define BOOTSECTOR_OEM_NAME "MSWIN4.1"
78
#define DIR_DELETED 0xe5
79
#define DIR_KANJI DIR_DELETED
80
#define DIR_KANJI_FAKE 0x05
83
/* dynamic array functions */
84
typedef struct array_t {
86
unsigned int size,next,item_size;
89
static inline void array_init(array_t* array,unsigned int item_size)
91
array->pointer = NULL;
94
array->item_size=item_size;
97
static inline void array_free(array_t* array)
99
g_free(array->pointer);
100
array->size=array->next=0;
103
/* does not automatically grow */
104
static inline void* array_get(array_t* array,unsigned int index) {
105
assert(index < array->next);
106
assert(array->pointer);
107
return array->pointer + index * array->item_size;
110
static inline void array_ensure_allocated(array_t *array, int index)
112
if((index + 1) * array->item_size > array->size) {
113
int new_size = (index + 32) * array->item_size;
114
array->pointer = g_realloc(array->pointer, new_size);
115
assert(array->pointer);
116
memset(array->pointer + array->size, 0, new_size - array->size);
117
array->size = new_size;
118
array->next = index + 1;
122
static inline void* array_get_next(array_t* array) {
123
unsigned int next = array->next;
125
array_ensure_allocated(array, next);
126
array->next = next + 1;
127
return array_get(array, next);
130
static inline void* array_insert(array_t* array,unsigned int index,unsigned int count) {
131
if((array->next+count)*array->item_size>array->size) {
132
int increment=count*array->item_size;
133
array->pointer=g_realloc(array->pointer,array->size+increment);
136
array->size+=increment;
138
memmove(array->pointer+(index+count)*array->item_size,
139
array->pointer+index*array->item_size,
140
(array->next-index)*array->item_size);
142
return array->pointer+index*array->item_size;
145
static inline int array_remove_slice(array_t* array,int index, int count)
149
assert(index + count <= array->next);
151
memmove(array->pointer + index * array->item_size,
152
array->pointer + (index + count) * array->item_size,
153
(array->next - index - count) * array->item_size);
155
array->next -= count;
159
static int array_remove(array_t* array,int index)
161
return array_remove_slice(array, index, 1);
164
/* return the index for a given member */
165
static int array_index(array_t* array, void* pointer)
167
size_t offset = (char*)pointer - array->pointer;
168
assert((offset % array->item_size) == 0);
169
assert(offset/array->item_size < array->next);
170
return offset/array->item_size;
173
/* These structures are used to fake a disk and the VFAT filesystem.
174
* For this reason we need to use QEMU_PACKED. */
176
typedef struct bootsector_t {
179
uint16_t sector_size;
180
uint8_t sectors_per_cluster;
181
uint16_t reserved_sectors;
182
uint8_t number_of_fats;
183
uint16_t root_entries;
184
uint16_t total_sectors16;
186
uint16_t sectors_per_fat;
187
uint16_t sectors_per_track;
188
uint16_t number_of_heads;
189
uint32_t hidden_sectors;
190
uint32_t total_sectors;
193
uint8_t drive_number;
197
uint8_t volume_label[11];
199
uint8_t ignored[0x1c0];
202
uint32_t sectors_per_fat;
205
uint32_t first_cluster_of_root_dir;
206
uint16_t info_sector;
207
uint16_t backup_boot_sector;
208
uint8_t reserved[12];
209
uint8_t drive_number;
213
uint8_t volume_label[11];
215
uint8_t ignored[0x1a4];
219
} QEMU_PACKED bootsector_t;
227
typedef struct partition_t {
228
uint8_t attributes; /* 0x80 = bootable */
230
uint8_t fs_type; /* 0x1 = FAT12, 0x6 = FAT16, 0xe = FAT16_LBA, 0xb = FAT32, 0xc = FAT32_LBA */
232
uint32_t start_sector_long;
233
uint32_t length_sector_long;
234
} QEMU_PACKED partition_t;
236
typedef struct mbr_t {
237
uint8_t ignored[0x1b8];
240
partition_t partition[4];
244
typedef struct direntry_t {
256
} QEMU_PACKED direntry_t;
258
/* this structure are used to transparently access the files */
260
typedef struct mapping_t {
261
/* begin is the first cluster, end is the last+1 */
263
/* as s->directory is growable, no pointer may be used here */
264
unsigned int dir_index;
265
/* the clusters of a file may be in any order; this points to the first */
266
int first_mapping_index;
269
* - the offset in the file (in clusters) for a file, or
270
* - the next cluster of the directory for a directory
276
int parent_mapping_index;
280
/* path contains the full path, i.e. it always starts with s->path */
294
static void print_direntry(const struct direntry_t*);
295
static void print_mapping(const struct mapping_t* mapping);
298
/* here begins the real VVFAT driver */
300
typedef struct BDRVVVFATState {
302
BlockDriverState* bs; /* pointer to parent */
303
unsigned char first_sectors[0x40*0x200];
305
int fat_type; /* 16 or 32 */
306
array_t fat,directory,mapping;
307
char volume_label[11];
309
uint32_t offset_to_bootsector; /* 0 for floppy, 0x3f for disk */
311
unsigned int cluster_size;
312
unsigned int sectors_per_cluster;
313
unsigned int sectors_per_fat;
314
uint32_t last_cluster_of_root_directory;
315
/* how many entries are available in root directory (0 for FAT32) */
316
uint16_t root_entries;
317
uint32_t sector_count; /* total number of sectors of the partition */
318
uint32_t cluster_count; /* total number of clusters of this partition */
319
uint32_t max_fat_value;
320
uint32_t offset_to_fat;
321
uint32_t offset_to_root_dir;
324
mapping_t* current_mapping;
325
unsigned char* cluster; /* points to current cluster */
326
unsigned char* cluster_buffer; /* points to a buffer to hold temp data */
327
unsigned int current_cluster;
336
int downcase_short_names;
338
Error *migration_blocker;
341
/* take the sector position spos and convert it to Cylinder/Head/Sector position
342
* if the position is outside the specified geometry, fill maximum value for CHS
343
* and return 1 to signal overflow.
345
static int sector2CHS(mbr_chs_t *chs, int spos, int cyls, int heads, int secs)
348
sector = spos % secs; spos /= secs;
349
head = spos % heads; spos /= heads;
352
it happens if 32bit sector positions are used, while CHS is only 24bit.
353
Windows/Dos is said to take 1023/255/63 as nonrepresentable CHS */
356
chs->cylinder = 0xFF;
359
chs->head = (uint8_t)head;
360
chs->sector = (uint8_t)( (sector+1) | ((spos>>8)<<6) );
361
chs->cylinder = (uint8_t)spos;
365
static void init_mbr(BDRVVVFATState *s, int cyls, int heads, int secs)
367
/* TODO: if the files mbr.img and bootsect.img exist, use them */
368
mbr_t* real_mbr=(mbr_t*)s->first_sectors;
369
partition_t* partition = &(real_mbr->partition[0]);
372
memset(s->first_sectors,0,512);
374
/* Win NT Disk Signature */
375
real_mbr->nt_id= cpu_to_le32(0xbe1afdfa);
377
partition->attributes=0x80; /* bootable */
379
/* LBA is used when partition is outside the CHS geometry */
380
lba = sector2CHS(&partition->start_CHS, s->offset_to_bootsector,
382
lba |= sector2CHS(&partition->end_CHS, s->bs->total_sectors - 1,
385
/*LBA partitions are identified only by start/length_sector_long not by CHS*/
386
partition->start_sector_long = cpu_to_le32(s->offset_to_bootsector);
387
partition->length_sector_long = cpu_to_le32(s->bs->total_sectors
388
- s->offset_to_bootsector);
390
/* FAT12/FAT16/FAT32 */
391
/* DOS uses different types when partition is LBA,
392
probably to prevent older versions from using CHS on them */
393
partition->fs_type = s->fat_type == 12 ? 0x1 :
394
s->fat_type == 16 ? (lba ? 0xe : 0x06) :
395
/*s->fat_type == 32*/ (lba ? 0xc : 0x0b);
397
real_mbr->magic[0]=0x55; real_mbr->magic[1]=0xaa;
400
/* direntry functions */
402
static direntry_t *create_long_filename(BDRVVVFATState *s, const char *filename)
404
int number_of_entries, i;
408
gunichar2 *longname = g_utf8_to_utf16(filename, -1, NULL, &length, NULL);
410
fprintf(stderr, "vvfat: invalid UTF-8 name: %s\n", filename);
414
number_of_entries = DIV_ROUND_UP(length * 2, 26);
416
for(i=0;i<number_of_entries;i++) {
417
entry=array_get_next(&(s->directory));
418
entry->attributes=0xf;
419
entry->reserved[0]=0;
421
entry->name[0]=(number_of_entries-i)|(i==0?0x40:0);
423
for(i=0;i<26*number_of_entries;i++) {
425
if(offset<10) offset=1+offset;
426
else if(offset<22) offset=14+offset-10;
427
else offset=28+offset-22;
428
entry=array_get(&(s->directory),s->directory.next-1-(i/26));
429
if (i >= 2 * length + 2) {
430
entry->name[offset] = 0xff;
431
} else if (i % 2 == 0) {
432
entry->name[offset] = longname[i / 2] & 0xff;
434
entry->name[offset] = longname[i / 2] >> 8;
438
return array_get(&(s->directory),s->directory.next-number_of_entries);
441
static char is_free(const direntry_t* direntry)
443
return direntry->name[0] == DIR_DELETED || direntry->name[0] == DIR_FREE;
446
static char is_volume_label(const direntry_t* direntry)
448
return direntry->attributes == 0x28;
451
static char is_long_name(const direntry_t* direntry)
453
return direntry->attributes == 0xf;
456
static char is_short_name(const direntry_t* direntry)
458
return !is_volume_label(direntry) && !is_long_name(direntry)
459
&& !is_free(direntry);
462
static char is_directory(const direntry_t* direntry)
464
return direntry->attributes & 0x10 && direntry->name[0] != DIR_DELETED;
467
static inline char is_dot(const direntry_t* direntry)
469
return is_short_name(direntry) && direntry->name[0] == '.';
472
static char is_file(const direntry_t* direntry)
474
return is_short_name(direntry) && !is_directory(direntry);
477
static inline uint32_t begin_of_direntry(const direntry_t* direntry)
479
return le16_to_cpu(direntry->begin)|(le16_to_cpu(direntry->begin_hi)<<16);
482
static inline uint32_t filesize_of_direntry(const direntry_t* direntry)
484
return le32_to_cpu(direntry->size);
487
static void set_begin_of_direntry(direntry_t* direntry, uint32_t begin)
489
direntry->begin = cpu_to_le16(begin & 0xffff);
490
direntry->begin_hi = cpu_to_le16((begin >> 16) & 0xffff);
493
static bool valid_filename(const unsigned char *name)
496
if (!strcmp((const char*)name, ".") || !strcmp((const char*)name, "..")) {
499
for (; (c = *name); name++) {
500
if (!((c >= '0' && c <= '9') ||
501
(c >= 'A' && c <= 'Z') ||
502
(c >= 'a' && c <= 'z') ||
504
strchr(" $%'-_@~`!(){}^#&.+,;=[]", c) != NULL))
512
static uint8_t to_valid_short_char(gunichar c)
514
c = g_unichar_toupper(c);
515
if ((c >= '0' && c <= '9') ||
516
(c >= 'A' && c <= 'Z') ||
517
strchr("$%'-_@~`!(){}^#&", c) != NULL) {
524
static direntry_t *create_short_filename(BDRVVVFATState *s,
525
const char *filename,
526
unsigned int directory_start)
529
direntry_t *entry = array_get_next(&(s->directory));
530
const gchar *p, *last_dot = NULL;
532
bool lossy_conversion = false;
538
memset(entry->name, 0x20, sizeof(entry->name));
540
/* copy filename and search last dot */
541
for (p = filename; ; p = g_utf8_next_char(p)) {
542
c = g_utf8_get_char(p);
545
} else if (c == '.') {
547
/* '.' at start of filename */
548
lossy_conversion = true;
551
lossy_conversion = true;
555
} else if (!last_dot) {
556
/* first part of the name; copy it */
557
uint8_t v = to_valid_short_char(c);
559
entry->name[j++] = v;
561
lossy_conversion = true;
566
/* copy extension (if any) */
569
for (p = g_utf8_next_char(last_dot); ; p = g_utf8_next_char(p)) {
570
c = g_utf8_get_char(p);
574
/* extension; copy it */
575
uint8_t v = to_valid_short_char(c);
577
entry->name[8 + (j++)] = v;
579
lossy_conversion = true;
585
if (entry->name[0] == DIR_KANJI) {
586
entry->name[0] = DIR_KANJI_FAKE;
589
/* numeric-tail generation */
590
for (j = 0; j < 8; j++) {
591
if (entry->name[j] == ' ') {
595
for (i = lossy_conversion ? 1 : 0; i < 999999; i++) {
598
int len = snprintf(tail, sizeof(tail), "~%u", (unsigned)i);
600
memcpy(entry->name + MIN(j, 8 - len), tail, len);
602
for (entry1 = array_get(&(s->directory), directory_start);
603
entry1 < entry; entry1++) {
604
if (!is_long_name(entry1) &&
605
!memcmp(entry1->name, entry->name, 11)) {
606
break; /* found dupe */
609
if (entry1 == entry) {
619
static inline uint8_t fat_chksum(const direntry_t* entry)
624
for (i = 0; i < ARRAY_SIZE(entry->name); i++) {
625
chksum = (((chksum & 0xfe) >> 1) |
626
((chksum & 0x01) ? 0x80 : 0)) + entry->name[i];
632
/* if return_time==0, this returns the fat_date, else the fat_time */
633
static uint16_t fat_datetime(time_t time,int return_time) {
637
localtime_r(&time,t);
639
return cpu_to_le16((t->tm_sec/2)|(t->tm_min<<5)|(t->tm_hour<<11));
640
return cpu_to_le16((t->tm_mday)|((t->tm_mon+1)<<5)|((t->tm_year-80)<<9));
643
static inline void fat_set(BDRVVVFATState* s,unsigned int cluster,uint32_t value)
645
if(s->fat_type==32) {
646
uint32_t* entry=array_get(&(s->fat),cluster);
647
*entry=cpu_to_le32(value);
648
} else if(s->fat_type==16) {
649
uint16_t* entry=array_get(&(s->fat),cluster);
650
*entry=cpu_to_le16(value&0xffff);
652
int offset = (cluster*3/2);
653
unsigned char* p = array_get(&(s->fat), offset);
657
p[1] = (p[1]&0xf0) | ((value>>8)&0xf);
660
p[0] = (p[0]&0xf) | ((value&0xf)<<4);
667
static inline uint32_t fat_get(BDRVVVFATState* s,unsigned int cluster)
669
if(s->fat_type==32) {
670
uint32_t* entry=array_get(&(s->fat),cluster);
671
return le32_to_cpu(*entry);
672
} else if(s->fat_type==16) {
673
uint16_t* entry=array_get(&(s->fat),cluster);
674
return le16_to_cpu(*entry);
676
const uint8_t* x=(uint8_t*)(s->fat.pointer)+cluster*3/2;
677
return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
681
static inline int fat_eof(BDRVVVFATState* s,uint32_t fat_entry)
683
if(fat_entry>s->max_fat_value-8)
688
static inline void init_fat(BDRVVVFATState* s)
690
if (s->fat_type == 12) {
691
array_init(&(s->fat),1);
692
array_ensure_allocated(&(s->fat),
693
s->sectors_per_fat * 0x200 * 3 / 2 - 1);
695
array_init(&(s->fat),(s->fat_type==32?4:2));
696
array_ensure_allocated(&(s->fat),
697
s->sectors_per_fat * 0x200 / s->fat.item_size - 1);
699
memset(s->fat.pointer,0,s->fat.size);
701
switch(s->fat_type) {
702
case 12: s->max_fat_value=0xfff; break;
703
case 16: s->max_fat_value=0xffff; break;
704
case 32: s->max_fat_value=0x0fffffff; break;
705
default: s->max_fat_value=0; /* error... */
710
static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,
711
unsigned int directory_start, const char* filename, int is_dot)
713
int long_index = s->directory.next;
714
direntry_t* entry = NULL;
715
direntry_t* entry_long = NULL;
718
entry=array_get_next(&(s->directory));
719
memset(entry->name, 0x20, sizeof(entry->name));
720
memcpy(entry->name,filename,strlen(filename));
724
entry_long=create_long_filename(s,filename);
725
entry = create_short_filename(s, filename, directory_start);
727
/* calculate checksum; propagate to long name */
729
uint8_t chksum=fat_chksum(entry);
731
/* calculate anew, because realloc could have taken place */
732
entry_long=array_get(&(s->directory),long_index);
733
while(entry_long<entry && is_long_name(entry_long)) {
734
entry_long->reserved[1]=chksum;
743
* Read a directory. (the index of the corresponding mapping must be passed).
745
static int read_directory(BDRVVVFATState* s, int mapping_index)
747
mapping_t* mapping = array_get(&(s->mapping), mapping_index);
748
direntry_t* direntry;
749
const char* dirname = mapping->path;
750
int first_cluster = mapping->begin;
751
int parent_index = mapping->info.dir.parent_mapping_index;
752
mapping_t* parent_mapping = (mapping_t*)
753
(parent_index >= 0 ? array_get(&(s->mapping), parent_index) : NULL);
754
int first_cluster_of_parent = parent_mapping ? parent_mapping->begin : -1;
756
DIR* dir=opendir(dirname);
757
struct dirent* entry;
760
assert(mapping->mode & MODE_DIRECTORY);
763
mapping->end = mapping->begin;
767
i = mapping->info.dir.first_dir_index =
768
first_cluster == 0 ? 0 : s->directory.next;
770
if (first_cluster != 0) {
771
/* create the top entries of a subdirectory */
772
(void)create_short_and_long_name(s, i, ".", 1);
773
(void)create_short_and_long_name(s, i, "..", 1);
776
/* actually read the directory, and allocate the mappings */
777
while((entry=readdir(dir))) {
778
unsigned int length=strlen(dirname)+2+strlen(entry->d_name);
781
int is_dot=!strcmp(entry->d_name,".");
782
int is_dotdot=!strcmp(entry->d_name,"..");
784
if (first_cluster == 0 && s->directory.next >= s->root_entries - 1) {
785
fprintf(stderr, "Too many entries in root directory\n");
790
if(first_cluster == 0 && (is_dotdot || is_dot))
793
buffer = g_malloc(length);
794
snprintf(buffer,length,"%s/%s",dirname,entry->d_name);
796
if(stat(buffer,&st)<0) {
801
/* create directory entry for this file */
802
if (!is_dot && !is_dotdot) {
803
direntry = create_short_and_long_name(s, i, entry->d_name, 0);
805
direntry = array_get(&(s->directory), is_dot ? i : i + 1);
807
direntry->attributes=(S_ISDIR(st.st_mode)?0x10:0x20);
808
direntry->reserved[0]=direntry->reserved[1]=0;
809
direntry->ctime=fat_datetime(st.st_ctime,1);
810
direntry->cdate=fat_datetime(st.st_ctime,0);
811
direntry->adate=fat_datetime(st.st_atime,0);
812
direntry->begin_hi=0;
813
direntry->mtime=fat_datetime(st.st_mtime,1);
814
direntry->mdate=fat_datetime(st.st_mtime,0);
816
set_begin_of_direntry(direntry, first_cluster_of_parent);
818
set_begin_of_direntry(direntry, first_cluster);
820
direntry->begin=0; /* do that later */
821
if (st.st_size > 0x7fffffff) {
822
fprintf(stderr, "File %s is larger than 2GB\n", buffer);
827
direntry->size=cpu_to_le32(S_ISDIR(st.st_mode)?0:st.st_size);
829
/* create mapping for this file */
830
if(!is_dot && !is_dotdot && (S_ISDIR(st.st_mode) || st.st_size)) {
831
s->current_mapping = array_get_next(&(s->mapping));
832
s->current_mapping->begin=0;
833
s->current_mapping->end=st.st_size;
835
* we get the direntry of the most recent direntry, which
836
* contains the short name and all the relevant information.
838
s->current_mapping->dir_index=s->directory.next-1;
839
s->current_mapping->first_mapping_index = -1;
840
if (S_ISDIR(st.st_mode)) {
841
s->current_mapping->mode = MODE_DIRECTORY;
842
s->current_mapping->info.dir.parent_mapping_index =
845
s->current_mapping->mode = MODE_UNDEFINED;
846
s->current_mapping->info.file.offset = 0;
848
s->current_mapping->path=buffer;
849
s->current_mapping->read_only =
850
(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0;
857
/* fill with zeroes up to the end of the cluster */
858
while(s->directory.next%(0x10*s->sectors_per_cluster)) {
859
direntry = array_get_next(&(s->directory));
860
memset(direntry,0,sizeof(direntry_t));
863
if (s->fat_type != 32 &&
864
mapping_index == 0 &&
865
s->directory.next < s->root_entries) {
867
int cur = s->directory.next;
868
array_ensure_allocated(&(s->directory), s->root_entries - 1);
869
s->directory.next = s->root_entries;
870
memset(array_get(&(s->directory), cur), 0,
871
(s->root_entries - cur) * sizeof(direntry_t));
874
/* re-get the mapping, since s->mapping was possibly realloc()ed */
875
mapping = array_get(&(s->mapping), mapping_index);
876
first_cluster += (s->directory.next - mapping->info.dir.first_dir_index)
877
* 0x20 / s->cluster_size;
878
mapping->end = first_cluster;
880
direntry = array_get(&(s->directory), mapping->dir_index);
881
set_begin_of_direntry(direntry, mapping->begin);
886
static inline int32_t sector2cluster(BDRVVVFATState* s,off_t sector_num)
888
return (sector_num - s->offset_to_root_dir) / s->sectors_per_cluster;
891
static inline off_t cluster2sector(BDRVVVFATState* s, uint32_t cluster_num)
893
return s->offset_to_root_dir + s->sectors_per_cluster * cluster_num;
896
static int init_directories(BDRVVVFATState* s,
897
const char *dirname, int heads, int secs,
900
bootsector_t* bootsector;
903
unsigned int cluster;
905
memset(&(s->first_sectors[0]),0,0x40*0x200);
907
s->cluster_size=s->sectors_per_cluster*0x200;
908
s->cluster_buffer=g_malloc(s->cluster_size);
911
* The formula: sc = spf+1+spf*spc*(512*8/fat_type),
912
* where sc is sector_count,
913
* spf is sectors_per_fat,
914
* spc is sectors_per_clusters, and
915
* fat_type = 12, 16 or 32.
917
i = 1+s->sectors_per_cluster*0x200*8/s->fat_type;
918
s->sectors_per_fat=(s->sector_count+i)/i; /* round up */
920
s->offset_to_fat = s->offset_to_bootsector + 1;
921
s->offset_to_root_dir = s->offset_to_fat + s->sectors_per_fat * 2;
923
array_init(&(s->mapping),sizeof(mapping_t));
924
array_init(&(s->directory),sizeof(direntry_t));
926
/* add volume label */
928
direntry_t* entry=array_get_next(&(s->directory));
929
entry->attributes=0x28; /* archive | volume label */
930
memcpy(entry->name, s->volume_label, sizeof(entry->name));
933
/* Now build FAT, and write back information into directory */
936
/* TODO: if there are more entries, bootsector has to be adjusted! */
937
s->root_entries = 0x02 * 0x10 * s->sectors_per_cluster;
938
s->cluster_count=sector2cluster(s, s->sector_count);
940
mapping = array_get_next(&(s->mapping));
942
mapping->dir_index = 0;
943
mapping->info.dir.parent_mapping_index = -1;
944
mapping->first_mapping_index = -1;
945
mapping->path = g_strdup(dirname);
946
i = strlen(mapping->path);
947
if (i > 0 && mapping->path[i - 1] == '/')
948
mapping->path[i - 1] = '\0';
949
mapping->mode = MODE_DIRECTORY;
950
mapping->read_only = 0;
951
s->path = mapping->path;
953
for (i = 0, cluster = 0; i < s->mapping.next; i++) {
954
/* MS-DOS expects the FAT to be 0 for the root directory
955
* (except for the media byte). */
956
/* LATER TODO: still true for FAT32? */
957
int fix_fat = (i != 0);
958
mapping = array_get(&(s->mapping), i);
960
if (mapping->mode & MODE_DIRECTORY) {
961
char *path = mapping->path;
962
mapping->begin = cluster;
963
if(read_directory(s, i)) {
964
error_setg(errp, "Could not read directory %s", path);
967
mapping = array_get(&(s->mapping), i);
969
assert(mapping->mode == MODE_UNDEFINED);
970
mapping->mode=MODE_NORMAL;
971
mapping->begin = cluster;
972
if (mapping->end > 0) {
973
direntry_t* direntry = array_get(&(s->directory),
976
mapping->end = cluster + 1 + (mapping->end-1)/s->cluster_size;
977
set_begin_of_direntry(direntry, mapping->begin);
979
mapping->end = cluster + 1;
984
assert(mapping->begin < mapping->end);
986
/* next free cluster */
987
cluster = mapping->end;
989
if(cluster > s->cluster_count) {
991
"Directory does not fit in FAT%d (capacity %.2f MB)",
992
s->fat_type, s->sector_count / 2000.0);
996
/* fix fat for entry */
999
for(j = mapping->begin; j < mapping->end - 1; j++)
1001
fat_set(s, mapping->end - 1, s->max_fat_value);
1005
mapping = array_get(&(s->mapping), 0);
1006
s->last_cluster_of_root_directory = mapping->end;
1008
/* the FAT signature */
1009
fat_set(s,0,s->max_fat_value);
1010
fat_set(s,1,s->max_fat_value);
1012
s->current_mapping = NULL;
1014
bootsector = (bootsector_t *)(s->first_sectors
1015
+ s->offset_to_bootsector * 0x200);
1016
bootsector->jump[0]=0xeb;
1017
bootsector->jump[1]=0x3e;
1018
bootsector->jump[2]=0x90;
1019
memcpy(bootsector->name, BOOTSECTOR_OEM_NAME, 8);
1020
bootsector->sector_size=cpu_to_le16(0x200);
1021
bootsector->sectors_per_cluster=s->sectors_per_cluster;
1022
bootsector->reserved_sectors=cpu_to_le16(1);
1023
bootsector->number_of_fats=0x2; /* number of FATs */
1024
bootsector->root_entries = cpu_to_le16(s->root_entries);
1025
bootsector->total_sectors16=s->sector_count>0xffff?0:cpu_to_le16(s->sector_count);
1026
/* media descriptor: hard disk=0xf8, floppy=0xf0 */
1027
bootsector->media_type = (s->offset_to_bootsector > 0 ? 0xf8 : 0xf0);
1028
s->fat.pointer[0] = bootsector->media_type;
1029
bootsector->sectors_per_fat=cpu_to_le16(s->sectors_per_fat);
1030
bootsector->sectors_per_track = cpu_to_le16(secs);
1031
bootsector->number_of_heads = cpu_to_le16(heads);
1032
bootsector->hidden_sectors = cpu_to_le32(s->offset_to_bootsector);
1033
bootsector->total_sectors=cpu_to_le32(s->sector_count>0xffff?s->sector_count:0);
1035
/* LATER TODO: if FAT32, this is wrong */
1036
/* drive_number: fda=0, hda=0x80 */
1037
bootsector->u.fat16.drive_number = s->offset_to_bootsector == 0 ? 0 : 0x80;
1038
bootsector->u.fat16.signature=0x29;
1039
bootsector->u.fat16.id=cpu_to_le32(0xfabe1afd);
1041
memcpy(bootsector->u.fat16.volume_label, s->volume_label,
1042
sizeof(bootsector->u.fat16.volume_label));
1043
memcpy(bootsector->u.fat16.fat_type,
1044
s->fat_type == 12 ? "FAT12 " : "FAT16 ", 8);
1045
bootsector->magic[0]=0x55; bootsector->magic[1]=0xaa;
1051
static BDRVVVFATState *vvv = NULL;
1054
static int enable_write_target(BlockDriverState *bs, Error **errp);
1055
static int coroutine_fn is_consistent(BDRVVVFATState *s);
1057
static QemuOptsList runtime_opts = {
1059
.head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
1063
.type = QEMU_OPT_STRING,
1064
.help = "Host directory to map to the vvfat device",
1068
.type = QEMU_OPT_NUMBER,
1069
.help = "FAT type (12, 16 or 32)",
1073
.type = QEMU_OPT_BOOL,
1074
.help = "Create a floppy rather than a hard disk image",
1078
.type = QEMU_OPT_STRING,
1079
.help = "Use a volume label other than QEMU VVFAT",
1083
.type = QEMU_OPT_BOOL,
1084
.help = "Make the image writable",
1086
{ /* end of list */ }
1090
static void vvfat_parse_filename(const char *filename, QDict *options,
1094
bool floppy = false;
1098
if (!strstart(filename, "fat:", NULL)) {
1099
error_setg(errp, "File name string must start with 'fat:'");
1104
if (strstr(filename, ":32:")) {
1106
} else if (strstr(filename, ":16:")) {
1108
} else if (strstr(filename, ":12:")) {
1112
if (strstr(filename, ":floppy:")) {
1116
if (strstr(filename, ":rw:")) {
1120
/* Get the directory name without options */
1121
i = strrchr(filename, ':') - filename;
1123
if (filename[i - 2] == ':' && qemu_isalpha(filename[i - 1])) {
1124
/* workaround for DOS drive names */
1130
/* Fill in the options QDict */
1131
qdict_put_str(options, "dir", filename);
1132
qdict_put_int(options, "fat-type", fat_type);
1133
qdict_put_bool(options, "floppy", floppy);
1134
qdict_put_bool(options, "rw", rw);
1137
static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
1140
BDRVVVFATState *s = bs->opaque;
1141
int cyls, heads, secs;
1143
const char *dirname, *label;
1147
GRAPH_RDLOCK_GUARD_MAINLOOP();
1153
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
1154
if (!qemu_opts_absorb_qdict(opts, options, errp)) {
1159
dirname = qemu_opt_get(opts, "dir");
1161
error_setg(errp, "vvfat block driver requires a 'dir' option");
1166
s->fat_type = qemu_opt_get_number(opts, "fat-type", 0);
1167
floppy = qemu_opt_get_bool(opts, "floppy", false);
1169
memset(s->volume_label, ' ', sizeof(s->volume_label));
1170
label = qemu_opt_get(opts, "label");
1172
size_t label_length = strlen(label);
1173
if (label_length > 11) {
1174
error_setg(errp, "vvfat label cannot be longer than 11 bytes");
1178
memcpy(s->volume_label, label, label_length);
1180
memcpy(s->volume_label, "QEMU VVFAT", 10);
1184
/* 1.44MB or 2.88MB floppy. 2.88MB can be FAT12 (default) or FAT16. */
1188
s->sectors_per_cluster = 2;
1190
secs = s->fat_type == 12 ? 18 : 36;
1191
s->sectors_per_cluster = 1;
1196
/* 32MB or 504MB disk*/
1200
s->offset_to_bootsector = 0x3f;
1201
cyls = s->fat_type == 12 ? 64 : 1024;
1206
switch (s->fat_type) {
1208
warn_report("FAT32 has not been tested. You are welcome to do so!");
1214
error_setg(errp, "Valid FAT types are only 12, 16 and 32");
1222
/* LATER TODO: if FAT32, adjust */
1223
s->sectors_per_cluster=0x10;
1225
s->current_cluster=0xffffffff;
1228
s->qcow_filename = NULL;
1230
s->downcase_short_names = 1;
1232
DLOG(fprintf(stderr, "vvfat %s chs %d,%d,%d\n",
1233
dirname, cyls, heads, secs));
1235
s->sector_count = cyls * heads * secs - s->offset_to_bootsector;
1236
bs->total_sectors = cyls * heads * secs;
1238
if (qemu_opt_get_bool(opts, "rw", false)) {
1239
if (!bdrv_is_read_only(bs)) {
1240
ret = enable_write_target(bs, errp);
1247
"Unable to set VVFAT to 'rw' when drive is read-only");
1251
ret = bdrv_apply_auto_read_only(bs, NULL, errp);
1257
if (init_directories(s, dirname, heads, secs, errp)) {
1262
s->sector_count = s->offset_to_root_dir
1263
+ s->sectors_per_cluster * s->cluster_count;
1265
/* Disable migration when vvfat is used rw */
1267
error_setg(&s->migration_blocker,
1268
"The vvfat (rw) format used by node '%s' "
1269
"does not support live migration",
1270
bdrv_get_device_or_node_name(bs));
1271
ret = migrate_add_blocker_normal(&s->migration_blocker, errp);
1277
if (s->offset_to_bootsector > 0) {
1278
init_mbr(s, cyls, heads, secs);
1281
qemu_co_mutex_init(&s->lock);
1283
qemu_opts_del(opts);
1288
g_free(s->qcow_filename);
1289
s->qcow_filename = NULL;
1290
g_free(s->cluster_buffer);
1291
s->cluster_buffer = NULL;
1292
g_free(s->used_clusters);
1293
s->used_clusters = NULL;
1295
qemu_opts_del(opts);
1299
static void vvfat_refresh_limits(BlockDriverState *bs, Error **errp)
1301
bs->bl.request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O */
1304
static inline void vvfat_close_current_file(BDRVVVFATState *s)
1306
if(s->current_mapping) {
1307
s->current_mapping = NULL;
1308
if (s->current_fd) {
1309
qemu_close(s->current_fd);
1313
s->current_cluster = -1;
1316
/* mappings between index1 and index2-1 are supposed to be ordered
1317
* return value is the index of the last mapping for which end>cluster_num
1319
static inline int find_mapping_for_cluster_aux(BDRVVVFATState* s,int cluster_num,int index1,int index2)
1324
index3=(index1+index2)/2;
1325
mapping=array_get(&(s->mapping),index3);
1326
assert(mapping->begin < mapping->end);
1327
if(mapping->begin>=cluster_num) {
1328
assert(index2!=index3 || index2==0);
1334
return mapping->end<=cluster_num ? index2 : index1;
1337
assert(index1<=index2);
1338
DLOG(mapping=array_get(&(s->mapping),index1);
1339
assert(mapping->begin<=cluster_num);
1340
assert(index2 >= s->mapping.next ||
1341
((mapping = array_get(&(s->mapping),index2)) &&
1342
mapping->end>cluster_num)));
1346
static inline mapping_t* find_mapping_for_cluster(BDRVVVFATState* s,int cluster_num)
1348
int index=find_mapping_for_cluster_aux(s,cluster_num,0,s->mapping.next);
1350
if(index>=s->mapping.next)
1352
mapping=array_get(&(s->mapping),index);
1353
if(mapping->begin>cluster_num)
1355
assert(mapping->begin<=cluster_num && mapping->end>cluster_num);
1359
static int open_file(BDRVVVFATState* s,mapping_t* mapping)
1363
if(!s->current_mapping ||
1364
strcmp(s->current_mapping->path,mapping->path)) {
1366
int fd = qemu_open_old(mapping->path,
1367
O_RDONLY | O_BINARY | O_LARGEFILE);
1370
vvfat_close_current_file(s);
1374
s->current_mapping = mapping;
1378
static inline int read_cluster(BDRVVVFATState *s,int cluster_num)
1380
if(s->current_cluster != cluster_num) {
1383
assert(!s->current_mapping || s->current_fd || (s->current_mapping->mode & MODE_DIRECTORY));
1384
if(!s->current_mapping
1385
|| s->current_mapping->begin>cluster_num
1386
|| s->current_mapping->end<=cluster_num) {
1387
/* binary search of mappings for file */
1388
mapping_t* mapping=find_mapping_for_cluster(s,cluster_num);
1390
assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
1392
if (mapping && mapping->mode & MODE_DIRECTORY) {
1393
vvfat_close_current_file(s);
1394
s->current_mapping = mapping;
1395
read_cluster_directory:
1396
offset = s->cluster_size*(cluster_num-s->current_mapping->begin);
1397
s->cluster = (unsigned char*)s->directory.pointer+offset
1398
+ 0x20*s->current_mapping->info.dir.first_dir_index;
1399
assert(((s->cluster-(unsigned char*)s->directory.pointer)%s->cluster_size)==0);
1400
assert((char*)s->cluster+s->cluster_size <= s->directory.pointer+s->directory.next*s->directory.item_size);
1401
s->current_cluster = cluster_num;
1405
if(open_file(s,mapping))
1407
} else if (s->current_mapping->mode & MODE_DIRECTORY)
1408
goto read_cluster_directory;
1410
assert(s->current_fd);
1412
offset = s->cluster_size *
1413
((cluster_num - s->current_mapping->begin)
1414
+ s->current_mapping->info.file.offset);
1415
if(lseek(s->current_fd, offset, SEEK_SET)!=offset)
1417
s->cluster=s->cluster_buffer;
1418
result=read(s->current_fd,s->cluster,s->cluster_size);
1420
s->current_cluster = -1;
1423
s->current_cluster = cluster_num;
1429
static void print_direntry(const direntry_t* direntry)
1434
fprintf(stderr, "direntry %p: ", direntry);
1437
if(is_long_name(direntry)) {
1438
unsigned char* c=(unsigned char*)direntry;
1440
for(i=1;i<11 && c[i] && c[i]!=0xff;i+=2)
1441
#define ADD_CHAR(c) {buffer[j] = (c); if (buffer[j] < ' ') buffer[j] = 0xb0; j++;}
1443
for(i=14;i<26 && c[i] && c[i]!=0xff;i+=2)
1445
for(i=28;i<32 && c[i] && c[i]!=0xff;i+=2)
1448
fprintf(stderr, "%s\n", buffer);
1452
ADD_CHAR(direntry->name[i]);
1454
fprintf(stderr, "%s attributes=0x%02x begin=%u size=%u\n",
1456
direntry->attributes,
1457
begin_of_direntry(direntry),le32_to_cpu(direntry->size));
1461
static void print_mapping(const mapping_t* mapping)
1463
fprintf(stderr, "mapping (%p): begin, end = %u, %u, dir_index = %u, "
1464
"first_mapping_index = %d, name = %s, mode = 0x%x, " ,
1465
mapping, mapping->begin, mapping->end, mapping->dir_index,
1466
mapping->first_mapping_index, mapping->path, mapping->mode);
1468
if (mapping->mode & MODE_DIRECTORY)
1469
fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
1471
fprintf(stderr, "offset = %u\n", mapping->info.file.offset);
1475
static int coroutine_fn GRAPH_RDLOCK
1476
vvfat_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors)
1478
BDRVVVFATState *s = bs->opaque;
1481
for(i=0;i<nb_sectors;i++,sector_num++) {
1482
if (sector_num >= bs->total_sectors)
1487
ret = bdrv_co_is_allocated(s->qcow->bs, sector_num * BDRV_SECTOR_SIZE,
1488
(nb_sectors - i) * BDRV_SECTOR_SIZE, &n);
1493
DLOG(fprintf(stderr, "sectors %" PRId64 "+%" PRId64
1494
" allocated\n", sector_num,
1495
n >> BDRV_SECTOR_BITS));
1496
if (bdrv_co_pread(s->qcow, sector_num * BDRV_SECTOR_SIZE, n,
1497
buf + i * 0x200, 0) < 0) {
1500
i += (n >> BDRV_SECTOR_BITS) - 1;
1501
sector_num += (n >> BDRV_SECTOR_BITS) - 1;
1504
DLOG(fprintf(stderr, "sector %" PRId64 " not allocated\n",
1507
if (sector_num < s->offset_to_root_dir) {
1508
if (sector_num < s->offset_to_fat) {
1509
memcpy(buf + i * 0x200,
1510
&(s->first_sectors[sector_num * 0x200]),
1512
} else if (sector_num < s->offset_to_fat + s->sectors_per_fat) {
1513
memcpy(buf + i * 0x200,
1514
&(s->fat.pointer[(sector_num
1515
- s->offset_to_fat) * 0x200]),
1517
} else if (sector_num < s->offset_to_root_dir) {
1518
memcpy(buf + i * 0x200,
1519
&(s->fat.pointer[(sector_num - s->offset_to_fat
1520
- s->sectors_per_fat) * 0x200]),
1524
uint32_t sector = sector_num - s->offset_to_root_dir,
1525
sector_offset_in_cluster=(sector%s->sectors_per_cluster),
1526
cluster_num=sector/s->sectors_per_cluster;
1527
if(cluster_num > s->cluster_count || read_cluster(s, cluster_num) != 0) {
1528
/* LATER TODO: strict: return -1; */
1529
memset(buf+i*0x200,0,0x200);
1532
memcpy(buf+i*0x200,s->cluster+sector_offset_in_cluster*0x200,0x200);
1538
static int coroutine_fn GRAPH_RDLOCK
1539
vvfat_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
1540
QEMUIOVector *qiov, BdrvRequestFlags flags)
1543
BDRVVVFATState *s = bs->opaque;
1544
uint64_t sector_num = offset >> BDRV_SECTOR_BITS;
1545
int nb_sectors = bytes >> BDRV_SECTOR_BITS;
1548
assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
1549
assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
1551
buf = g_try_malloc(bytes);
1552
if (bytes && buf == NULL) {
1556
qemu_co_mutex_lock(&s->lock);
1557
ret = vvfat_read(bs, sector_num, buf, nb_sectors);
1558
qemu_co_mutex_unlock(&s->lock);
1560
qemu_iovec_from_buf(qiov, 0, buf, bytes);
1566
/* LATER TODO: statify all functions */
1569
* Idea of the write support (use snapshot):
1571
* 1. check if all data is consistent, recording renames, modifications,
1572
* new files and directories (in s->commits).
1574
* 2. if the data is not consistent, stop committing
1576
* 3. handle renames, and create new files and directories (do not yet
1577
* write their contents)
1579
* 4. walk the directories, fixing the mapping and direntries, and marking
1580
* the handled mappings as not deleted
1582
* 5. commit the contents of the files
1584
* 6. handle deleted files and directories
1588
typedef struct commit_t {
1591
struct { uint32_t cluster; } rename;
1592
struct { int dir_index; uint32_t modified_offset; } writeout;
1593
struct { uint32_t first_cluster; } new_file;
1594
struct { uint32_t cluster; } mkdir;
1596
/* DELETEs and RMDIRs are handled differently: see handle_deletes() */
1598
ACTION_RENAME, ACTION_WRITEOUT, ACTION_NEW_FILE, ACTION_MKDIR
1602
static void clear_commits(BDRVVVFATState* s)
1605
DLOG(fprintf(stderr, "clear_commits (%u commits)\n", s->commits.next));
1606
for (i = 0; i < s->commits.next; i++) {
1607
commit_t* commit = array_get(&(s->commits), i);
1608
assert(commit->path || commit->action == ACTION_WRITEOUT);
1609
if (commit->action != ACTION_WRITEOUT) {
1610
assert(commit->path);
1611
g_free(commit->path);
1613
assert(commit->path == NULL);
1615
s->commits.next = 0;
1618
static void schedule_rename(BDRVVVFATState* s,
1619
uint32_t cluster, char* new_path)
1621
commit_t* commit = array_get_next(&(s->commits));
1622
commit->path = new_path;
1623
commit->param.rename.cluster = cluster;
1624
commit->action = ACTION_RENAME;
1627
static void schedule_writeout(BDRVVVFATState* s,
1628
int dir_index, uint32_t modified_offset)
1630
commit_t* commit = array_get_next(&(s->commits));
1631
commit->path = NULL;
1632
commit->param.writeout.dir_index = dir_index;
1633
commit->param.writeout.modified_offset = modified_offset;
1634
commit->action = ACTION_WRITEOUT;
1637
static void schedule_new_file(BDRVVVFATState* s,
1638
char* path, uint32_t first_cluster)
1640
commit_t* commit = array_get_next(&(s->commits));
1641
commit->path = path;
1642
commit->param.new_file.first_cluster = first_cluster;
1643
commit->action = ACTION_NEW_FILE;
1646
static void schedule_mkdir(BDRVVVFATState* s, uint32_t cluster, char* path)
1648
commit_t* commit = array_get_next(&(s->commits));
1649
commit->path = path;
1650
commit->param.mkdir.cluster = cluster;
1651
commit->action = ACTION_MKDIR;
1656
* Since the sequence number is at most 0x3f, and the filename
1657
* length is at most 13 times the sequence number, the maximal
1658
* filename length is 0x3f * 13 bytes.
1660
unsigned char name[0x3f * 13 + 1];
1661
gunichar2 name2[0x3f * 13 + 1];
1663
int sequence_number;
1666
static void lfn_init(long_file_name* lfn)
1668
lfn->sequence_number = lfn->len = 0;
1669
lfn->checksum = 0x100;
1672
/* return 0 if parsed successfully, > 0 if no long name, < 0 if error */
1673
static int parse_long_name(long_file_name* lfn,
1674
const direntry_t* direntry)
1677
const unsigned char* pointer = (const unsigned char*)direntry;
1679
if (!is_long_name(direntry))
1682
if (pointer[0] & 0x40) {
1683
/* first entry; do some initialization */
1684
lfn->sequence_number = pointer[0] & 0x3f;
1685
lfn->checksum = pointer[13];
1687
lfn->name[lfn->sequence_number * 13] = 0;
1688
} else if ((pointer[0] & 0x3f) != --lfn->sequence_number) {
1689
/* not the expected sequence number */
1691
} else if (pointer[13] != lfn->checksum) {
1692
/* not the expected checksum */
1694
} else if (pointer[12] || pointer[26] || pointer[27]) {
1695
/* invalid zero fields */
1699
offset = 13 * (lfn->sequence_number - 1);
1700
for (i = 0, j = 1; i < 13; i++, j+=2) {
1706
if (pointer[j] == 0 && pointer[j + 1] == 0) {
1707
/* end of long file name */
1710
gunichar2 c = (pointer[j + 1] << 8) + pointer[j];
1711
lfn->name2[offset + i] = c;
1714
if (pointer[0] & 0x40) {
1715
/* first entry; set len */
1716
lfn->len = offset + i;
1718
if ((pointer[0] & 0x3f) == 0x01) {
1719
/* last entry; finalize entry */
1721
gchar *utf8 = g_utf16_to_utf8(lfn->name2, lfn->len, NULL, &olen, NULL);
1726
memcpy(lfn->name, utf8, olen + 1);
1733
/* returns 0 if successful, >0 if no short_name, and <0 on error */
1734
static int parse_short_name(BDRVVVFATState* s,
1735
long_file_name* lfn, direntry_t* direntry)
1739
if (!is_short_name(direntry))
1742
for (j = 7; j >= 0 && direntry->name[j] == ' '; j--);
1743
for (i = 0; i <= j; i++) {
1744
uint8_t c = direntry->name[i];
1745
if (c != to_valid_short_char(c)) {
1747
} else if (s->downcase_short_names) {
1748
lfn->name[i] = qemu_tolower(direntry->name[i]);
1750
lfn->name[i] = direntry->name[i];
1754
for (j = 2; j >= 0 && direntry->name[8 + j] == ' '; j--) {
1757
lfn->name[i++] = '.';
1758
lfn->name[i + j + 1] = '\0';
1759
for (;j >= 0; j--) {
1760
uint8_t c = direntry->name[8 + j];
1761
if (c != to_valid_short_char(c)) {
1763
} else if (s->downcase_short_names) {
1764
lfn->name[i + j] = qemu_tolower(c);
1766
lfn->name[i + j] = c;
1770
lfn->name[i + j + 1] = '\0';
1772
if (lfn->name[0] == DIR_KANJI_FAKE) {
1773
lfn->name[0] = DIR_KANJI;
1775
lfn->len = strlen((char*)lfn->name);
1780
static inline uint32_t modified_fat_get(BDRVVVFATState* s,
1781
unsigned int cluster)
1783
if (cluster < s->last_cluster_of_root_directory) {
1784
if (cluster + 1 == s->last_cluster_of_root_directory)
1785
return s->max_fat_value;
1790
if (s->fat_type==32) {
1791
uint32_t* entry=((uint32_t*)s->fat2)+cluster;
1792
return le32_to_cpu(*entry);
1793
} else if (s->fat_type==16) {
1794
uint16_t* entry=((uint16_t*)s->fat2)+cluster;
1795
return le16_to_cpu(*entry);
1797
const uint8_t* x=s->fat2+cluster*3/2;
1798
return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
1802
static inline bool coroutine_fn GRAPH_RDLOCK
1803
cluster_was_modified(BDRVVVFATState *s, uint32_t cluster_num)
1805
int was_modified = 0;
1808
if (s->qcow == NULL) {
1812
for (i = 0; !was_modified && i < s->sectors_per_cluster; i++) {
1813
was_modified = bdrv_co_is_allocated(s->qcow->bs,
1814
(cluster2sector(s, cluster_num) +
1815
i) * BDRV_SECTOR_SIZE,
1816
BDRV_SECTOR_SIZE, NULL);
1820
* Note that this treats failures to learn allocation status the
1821
* same as if an allocation has occurred. It's as safe as
1822
* anything else, given that a failure to learn allocation status
1823
* will probably result in more failures.
1825
return !!was_modified;
1828
static const char* get_basename(const char* path)
1830
char* basename = strrchr(path, '/');
1831
if (basename == NULL)
1834
return basename + 1; /* strip '/' */
1838
* The array s->used_clusters holds the states of the clusters. If it is
1839
* part of a file, it has bit 2 set, in case of a directory, bit 1. If it
1840
* was modified, bit 3 is set.
1841
* If any cluster is allocated, but not part of a file or directory, this
1842
* driver refuses to commit.
1845
USED_DIRECTORY = 1, USED_FILE = 2, USED_ANY = 3, USED_ALLOCATED = 4
1849
* get_cluster_count_for_direntry() not only determines how many clusters
1850
* are occupied by direntry, but also if it was renamed or modified.
1852
* A file is thought to be renamed *only* if there already was a file with
1853
* exactly the same first cluster, but a different name.
1855
* Further, the files/directories handled by this function are
1856
* assumed to be *not* deleted (and *only* those).
1858
static uint32_t coroutine_fn GRAPH_RDLOCK
1859
get_cluster_count_for_direntry(BDRVVVFATState* s, direntry_t* direntry, const char* path)
1862
* This is a little bit tricky:
1863
* IF the guest OS just inserts a cluster into the file chain,
1864
* and leaves the rest alone, (i.e. the original file had clusters
1865
* 15 -> 16, but now has 15 -> 32 -> 16), then the following happens:
1867
* - do_commit will write the cluster into the file at the given
1870
* - the cluster which is overwritten should be moved to a later
1871
* position in the file.
1873
* I am not aware that any OS does something as braindead, but this
1874
* situation could happen anyway when not committing for a long time.
1875
* Just to be sure that this does not bite us, detect it, and copy the
1876
* contents of the clusters to-be-overwritten into the qcow.
1879
int was_modified = 0;
1882
uint32_t cluster_num = begin_of_direntry(direntry);
1883
uint32_t offset = 0;
1884
mapping_t* mapping = NULL;
1885
const char* basename2 = NULL;
1887
vvfat_close_current_file(s);
1889
/* the root directory */
1890
if (cluster_num == 0)
1895
basename2 = get_basename(path);
1897
mapping = find_mapping_for_cluster(s, cluster_num);
1900
const char* basename;
1902
assert(mapping->mode & MODE_DELETED);
1903
mapping->mode &= ~MODE_DELETED;
1905
basename = get_basename(mapping->path);
1907
assert(mapping->mode & MODE_NORMAL);
1910
if (strcmp(basename, basename2))
1911
schedule_rename(s, cluster_num, g_strdup(path));
1912
} else if (is_file(direntry))
1914
schedule_new_file(s, g_strdup(path), cluster_num);
1923
if (!copy_it && cluster_was_modified(s, cluster_num)) {
1924
if (mapping == NULL ||
1925
mapping->begin > cluster_num ||
1926
mapping->end <= cluster_num)
1927
mapping = find_mapping_for_cluster(s, cluster_num);
1931
(mapping->mode & MODE_DIRECTORY) == 0) {
1933
/* was modified in qcow */
1934
if (offset != s->cluster_size
1935
* ((cluster_num - mapping->begin)
1936
+ mapping->info.file.offset)) {
1937
/* offset of this cluster in file chain has changed */
1940
} else if (offset == 0) {
1941
const char* basename = get_basename(mapping->path);
1943
if (strcmp(basename, basename2))
1946
assert(mapping->first_mapping_index == -1
1947
|| mapping->info.file.offset > 0);
1949
/* need to write out? */
1950
if (!was_modified && is_file(direntry)) {
1952
schedule_writeout(s, mapping->dir_index, offset);
1960
* This is horribly inefficient, but that is okay, since
1961
* it is rarely executed, if at all.
1963
int64_t offs = cluster2sector(s, cluster_num);
1965
vvfat_close_current_file(s);
1966
for (i = 0; i < s->sectors_per_cluster; i++) {
1969
res = bdrv_co_is_allocated(s->qcow->bs,
1970
(offs + i) * BDRV_SECTOR_SIZE,
1971
BDRV_SECTOR_SIZE, NULL);
1976
res = vvfat_read(s->bs, offs, s->cluster_buffer, 1);
1980
res = bdrv_co_pwrite(s->qcow, offs * BDRV_SECTOR_SIZE,
1981
BDRV_SECTOR_SIZE, s->cluster_buffer,
1992
if (s->used_clusters[cluster_num] & USED_ANY)
1994
s->used_clusters[cluster_num] = USED_FILE;
1996
cluster_num = modified_fat_get(s, cluster_num);
1998
if (fat_eof(s, cluster_num))
2000
else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
2003
offset += s->cluster_size;
2008
* This function looks at the modified data (qcow).
2009
* It returns 0 upon inconsistency or error, and the number of clusters
2010
* used by the directory, its subdirectories and their files.
2012
static int coroutine_fn GRAPH_RDLOCK
2013
check_directory_consistency(BDRVVVFATState *s, int cluster_num, const char* path)
2016
unsigned char* cluster = g_malloc(s->cluster_size);
2017
direntry_t* direntries = (direntry_t*)cluster;
2018
mapping_t* mapping = find_mapping_for_cluster(s, cluster_num);
2021
int path_len = strlen(path);
2022
char path2[PATH_MAX + 1];
2024
assert(path_len < PATH_MAX); /* len was tested before! */
2025
pstrcpy(path2, sizeof(path2), path);
2026
path2[path_len] = '/';
2027
path2[path_len + 1] = '\0';
2030
const char* basename = get_basename(mapping->path);
2031
const char* basename2 = get_basename(path);
2033
assert(mapping->mode & MODE_DIRECTORY);
2035
assert(mapping->mode & MODE_DELETED);
2036
mapping->mode &= ~MODE_DELETED;
2038
if (strcmp(basename, basename2))
2039
schedule_rename(s, cluster_num, g_strdup(path));
2042
schedule_mkdir(s, cluster_num, g_strdup(path));
2051
if (s->used_clusters[cluster_num] & USED_ANY) {
2052
fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
2055
s->used_clusters[cluster_num] = USED_DIRECTORY;
2057
DLOG(fprintf(stderr, "read cluster %d (sector %d)\n", (int)cluster_num, (int)cluster2sector(s, cluster_num)));
2058
subret = vvfat_read(s->bs, cluster2sector(s, cluster_num), cluster,
2059
s->sectors_per_cluster);
2061
fprintf(stderr, "Error fetching direntries\n");
2067
for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
2068
int cluster_count = 0;
2070
DLOG(fprintf(stderr, "check direntry %d:\n", i); print_direntry(direntries + i));
2071
if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
2072
is_free(direntries + i))
2075
subret = parse_long_name(&lfn, direntries + i);
2077
fprintf(stderr, "Error in long name\n");
2080
if (subret == 0 || is_free(direntries + i))
2083
if (fat_chksum(direntries+i) != lfn.checksum) {
2084
subret = parse_short_name(s, &lfn, direntries + i);
2086
fprintf(stderr, "Error in short name (%d)\n", subret);
2089
if (subret > 0 || !strcmp((char*)lfn.name, ".")
2090
|| !strcmp((char*)lfn.name, ".."))
2093
lfn.checksum = 0x100; /* cannot use long name twice */
2095
if (!valid_filename(lfn.name)) {
2096
fprintf(stderr, "Invalid file name\n");
2099
if (path_len + 1 + lfn.len >= PATH_MAX) {
2100
fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
2103
pstrcpy(path2 + path_len + 1, sizeof(path2) - path_len - 1,
2106
if (is_directory(direntries + i)) {
2107
if (begin_of_direntry(direntries + i) == 0) {
2108
DLOG(fprintf(stderr, "invalid begin for directory: %s\n", path2); print_direntry(direntries + i));
2111
cluster_count = check_directory_consistency(s,
2112
begin_of_direntry(direntries + i), path2);
2113
if (cluster_count == 0) {
2114
DLOG(fprintf(stderr, "problem in directory %s:\n", path2); print_direntry(direntries + i));
2117
} else if (is_file(direntries + i)) {
2118
/* check file size with FAT */
2119
cluster_count = get_cluster_count_for_direntry(s, direntries + i, path2);
2120
if (cluster_count !=
2121
DIV_ROUND_UP(le32_to_cpu(direntries[i].size), s->cluster_size)) {
2122
DLOG(fprintf(stderr, "Cluster count mismatch\n"));
2126
abort(); /* cluster_count = 0; */
2128
ret += cluster_count;
2131
cluster_num = modified_fat_get(s, cluster_num);
2132
} while(!fat_eof(s, cluster_num));
2138
/* returns 1 on success */
2139
static int coroutine_fn GRAPH_RDLOCK
2140
is_consistent(BDRVVVFATState* s)
2143
int used_clusters_count = 0;
2147
* - get modified FAT
2148
* - compare the two FATs (TODO)
2149
* - get buffer for marking used clusters
2150
* - recurse direntries from root (using bs->bdrv_pread to make
2151
* sure to get the new data)
2152
* - check that the FAT agrees with the size
2153
* - count the number of clusters occupied by this directory and
2155
* - check that the cumulative used cluster count agrees with the
2157
* - if all is fine, return number of used clusters
2159
if (s->fat2 == NULL) {
2160
int size = 0x200 * s->sectors_per_fat;
2161
s->fat2 = g_malloc(size);
2162
memcpy(s->fat2, s->fat.pointer, size);
2164
check = vvfat_read(s->bs,
2165
s->offset_to_fat, s->fat2, s->sectors_per_fat);
2167
fprintf(stderr, "Could not copy fat\n");
2170
assert (s->used_clusters);
2171
for (i = 0; i < sector2cluster(s, s->sector_count); i++)
2172
s->used_clusters[i] &= ~USED_ANY;
2176
/* mark every mapped file/directory as deleted.
2177
* (check_directory_consistency() will unmark those still present). */
2179
for (i = 0; i < s->mapping.next; i++) {
2180
mapping_t* mapping = array_get(&(s->mapping), i);
2181
if (mapping->first_mapping_index < 0)
2182
mapping->mode |= MODE_DELETED;
2185
used_clusters_count = check_directory_consistency(s, 0, s->path);
2186
if (used_clusters_count <= 0) {
2187
DLOG(fprintf(stderr, "problem in directory\n"));
2191
check = s->last_cluster_of_root_directory;
2192
for (i = check; i < sector2cluster(s, s->sector_count); i++) {
2193
if (modified_fat_get(s, i)) {
2194
if(!s->used_clusters[i]) {
2195
DLOG(fprintf(stderr, "FAT was modified (%d), but cluster is not used?\n", i));
2201
if (s->used_clusters[i] == USED_ALLOCATED) {
2202
/* allocated, but not used... */
2203
DLOG(fprintf(stderr, "unused, modified cluster: %d\n", i));
2208
if (check != used_clusters_count)
2211
return used_clusters_count;
2214
static inline void adjust_mapping_indices(BDRVVVFATState* s,
2215
int offset, int adjust)
2219
for (i = 0; i < s->mapping.next; i++) {
2220
mapping_t* mapping = array_get(&(s->mapping), i);
2222
#define ADJUST_MAPPING_INDEX(name) \
2223
if (mapping->name >= offset) \
2224
mapping->name += adjust
2226
ADJUST_MAPPING_INDEX(first_mapping_index);
2227
if (mapping->mode & MODE_DIRECTORY)
2228
ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
2232
/* insert or update mapping */
2233
static mapping_t* insert_mapping(BDRVVVFATState* s,
2234
uint32_t begin, uint32_t end)
2237
* - find mapping where mapping->begin >= begin,
2238
* - if mapping->begin > begin: insert
2239
* - adjust all references to mappings!
2243
int index = find_mapping_for_cluster_aux(s, begin, 0, s->mapping.next);
2244
mapping_t* mapping = NULL;
2245
mapping_t* first_mapping = array_get(&(s->mapping), 0);
2247
if (index < s->mapping.next && (mapping = array_get(&(s->mapping), index))
2248
&& mapping->begin < begin) {
2249
mapping->end = begin;
2251
mapping = array_get(&(s->mapping), index);
2253
if (index >= s->mapping.next || mapping->begin > begin) {
2254
mapping = array_insert(&(s->mapping), index, 1);
2255
mapping->path = NULL;
2256
adjust_mapping_indices(s, index, +1);
2259
mapping->begin = begin;
2262
DLOG(mapping_t* next_mapping;
2263
assert(index + 1 >= s->mapping.next ||
2264
((next_mapping = array_get(&(s->mapping), index + 1)) &&
2265
next_mapping->begin >= end)));
2267
if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
2268
s->current_mapping = array_get(&(s->mapping),
2269
s->current_mapping - first_mapping);
2274
static int remove_mapping(BDRVVVFATState* s, int mapping_index)
2276
mapping_t* mapping = array_get(&(s->mapping), mapping_index);
2277
mapping_t* first_mapping = array_get(&(s->mapping), 0);
2280
if (mapping->first_mapping_index < 0) {
2281
g_free(mapping->path);
2284
/* remove from s->mapping */
2285
array_remove(&(s->mapping), mapping_index);
2287
/* adjust all references to mappings */
2288
adjust_mapping_indices(s, mapping_index, -1);
2290
if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
2291
s->current_mapping = array_get(&(s->mapping),
2292
s->current_mapping - first_mapping);
2297
static void adjust_dirindices(BDRVVVFATState* s, int offset, int adjust)
2300
for (i = 0; i < s->mapping.next; i++) {
2301
mapping_t* mapping = array_get(&(s->mapping), i);
2302
if (mapping->dir_index >= offset)
2303
mapping->dir_index += adjust;
2304
if ((mapping->mode & MODE_DIRECTORY) &&
2305
mapping->info.dir.first_dir_index >= offset)
2306
mapping->info.dir.first_dir_index += adjust;
2310
static direntry_t* insert_direntries(BDRVVVFATState* s,
2311
int dir_index, int count)
2314
* make room in s->directory,
2317
direntry_t* result = array_insert(&(s->directory), dir_index, count);
2320
adjust_dirindices(s, dir_index, count);
2324
static int remove_direntries(BDRVVVFATState* s, int dir_index, int count)
2326
int ret = array_remove_slice(&(s->directory), dir_index, count);
2329
adjust_dirindices(s, dir_index, -count);
2334
* Adapt the mappings of the cluster chain starting at first cluster
2335
* (i.e. if a file starts at first_cluster, the chain is followed according
2336
* to the modified fat, and the corresponding entries in s->mapping are
2339
static int commit_mappings(BDRVVVFATState* s,
2340
uint32_t first_cluster, int dir_index)
2342
mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2343
direntry_t* direntry = array_get(&(s->directory), dir_index);
2344
uint32_t cluster = first_cluster;
2346
vvfat_close_current_file(s);
2349
assert(mapping->begin == first_cluster);
2350
mapping->first_mapping_index = -1;
2351
mapping->dir_index = dir_index;
2352
mapping->mode = (dir_index <= 0 || is_directory(direntry)) ?
2353
MODE_DIRECTORY : MODE_NORMAL;
2355
while (!fat_eof(s, cluster)) {
2358
for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
2359
c = c1, c1 = modified_fat_get(s, c1));
2362
if (c > mapping->end) {
2363
int index = array_index(&(s->mapping), mapping);
2364
int i, max_i = s->mapping.next - index;
2365
for (i = 1; i < max_i && mapping[i].begin < c; i++);
2367
remove_mapping(s, index + 1);
2369
assert(mapping == array_get(&(s->mapping), s->mapping.next - 1)
2370
|| mapping[1].begin >= c);
2373
if (!fat_eof(s, c1)) {
2374
int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next);
2375
mapping_t* next_mapping = i >= s->mapping.next ? NULL :
2376
array_get(&(s->mapping), i);
2378
if (next_mapping == NULL || next_mapping->begin > c1) {
2379
int i1 = array_index(&(s->mapping), mapping);
2381
next_mapping = insert_mapping(s, c1, c1+1);
2385
mapping = array_get(&(s->mapping), i1);
2388
next_mapping->dir_index = mapping->dir_index;
2389
next_mapping->first_mapping_index =
2390
mapping->first_mapping_index < 0 ?
2391
array_index(&(s->mapping), mapping) :
2392
mapping->first_mapping_index;
2393
next_mapping->path = mapping->path;
2394
next_mapping->mode = mapping->mode;
2395
next_mapping->read_only = mapping->read_only;
2396
if (mapping->mode & MODE_DIRECTORY) {
2397
next_mapping->info.dir.parent_mapping_index =
2398
mapping->info.dir.parent_mapping_index;
2399
next_mapping->info.dir.first_dir_index =
2400
mapping->info.dir.first_dir_index +
2401
0x10 * s->sectors_per_cluster *
2402
(mapping->end - mapping->begin);
2404
next_mapping->info.file.offset = mapping->info.file.offset +
2405
(mapping->end - mapping->begin);
2407
mapping = next_mapping;
2416
static int coroutine_fn GRAPH_RDLOCK
2417
commit_direntries(BDRVVVFATState* s, int dir_index, int parent_mapping_index)
2419
direntry_t* direntry = array_get(&(s->directory), dir_index);
2420
uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
2421
mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2422
int factor = 0x10 * s->sectors_per_cluster;
2423
int old_cluster_count, new_cluster_count;
2424
int current_dir_index;
2425
int first_dir_index;
2431
assert(mapping->begin == first_cluster);
2432
assert(mapping->info.dir.first_dir_index < s->directory.next);
2433
assert(mapping->mode & MODE_DIRECTORY);
2434
assert(dir_index == 0 || is_directory(direntry));
2436
DLOG(fprintf(stderr, "commit_direntries for %s, parent_mapping_index %d\n",
2437
mapping->path, parent_mapping_index));
2439
current_dir_index = mapping->info.dir.first_dir_index;
2440
first_dir_index = current_dir_index;
2441
mapping->info.dir.parent_mapping_index = parent_mapping_index;
2443
if (first_cluster == 0) {
2444
old_cluster_count = new_cluster_count =
2445
s->last_cluster_of_root_directory;
2447
for (old_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2449
old_cluster_count++;
2451
for (new_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2452
c = modified_fat_get(s, c))
2453
new_cluster_count++;
2456
if (new_cluster_count > old_cluster_count) {
2457
if (insert_direntries(s,
2458
current_dir_index + factor * old_cluster_count,
2459
factor * (new_cluster_count - old_cluster_count)) == NULL)
2461
} else if (new_cluster_count < old_cluster_count)
2462
remove_direntries(s,
2463
current_dir_index + factor * new_cluster_count,
2464
factor * (old_cluster_count - new_cluster_count));
2466
for (c = first_cluster; !fat_eof(s, c); c = modified_fat_get(s, c)) {
2467
direntry_t *first_direntry;
2469
direntry = array_get(&(s->directory), current_dir_index);
2470
ret = vvfat_read(s->bs, cluster2sector(s, c), (uint8_t *)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 coroutine_fn GRAPH_RDLOCK
2508
commit_one_file(BDRVVVFATState* s, 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 = 0; i < offset; i += s->cluster_size) {
2527
c = modified_fat_get(s, c);
2530
fd = qemu_open_old(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666);
2532
fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path,
2533
strerror(errno), errno);
2537
if (lseek(fd, offset, SEEK_SET) != offset) {
2543
cluster = g_malloc(s->cluster_size);
2545
while (offset < size) {
2547
int rest_size = (size - offset > s->cluster_size ?
2548
s->cluster_size : size - offset);
2551
c1 = modified_fat_get(s, c);
2553
assert((size - offset == 0 && fat_eof(s, c)) ||
2554
(size > offset && c >=2 && !fat_eof(s, c)));
2556
ret = vvfat_read(s->bs, cluster2sector(s, c),
2557
(uint8_t*)cluster, DIV_ROUND_UP(rest_size, 0x200));
2565
if (write(fd, cluster, rest_size) < 0) {
2571
offset += rest_size;
2575
if (ftruncate(fd, size)) {
2576
perror("ftruncate()");
2584
return commit_mappings(s, first_cluster, dir_index);
2588
/* test, if all mappings point to valid direntries */
2589
static void check1(BDRVVVFATState* s)
2592
for (i = 0; i < s->mapping.next; i++) {
2593
mapping_t* mapping = array_get(&(s->mapping), i);
2594
if (mapping->mode & MODE_DELETED) {
2595
fprintf(stderr, "deleted\n");
2598
assert(mapping->dir_index < s->directory.next);
2599
direntry_t* direntry = array_get(&(s->directory), mapping->dir_index);
2600
assert(mapping->begin == begin_of_direntry(direntry) || mapping->first_mapping_index >= 0);
2601
if (mapping->mode & MODE_DIRECTORY) {
2602
assert(mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster * (mapping->end - mapping->begin) <= s->directory.next);
2603
assert((mapping->info.dir.first_dir_index % (0x10 * s->sectors_per_cluster)) == 0);
2608
/* test, if all direntries have mappings */
2609
static void check2(BDRVVVFATState* s)
2612
int first_mapping = -1;
2614
for (i = 0; i < s->directory.next; i++) {
2615
direntry_t* direntry = array_get(&(s->directory), i);
2617
if (is_short_name(direntry) && begin_of_direntry(direntry)) {
2618
mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
2620
assert(mapping->dir_index == i || is_dot(direntry));
2621
assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry));
2624
if ((i % (0x10 * s->sectors_per_cluster)) == 0) {
2628
for (j = 0; j < s->mapping.next; j++) {
2629
mapping_t* mapping = array_get(&(s->mapping), j);
2630
if (mapping->mode & MODE_DELETED)
2632
if (mapping->mode & MODE_DIRECTORY) {
2633
if (mapping->info.dir.first_dir_index <= i && mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster > i) {
2634
assert(++count == 1);
2635
if (mapping->first_mapping_index == -1)
2636
first_mapping = array_index(&(s->mapping), mapping);
2638
assert(first_mapping == mapping->first_mapping_index);
2639
if (mapping->info.dir.parent_mapping_index < 0)
2642
mapping_t* parent = array_get(&(s->mapping), mapping->info.dir.parent_mapping_index);
2643
assert(parent->mode & MODE_DIRECTORY);
2644
assert(parent->info.dir.first_dir_index < mapping->info.dir.first_dir_index);
2656
static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2661
fprintf(stderr, "handle_renames\n");
2662
for (i = 0; i < s->commits.next; i++) {
2663
commit_t* commit = array_get(&(s->commits), i);
2664
fprintf(stderr, "%d, %s (%u, %d)\n", i,
2665
commit->path ? commit->path : "(null)",
2666
commit->param.rename.cluster, commit->action);
2670
for (i = 0; i < s->commits.next;) {
2671
commit_t* commit = array_get(&(s->commits), i);
2672
if (commit->action == ACTION_RENAME) {
2673
mapping_t* mapping = find_mapping_for_cluster(s,
2674
commit->param.rename.cluster);
2677
if (mapping == NULL) {
2680
old_path = mapping->path;
2681
assert(commit->path);
2682
mapping->path = commit->path;
2683
if (rename(old_path, mapping->path))
2686
if (mapping->mode & MODE_DIRECTORY) {
2687
int l1 = strlen(mapping->path);
2688
int l2 = strlen(old_path);
2690
direntry_t* direntry = array_get(&(s->directory),
2691
mapping->info.dir.first_dir_index);
2692
uint32_t c = mapping->begin;
2696
while (!fat_eof(s, c)) {
2698
direntry_t *d = direntry + j;
2700
if (is_file(d) || (is_directory(d) && !is_dot(d))) {
2703
mapping_t* m = find_mapping_for_cluster(s,
2704
begin_of_direntry(d));
2708
l = strlen(m->path);
2709
new_path = g_malloc(l + diff + 1);
2711
assert(!strncmp(m->path, mapping->path, l2));
2713
pstrcpy(new_path, l + diff + 1, mapping->path);
2714
pstrcpy(new_path + l1, l + diff + 1 - l1,
2717
schedule_rename(s, m->begin, new_path);
2720
} while (j % (0x10 * s->sectors_per_cluster) != 0);
2726
array_remove(&(s->commits), i);
2728
} else if (commit->action == ACTION_MKDIR) {
2730
int j, parent_path_len;
2732
if (g_mkdir(commit->path, 0755)) {
2736
mapping = insert_mapping(s, commit->param.mkdir.cluster,
2737
commit->param.mkdir.cluster + 1);
2738
if (mapping == NULL)
2741
mapping->mode = MODE_DIRECTORY;
2742
mapping->read_only = 0;
2743
mapping->path = commit->path;
2744
j = s->directory.next;
2746
insert_direntries(s, s->directory.next,
2747
0x10 * s->sectors_per_cluster);
2748
mapping->info.dir.first_dir_index = j;
2750
parent_path_len = strlen(commit->path)
2751
- strlen(get_basename(commit->path)) - 1;
2752
for (j = 0; j < s->mapping.next; j++) {
2753
mapping_t* m = array_get(&(s->mapping), j);
2754
if (m->first_mapping_index < 0 && m != mapping &&
2755
!strncmp(m->path, mapping->path, parent_path_len) &&
2756
strlen(m->path) == parent_path_len)
2759
assert(j < s->mapping.next);
2760
mapping->info.dir.parent_mapping_index = j;
2762
array_remove(&(s->commits), i);
2772
* TODO: make sure that the short name is not matching *another* file
2774
static int coroutine_fn GRAPH_RDLOCK handle_commits(BDRVVVFATState* s)
2778
vvfat_close_current_file(s);
2780
for (i = 0; !fail && i < s->commits.next; i++) {
2781
commit_t* commit = array_get(&(s->commits), i);
2782
switch(commit->action) {
2783
case ACTION_RENAME: case ACTION_MKDIR:
2787
case ACTION_WRITEOUT: {
2788
direntry_t* entry = array_get(&(s->directory),
2789
commit->param.writeout.dir_index);
2790
uint32_t begin = begin_of_direntry(entry);
2791
mapping_t* mapping = find_mapping_for_cluster(s, begin);
2794
assert(mapping->begin == begin);
2795
assert(commit->path == NULL);
2797
if (commit_one_file(s, commit->param.writeout.dir_index,
2798
commit->param.writeout.modified_offset))
2803
case ACTION_NEW_FILE: {
2804
int begin = commit->param.new_file.first_cluster;
2805
mapping_t* mapping = find_mapping_for_cluster(s, begin);
2810
for (j = 0; j < s->directory.next; j++) {
2811
entry = array_get(&(s->directory), j);
2812
if (is_file(entry) && begin_of_direntry(entry) == begin)
2816
if (j >= s->directory.next) {
2821
/* make sure there exists an initial mapping */
2822
if (mapping && mapping->begin != begin) {
2823
mapping->end = begin;
2826
if (mapping == NULL) {
2827
mapping = insert_mapping(s, begin, begin+1);
2829
/* most members will be fixed in commit_mappings() */
2830
assert(commit->path);
2831
mapping->path = commit->path;
2832
mapping->read_only = 0;
2833
mapping->mode = MODE_NORMAL;
2834
mapping->info.file.offset = 0;
2836
if (commit_one_file(s, j, 0)) {
2846
if (i > 0 && array_remove_slice(&(s->commits), 0, i))
2851
static int handle_deletes(BDRVVVFATState* s)
2853
int i, deferred = 1, deleted = 1;
2855
/* delete files corresponding to mappings marked as deleted */
2856
/* handle DELETEs and unused mappings (modified_fat_get(s, mapping->begin) == 0) */
2857
while (deferred && deleted) {
2861
for (i = 1; i < s->mapping.next; i++) {
2862
mapping_t* mapping = array_get(&(s->mapping), i);
2863
if (mapping->mode & MODE_DELETED) {
2864
direntry_t* entry = array_get(&(s->directory),
2865
mapping->dir_index);
2867
if (is_free(entry)) {
2868
/* remove file/directory */
2869
if (mapping->mode & MODE_DIRECTORY) {
2870
int j, next_dir_index = s->directory.next,
2871
first_dir_index = mapping->info.dir.first_dir_index;
2873
if (rmdir(mapping->path) < 0) {
2874
if (errno == ENOTEMPTY) {
2881
for (j = 1; j < s->mapping.next; j++) {
2882
mapping_t* m = array_get(&(s->mapping), j);
2883
if (m->mode & MODE_DIRECTORY &&
2884
m->info.dir.first_dir_index >
2886
m->info.dir.first_dir_index <
2889
m->info.dir.first_dir_index;
2891
remove_direntries(s, first_dir_index,
2892
next_dir_index - first_dir_index);
2897
if (unlink(mapping->path))
2901
DLOG(fprintf(stderr, "DELETE (%d)\n", i); print_mapping(mapping); print_direntry(entry));
2902
remove_mapping(s, i);
2911
* synchronize mapping with new state:
2913
* - copy FAT (with bdrv_pread)
2914
* - mark all filenames corresponding to mappings as deleted
2915
* - recurse direntries from root (using bs->bdrv_pread)
2916
* - delete files corresponding to mappings marked as deleted
2918
static int coroutine_fn GRAPH_RDLOCK do_commit(BDRVVVFATState* s)
2922
/* the real meat are the commits. Nothing to do? Move along! */
2923
if (s->commits.next == 0)
2926
vvfat_close_current_file(s);
2928
ret = handle_renames_and_mkdirs(s);
2930
fprintf(stderr, "Error handling renames (%d)\n", ret);
2935
/* copy FAT (with bdrv_pread) */
2936
memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
2938
/* recurse direntries from root (using bs->bdrv_pread) */
2939
ret = commit_direntries(s, 0, -1);
2941
fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
2946
ret = handle_commits(s);
2948
fprintf(stderr, "Error handling commits (%d)\n", ret);
2953
ret = handle_deletes(s);
2955
fprintf(stderr, "Error deleting\n");
2960
bdrv_make_empty(s->qcow, NULL);
2962
memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
2968
static int coroutine_fn GRAPH_RDLOCK try_commit(BDRVVVFATState* s)
2970
vvfat_close_current_file(s);
2972
if(!is_consistent(s))
2974
return do_commit(s);
2977
static int coroutine_fn GRAPH_RDLOCK
2978
vvfat_write(BlockDriverState *bs, int64_t sector_num,
2979
const uint8_t *buf, int nb_sectors)
2981
BDRVVVFATState *s = bs->opaque;
2983
int first_cluster, last_cluster;
2987
/* Check if we're operating in read-only mode */
2988
if (s->qcow == NULL) {
2992
vvfat_close_current_file(s);
2994
if (sector_num == s->offset_to_bootsector && nb_sectors == 1) {
2996
* Write on bootsector. Allow only changing the reserved1 field,
2997
* used to mark volume dirtiness
2999
unsigned char *bootsector = s->first_sectors
3000
+ s->offset_to_bootsector * 0x200;
3002
* LATER TODO: if FAT32, this is wrong (see init_directories(),
3003
* which always creates a FAT16 bootsector)
3005
const int reserved1_offset = offsetof(bootsector_t, u.fat16.reserved1);
3007
for (i = 0; i < 0x200; i++) {
3008
if (i != reserved1_offset && bootsector[i] != buf[i]) {
3009
fprintf(stderr, "Tried to write to protected bootsector\n");
3014
/* Update bootsector with the only updatable byte, and return success */
3015
bootsector[reserved1_offset] = buf[reserved1_offset];
3020
* Some sanity checks:
3021
* - do not allow writing to the boot sector
3023
if (sector_num < s->offset_to_fat)
3027
* Values will be negative for writes to the FAT, which is located before
3028
* the root directory.
3030
first_cluster = sector2cluster(s, sector_num);
3031
last_cluster = sector2cluster(s, sector_num + nb_sectors - 1);
3033
for (i = first_cluster; i <= last_cluster;) {
3034
mapping_t *mapping = NULL;
3037
mapping = find_mapping_for_cluster(s, i);
3041
if (mapping->read_only) {
3042
fprintf(stderr, "Tried to write to write-protected file %s\n",
3047
if (mapping->mode & MODE_DIRECTORY) {
3048
int begin = cluster2sector(s, i);
3049
int end = begin + s->sectors_per_cluster, k;
3051
const direntry_t* direntries;
3056
if (begin < sector_num)
3058
if (end > sector_num + nb_sectors)
3059
end = sector_num + nb_sectors;
3060
dir_index = mapping->dir_index +
3061
0x10 * (begin - mapping->begin * s->sectors_per_cluster);
3062
direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
3064
for (k = 0; k < (end - begin) * 0x10; k++) {
3065
/* no access to the direntry of a read-only file */
3066
if (is_short_name(direntries + k) &&
3067
(direntries[k].attributes & 1)) {
3068
if (memcmp(direntries + k,
3069
array_get(&(s->directory), dir_index + k),
3070
sizeof(direntry_t))) {
3071
warn_report("tried to write to write-protected "
3085
* Use qcow backend. Commit later.
3087
DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
3088
ret = bdrv_co_pwrite(s->qcow, sector_num * BDRV_SECTOR_SIZE,
3089
nb_sectors * BDRV_SECTOR_SIZE, buf, 0);
3091
fprintf(stderr, "Error writing to qcow backend\n");
3095
for (i = first_cluster; i <= last_cluster; i++) {
3097
s->used_clusters[i] |= USED_ALLOCATED;
3102
/* TODO: add timeout */
3109
static int coroutine_fn GRAPH_RDLOCK
3110
vvfat_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
3111
QEMUIOVector *qiov, BdrvRequestFlags flags)
3114
BDRVVVFATState *s = bs->opaque;
3115
uint64_t sector_num = offset >> BDRV_SECTOR_BITS;
3116
int nb_sectors = bytes >> BDRV_SECTOR_BITS;
3119
assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
3120
assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
3122
buf = g_try_malloc(bytes);
3123
if (bytes && buf == NULL) {
3126
qemu_iovec_to_buf(qiov, 0, buf, bytes);
3128
qemu_co_mutex_lock(&s->lock);
3129
ret = vvfat_write(bs, sector_num, buf, nb_sectors);
3130
qemu_co_mutex_unlock(&s->lock);
3137
static int coroutine_fn vvfat_co_block_status(BlockDriverState *bs,
3138
bool want_zero, int64_t offset,
3139
int64_t bytes, int64_t *n,
3141
BlockDriverState **file)
3144
return BDRV_BLOCK_DATA;
3147
static void vvfat_qcow_options(BdrvChildRole role, bool parent_is_format,
3148
int *child_flags, QDict *child_options,
3149
int parent_flags, QDict *parent_options)
3151
qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "off");
3152
qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
3153
qdict_set_default_str(child_options, BDRV_OPT_CACHE_NO_FLUSH, "on");
3156
static BdrvChildClass child_vvfat_qcow;
3158
static int enable_write_target(BlockDriverState *bs, Error **errp)
3160
BDRVVVFATState *s = bs->opaque;
3161
BlockDriver *bdrv_qcow = NULL;
3162
QemuOpts *opts = NULL;
3164
int size = sector2cluster(s, s->sector_count);
3167
s->used_clusters = g_malloc0(size);
3169
array_init(&(s->commits), sizeof(commit_t));
3171
s->qcow_filename = create_tmp_file(errp);
3172
if (!s->qcow_filename) {
3177
bdrv_qcow = bdrv_find_format("qcow");
3179
error_setg(errp, "Failed to locate qcow driver");
3184
opts = qemu_opts_create(bdrv_qcow->create_opts, NULL, 0, &error_abort);
3185
qemu_opt_set_number(opts, BLOCK_OPT_SIZE,
3186
bs->total_sectors * BDRV_SECTOR_SIZE, &error_abort);
3187
qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, "fat:", &error_abort);
3189
ret = bdrv_create(bdrv_qcow, s->qcow_filename, opts, errp);
3190
qemu_opts_del(opts);
3195
options = qdict_new();
3196
qdict_put_str(options, "write-target.driver", "qcow");
3197
s->qcow = bdrv_open_child(s->qcow_filename, options, "write-target", bs,
3199
BDRV_CHILD_DATA | BDRV_CHILD_METADATA,
3201
qobject_unref(options);
3208
unlink(s->qcow_filename);
3217
static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c,
3219
BlockReopenQueue *reopen_queue,
3220
uint64_t perm, uint64_t shared,
3221
uint64_t *nperm, uint64_t *nshared)
3223
assert(role & BDRV_CHILD_DATA);
3224
/* This is a private node, nobody should try to attach to it */
3225
*nperm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE;
3226
*nshared = BLK_PERM_WRITE_UNCHANGED;
3229
static void vvfat_close(BlockDriverState *bs)
3231
BDRVVVFATState *s = bs->opaque;
3233
vvfat_close_current_file(s);
3234
array_free(&(s->fat));
3235
array_free(&(s->directory));
3236
array_free(&(s->mapping));
3237
g_free(s->cluster_buffer);
3240
migrate_del_blocker(&s->migration_blocker);
3244
static const char *const vvfat_strong_runtime_opts[] = {
3254
static BlockDriver bdrv_vvfat = {
3255
.format_name = "vvfat",
3256
.protocol_name = "fat",
3257
.instance_size = sizeof(BDRVVVFATState),
3259
.bdrv_parse_filename = vvfat_parse_filename,
3260
.bdrv_open = vvfat_open,
3261
.bdrv_refresh_limits = vvfat_refresh_limits,
3262
.bdrv_close = vvfat_close,
3263
.bdrv_child_perm = vvfat_child_perm,
3265
.bdrv_co_preadv = vvfat_co_preadv,
3266
.bdrv_co_pwritev = vvfat_co_pwritev,
3267
.bdrv_co_block_status = vvfat_co_block_status,
3269
.strong_runtime_opts = vvfat_strong_runtime_opts,
3272
static void bdrv_vvfat_init(void)
3274
child_vvfat_qcow = child_of_bds;
3275
child_vvfat_qcow.inherit_options = vvfat_qcow_options;
3276
bdrv_register(&bdrv_vvfat);
3279
block_init(bdrv_vvfat_init);
3282
static void checkpoint(void)
3284
assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2);
3287
assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY));