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
25 #include "qemu/osdep.h"
27 #include "qapi/error.h"
28 #include "block/block_int.h"
29 #include "qemu/module.h"
30 #include "qemu/bswap.h"
31 #include "migration/blocker.h"
32 #include "qapi/qmp/qbool.h"
33 #include "qapi/qmp/qstring.h"
34 #include "qemu/cutils.h"
43 /* TODO: add ":bootsector=blabla.img:" */
44 /* LATER TODO: add automatic boot sector generation from
45 BOOTEASY.ASM and Ranish Partition Manager
46 Note that DOS assumes the system files to be the first files in the
47 file system (test if the boot sector still relies on that fact)! */
48 /* MAYBE TODO: write block-visofs.c */
49 /* TODO: call try_commit() only after a timeout */
57 static void checkpoint(void);
60 void nonono(const char* file, int line, const char* msg) {
61 fprintf(stderr, "Nonono! %s:%d %s\n", file, line, msg);
65 #define assert(a) do {if (!(a)) nonono(__FILE__, __LINE__, #a);}while(0)
74 /* dynamic array functions */
75 typedef struct array_t {
77 unsigned int size,next,item_size;
80 static inline void array_init(array_t* array,unsigned int item_size)
82 array->pointer = NULL;
85 array->item_size=item_size;
88 static inline void array_free(array_t* array)
90 g_free(array->pointer);
91 array->size=array->next=0;
94 /* does not automatically grow */
95 static inline void* array_get(array_t* array,unsigned int index) {
96 assert(index < array->next);
97 return array->pointer + index * array->item_size;
100 static inline int array_ensure_allocated(array_t* array, int index)
102 if((index + 1) * array->item_size > array->size) {
103 int new_size = (index + 32) * array->item_size;
104 array->pointer = g_realloc(array->pointer, new_size);
107 array->size = new_size;
108 array->next = index + 1;
114 static inline void* array_get_next(array_t* array) {
115 unsigned int next = array->next;
117 if (array_ensure_allocated(array, next) < 0)
120 array->next = next + 1;
121 return array_get(array, next);
124 static inline void* array_insert(array_t* array,unsigned int index,unsigned int count) {
125 if((array->next+count)*array->item_size>array->size) {
126 int increment=count*array->item_size;
127 array->pointer=g_realloc(array->pointer,array->size+increment);
130 array->size+=increment;
132 memmove(array->pointer+(index+count)*array->item_size,
133 array->pointer+index*array->item_size,
134 (array->next-index)*array->item_size);
136 return array->pointer+index*array->item_size;
139 /* this performs a "roll", so that the element which was at index_from becomes
140 * index_to, but the order of all other elements is preserved. */
141 static inline int array_roll(array_t* array,int index_to,int index_from,int count)
149 index_to<0 || index_to>=array->next ||
150 index_from<0 || index_from>=array->next)
153 if(index_to==index_from)
157 from=array->pointer+index_from*is;
158 to=array->pointer+index_to*is;
159 buf=g_malloc(is*count);
160 memcpy(buf,from,is*count);
162 if(index_to<index_from)
163 memmove(to+is*count,to,from-to);
165 memmove(from,from+is*count,to-from);
167 memcpy(to,buf,is*count);
174 static inline int array_remove_slice(array_t* array,int index, int count)
178 assert(index + count <= array->next);
179 if(array_roll(array,array->next-1,index,count))
181 array->next -= count;
185 static int array_remove(array_t* array,int index)
187 return array_remove_slice(array, index, 1);
190 /* return the index for a given member */
191 static int array_index(array_t* array, void* pointer)
193 size_t offset = (char*)pointer - array->pointer;
194 assert((offset % array->item_size) == 0);
195 assert(offset/array->item_size < array->next);
196 return offset/array->item_size;
199 /* These structures are used to fake a disk and the VFAT filesystem.
200 * For this reason we need to use QEMU_PACKED. */
202 typedef struct bootsector_t {
205 uint16_t sector_size;
206 uint8_t sectors_per_cluster;
207 uint16_t reserved_sectors;
208 uint8_t number_of_fats;
209 uint16_t root_entries;
210 uint16_t total_sectors16;
212 uint16_t sectors_per_fat;
213 uint16_t sectors_per_track;
214 uint16_t number_of_heads;
215 uint32_t hidden_sectors;
216 uint32_t total_sectors;
219 uint8_t drive_number;
223 uint8_t volume_label[11];
225 uint8_t ignored[0x1c0];
228 uint32_t sectors_per_fat;
231 uint32_t first_cluster_of_root_dir;
232 uint16_t info_sector;
233 uint16_t backup_boot_sector;
234 uint8_t reserved[12];
235 uint8_t drive_number;
239 uint8_t volume_label[11];
241 uint8_t ignored[0x1a4];
245 } QEMU_PACKED bootsector_t;
253 typedef struct partition_t {
254 uint8_t attributes; /* 0x80 = bootable */
256 uint8_t fs_type; /* 0x1 = FAT12, 0x6 = FAT16, 0xe = FAT16_LBA, 0xb = FAT32, 0xc = FAT32_LBA */
258 uint32_t start_sector_long;
259 uint32_t length_sector_long;
260 } QEMU_PACKED partition_t;
262 typedef struct mbr_t {
263 uint8_t ignored[0x1b8];
266 partition_t partition[4];
270 typedef struct direntry_t {
282 } QEMU_PACKED direntry_t;
284 /* this structure are used to transparently access the files */
286 typedef struct mapping_t {
287 /* begin is the first cluster, end is the last+1 */
289 /* as s->directory is growable, no pointer may be used here */
290 unsigned int dir_index;
291 /* the clusters of a file may be in any order; this points to the first */
292 int first_mapping_index;
295 * - the offset in the file (in clusters) for a file, or
296 * - the next cluster of the directory for a directory
302 int parent_mapping_index;
306 /* path contains the full path, i.e. it always starts with s->path */
320 static void print_direntry(const struct direntry_t*);
321 static void print_mapping(const struct mapping_t* mapping);
324 /* here begins the real VVFAT driver */
326 typedef struct BDRVVVFATState {
328 BlockDriverState* bs; /* pointer to parent */
329 unsigned char first_sectors[0x40*0x200];
331 int fat_type; /* 16 or 32 */
332 array_t fat,directory,mapping;
333 char volume_label[11];
335 uint32_t offset_to_bootsector; /* 0 for floppy, 0x3f for disk */
337 unsigned int cluster_size;
338 unsigned int sectors_per_cluster;
339 unsigned int sectors_per_fat;
340 unsigned int sectors_of_root_directory;
341 uint32_t last_cluster_of_root_directory;
342 uint32_t sector_count; /* total number of sectors of the partition */
343 uint32_t cluster_count; /* total number of clusters of this partition */
344 uint32_t max_fat_value;
345 uint32_t offset_to_fat;
346 uint32_t offset_to_root_dir;
349 mapping_t* current_mapping;
350 unsigned char* cluster; /* points to current cluster */
351 unsigned char* cluster_buffer; /* points to a buffer to hold temp data */
352 unsigned int current_cluster;
361 int downcase_short_names;
363 Error *migration_blocker;
366 /* take the sector position spos and convert it to Cylinder/Head/Sector position
367 * if the position is outside the specified geometry, fill maximum value for CHS
368 * and return 1 to signal overflow.
370 static int sector2CHS(mbr_chs_t *chs, int spos, int cyls, int heads, int secs)
373 sector = spos % secs; spos /= secs;
374 head = spos % heads; spos /= heads;
377 it happens if 32bit sector positions are used, while CHS is only 24bit.
378 Windows/Dos is said to take 1023/255/63 as nonrepresentable CHS */
381 chs->cylinder = 0xFF;
384 chs->head = (uint8_t)head;
385 chs->sector = (uint8_t)( (sector+1) | ((spos>>8)<<6) );
386 chs->cylinder = (uint8_t)spos;
390 static void init_mbr(BDRVVVFATState *s, int cyls, int heads, int secs)
392 /* TODO: if the files mbr.img and bootsect.img exist, use them */
393 mbr_t* real_mbr=(mbr_t*)s->first_sectors;
394 partition_t* partition = &(real_mbr->partition[0]);
397 memset(s->first_sectors,0,512);
399 /* Win NT Disk Signature */
400 real_mbr->nt_id= cpu_to_le32(0xbe1afdfa);
402 partition->attributes=0x80; /* bootable */
404 /* LBA is used when partition is outside the CHS geometry */
405 lba = sector2CHS(&partition->start_CHS, s->offset_to_bootsector,
407 lba |= sector2CHS(&partition->end_CHS, s->bs->total_sectors - 1,
410 /*LBA partitions are identified only by start/length_sector_long not by CHS*/
411 partition->start_sector_long = cpu_to_le32(s->offset_to_bootsector);
412 partition->length_sector_long = cpu_to_le32(s->bs->total_sectors
413 - s->offset_to_bootsector);
415 /* FAT12/FAT16/FAT32 */
416 /* DOS uses different types when partition is LBA,
417 probably to prevent older versions from using CHS on them */
418 partition->fs_type = s->fat_type == 12 ? 0x1 :
419 s->fat_type == 16 ? (lba ? 0xe : 0x06) :
420 /*s->fat_type == 32*/ (lba ? 0xc : 0x0b);
422 real_mbr->magic[0]=0x55; real_mbr->magic[1]=0xaa;
425 /* direntry functions */
427 /* dest is assumed to hold 258 bytes, and pads with 0xffff up to next multiple of 26 */
428 static inline int short2long_name(char* dest,const char* src)
432 for(i=0;i<129 && src[i];i++) {
437 dest[2*i]=dest[2*i+1]=0;
438 for(i=2*i+2;(i%26);i++)
443 static inline direntry_t* create_long_filename(BDRVVVFATState* s,const char* filename)
446 int length=short2long_name(buffer,filename),
447 number_of_entries=(length+25)/26,i;
450 for(i=0;i<number_of_entries;i++) {
451 entry=array_get_next(&(s->directory));
452 entry->attributes=0xf;
453 entry->reserved[0]=0;
455 entry->name[0]=(number_of_entries-i)|(i==0?0x40:0);
457 for(i=0;i<26*number_of_entries;i++) {
459 if(offset<10) offset=1+offset;
460 else if(offset<22) offset=14+offset-10;
461 else offset=28+offset-22;
462 entry=array_get(&(s->directory),s->directory.next-1-(i/26));
463 entry->name[offset]=buffer[i];
465 return array_get(&(s->directory),s->directory.next-number_of_entries);
468 static char is_free(const direntry_t* direntry)
470 return direntry->name[0]==0xe5 || direntry->name[0]==0x00;
473 static char is_volume_label(const direntry_t* direntry)
475 return direntry->attributes == 0x28;
478 static char is_long_name(const direntry_t* direntry)
480 return direntry->attributes == 0xf;
483 static char is_short_name(const direntry_t* direntry)
485 return !is_volume_label(direntry) && !is_long_name(direntry)
486 && !is_free(direntry);
489 static char is_directory(const direntry_t* direntry)
491 return direntry->attributes & 0x10 && direntry->name[0] != 0xe5;
494 static inline char is_dot(const direntry_t* direntry)
496 return is_short_name(direntry) && direntry->name[0] == '.';
499 static char is_file(const direntry_t* direntry)
501 return is_short_name(direntry) && !is_directory(direntry);
504 static inline uint32_t begin_of_direntry(const direntry_t* direntry)
506 return le16_to_cpu(direntry->begin)|(le16_to_cpu(direntry->begin_hi)<<16);
509 static inline uint32_t filesize_of_direntry(const direntry_t* direntry)
511 return le32_to_cpu(direntry->size);
514 static void set_begin_of_direntry(direntry_t* direntry, uint32_t begin)
516 direntry->begin = cpu_to_le16(begin & 0xffff);
517 direntry->begin_hi = cpu_to_le16((begin >> 16) & 0xffff);
522 static inline uint8_t fat_chksum(const direntry_t* entry)
527 for (i = 0; i < ARRAY_SIZE(entry->name); i++) {
528 chksum = (((chksum & 0xfe) >> 1) |
529 ((chksum & 0x01) ? 0x80 : 0)) + entry->name[i];
535 /* if return_time==0, this returns the fat_date, else the fat_time */
536 static uint16_t fat_datetime(time_t time,int return_time) {
540 localtime_r(&time,t);
542 return cpu_to_le16((t->tm_sec/2)|(t->tm_min<<5)|(t->tm_hour<<11));
543 return cpu_to_le16((t->tm_mday)|((t->tm_mon+1)<<5)|((t->tm_year-80)<<9));
546 static inline void fat_set(BDRVVVFATState* s,unsigned int cluster,uint32_t value)
548 if(s->fat_type==32) {
549 uint32_t* entry=array_get(&(s->fat),cluster);
550 *entry=cpu_to_le32(value);
551 } else if(s->fat_type==16) {
552 uint16_t* entry=array_get(&(s->fat),cluster);
553 *entry=cpu_to_le16(value&0xffff);
555 int offset = (cluster*3/2);
556 unsigned char* p = array_get(&(s->fat), offset);
560 p[1] = (p[1]&0xf0) | ((value>>8)&0xf);
563 p[0] = (p[0]&0xf) | ((value&0xf)<<4);
570 static inline uint32_t fat_get(BDRVVVFATState* s,unsigned int cluster)
572 if(s->fat_type==32) {
573 uint32_t* entry=array_get(&(s->fat),cluster);
574 return le32_to_cpu(*entry);
575 } else if(s->fat_type==16) {
576 uint16_t* entry=array_get(&(s->fat),cluster);
577 return le16_to_cpu(*entry);
579 const uint8_t* x=(uint8_t*)(s->fat.pointer)+cluster*3/2;
580 return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
584 static inline int fat_eof(BDRVVVFATState* s,uint32_t fat_entry)
586 if(fat_entry>s->max_fat_value-8)
591 static inline void init_fat(BDRVVVFATState* s)
593 if (s->fat_type == 12) {
594 array_init(&(s->fat),1);
595 array_ensure_allocated(&(s->fat),
596 s->sectors_per_fat * 0x200 * 3 / 2 - 1);
598 array_init(&(s->fat),(s->fat_type==32?4:2));
599 array_ensure_allocated(&(s->fat),
600 s->sectors_per_fat * 0x200 / s->fat.item_size - 1);
602 memset(s->fat.pointer,0,s->fat.size);
604 switch(s->fat_type) {
605 case 12: s->max_fat_value=0xfff; break;
606 case 16: s->max_fat_value=0xffff; break;
607 case 32: s->max_fat_value=0x0fffffff; break;
608 default: s->max_fat_value=0; /* error... */
613 /* TODO: in create_short_filename, 0xe5->0x05 is not yet handled! */
614 /* TODO: in parse_short_filename, 0x05->0xe5 is not yet handled! */
615 static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,
616 unsigned int directory_start, const char* filename, int is_dot)
618 int i,j,long_index=s->directory.next;
619 direntry_t* entry = NULL;
620 direntry_t* entry_long = NULL;
623 entry=array_get_next(&(s->directory));
624 memset(entry->name, 0x20, sizeof(entry->name));
625 memcpy(entry->name,filename,strlen(filename));
629 entry_long=create_long_filename(s,filename);
631 i = strlen(filename);
632 for(j = i - 1; j>0 && filename[j]!='.';j--);
638 entry=array_get_next(&(s->directory));
639 memset(entry->name, 0x20, sizeof(entry->name));
640 memcpy(entry->name, filename, i);
643 for (i = 0; i < 3 && filename[j + 1 + i]; i++) {
644 entry->name[8 + i] = filename[j + 1 + i];
648 /* upcase & remove unwanted characters */
650 if(i==10 || i==7) for(;i>0 && entry->name[i]==' ';i--);
651 if(entry->name[i]<=' ' || entry->name[i]>0x7f
652 || strchr(".*?<>|\":/\\[];,+='",entry->name[i]))
654 else if(entry->name[i]>='a' && entry->name[i]<='z')
655 entry->name[i]+='A'-'a';
658 /* mangle duplicates */
660 direntry_t* entry1=array_get(&(s->directory),directory_start);
663 for(;entry1<entry;entry1++)
664 if(!is_long_name(entry1) && !memcmp(entry1->name,entry->name,11))
665 break; /* found dupe */
666 if(entry1==entry) /* no dupe found */
669 /* use all 8 characters of name */
670 if(entry->name[7]==' ') {
672 for(j=6;j>0 && entry->name[j]==' ';j--)
676 /* increment number */
677 for(j=7;j>0 && entry->name[j]=='9';j--)
680 if(entry->name[j]<'0' || entry->name[j]>'9')
687 /* calculate checksum; propagate to long name */
689 uint8_t chksum=fat_chksum(entry);
691 /* calculate anew, because realloc could have taken place */
692 entry_long=array_get(&(s->directory),long_index);
693 while(entry_long<entry && is_long_name(entry_long)) {
694 entry_long->reserved[1]=chksum;
703 * Read a directory. (the index of the corresponding mapping must be passed).
705 static int read_directory(BDRVVVFATState* s, int mapping_index)
707 mapping_t* mapping = array_get(&(s->mapping), mapping_index);
708 direntry_t* direntry;
709 const char* dirname = mapping->path;
710 int first_cluster = mapping->begin;
711 int parent_index = mapping->info.dir.parent_mapping_index;
712 mapping_t* parent_mapping = (mapping_t*)
713 (parent_index >= 0 ? array_get(&(s->mapping), parent_index) : NULL);
714 int first_cluster_of_parent = parent_mapping ? parent_mapping->begin : -1;
716 DIR* dir=opendir(dirname);
717 struct dirent* entry;
720 assert(mapping->mode & MODE_DIRECTORY);
723 mapping->end = mapping->begin;
727 i = mapping->info.dir.first_dir_index =
728 first_cluster == 0 ? 0 : s->directory.next;
730 if (first_cluster != 0) {
731 /* create the top entries of a subdirectory */
732 (void)create_short_and_long_name(s, i, ".", 1);
733 (void)create_short_and_long_name(s, i, "..", 1);
736 /* actually read the directory, and allocate the mappings */
737 while((entry=readdir(dir))) {
738 unsigned int length=strlen(dirname)+2+strlen(entry->d_name);
740 direntry_t* direntry;
742 int is_dot=!strcmp(entry->d_name,".");
743 int is_dotdot=!strcmp(entry->d_name,"..");
745 if(first_cluster == 0 && (is_dotdot || is_dot))
748 buffer = g_malloc(length);
749 snprintf(buffer,length,"%s/%s",dirname,entry->d_name);
751 if(stat(buffer,&st)<0) {
756 /* create directory entry for this file */
757 if (!is_dot && !is_dotdot) {
758 direntry = create_short_and_long_name(s, i, entry->d_name, 0);
760 direntry = array_get(&(s->directory), is_dot ? i : i + 1);
762 direntry->attributes=(S_ISDIR(st.st_mode)?0x10:0x20);
763 direntry->reserved[0]=direntry->reserved[1]=0;
764 direntry->ctime=fat_datetime(st.st_ctime,1);
765 direntry->cdate=fat_datetime(st.st_ctime,0);
766 direntry->adate=fat_datetime(st.st_atime,0);
767 direntry->begin_hi=0;
768 direntry->mtime=fat_datetime(st.st_mtime,1);
769 direntry->mdate=fat_datetime(st.st_mtime,0);
771 set_begin_of_direntry(direntry, first_cluster_of_parent);
773 set_begin_of_direntry(direntry, first_cluster);
775 direntry->begin=0; /* do that later */
776 if (st.st_size > 0x7fffffff) {
777 fprintf(stderr, "File %s is larger than 2GB\n", buffer);
782 direntry->size=cpu_to_le32(S_ISDIR(st.st_mode)?0:st.st_size);
784 /* create mapping for this file */
785 if(!is_dot && !is_dotdot && (S_ISDIR(st.st_mode) || st.st_size)) {
786 s->current_mapping = array_get_next(&(s->mapping));
787 s->current_mapping->begin=0;
788 s->current_mapping->end=st.st_size;
790 * we get the direntry of the most recent direntry, which
791 * contains the short name and all the relevant information.
793 s->current_mapping->dir_index=s->directory.next-1;
794 s->current_mapping->first_mapping_index = -1;
795 if (S_ISDIR(st.st_mode)) {
796 s->current_mapping->mode = MODE_DIRECTORY;
797 s->current_mapping->info.dir.parent_mapping_index =
800 s->current_mapping->mode = MODE_UNDEFINED;
801 s->current_mapping->info.file.offset = 0;
803 s->current_mapping->path=buffer;
804 s->current_mapping->read_only =
805 (st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0;
812 /* fill with zeroes up to the end of the cluster */
813 while(s->directory.next%(0x10*s->sectors_per_cluster)) {
814 direntry_t* direntry=array_get_next(&(s->directory));
815 memset(direntry,0,sizeof(direntry_t));
818 /* TODO: if there are more entries, bootsector has to be adjusted! */
819 #define ROOT_ENTRIES (0x02 * 0x10 * s->sectors_per_cluster)
820 if (mapping_index == 0 && s->directory.next < ROOT_ENTRIES) {
822 int cur = s->directory.next;
823 array_ensure_allocated(&(s->directory), ROOT_ENTRIES - 1);
824 s->directory.next = ROOT_ENTRIES;
825 memset(array_get(&(s->directory), cur), 0,
826 (ROOT_ENTRIES - cur) * sizeof(direntry_t));
829 /* re-get the mapping, since s->mapping was possibly realloc()ed */
830 mapping = array_get(&(s->mapping), mapping_index);
831 first_cluster += (s->directory.next - mapping->info.dir.first_dir_index)
832 * 0x20 / s->cluster_size;
833 mapping->end = first_cluster;
835 direntry = array_get(&(s->directory), mapping->dir_index);
836 set_begin_of_direntry(direntry, mapping->begin);
841 static inline uint32_t sector2cluster(BDRVVVFATState* s,off_t sector_num)
843 return (sector_num - s->offset_to_root_dir) / s->sectors_per_cluster;
846 static inline off_t cluster2sector(BDRVVVFATState* s, uint32_t cluster_num)
848 return s->offset_to_root_dir + s->sectors_per_cluster * cluster_num;
851 static int init_directories(BDRVVVFATState* s,
852 const char *dirname, int heads, int secs,
855 bootsector_t* bootsector;
858 unsigned int cluster;
860 memset(&(s->first_sectors[0]),0,0x40*0x200);
862 s->cluster_size=s->sectors_per_cluster*0x200;
863 s->cluster_buffer=g_malloc(s->cluster_size);
866 * The formula: sc = spf+1+spf*spc*(512*8/fat_type),
867 * where sc is sector_count,
868 * spf is sectors_per_fat,
869 * spc is sectors_per_clusters, and
870 * fat_type = 12, 16 or 32.
872 i = 1+s->sectors_per_cluster*0x200*8/s->fat_type;
873 s->sectors_per_fat=(s->sector_count+i)/i; /* round up */
875 s->offset_to_fat = s->offset_to_bootsector + 1;
876 s->offset_to_root_dir = s->offset_to_fat + s->sectors_per_fat * 2;
878 array_init(&(s->mapping),sizeof(mapping_t));
879 array_init(&(s->directory),sizeof(direntry_t));
881 /* add volume label */
883 direntry_t* entry=array_get_next(&(s->directory));
884 entry->attributes=0x28; /* archive | volume label */
885 memcpy(entry->name, s->volume_label, sizeof(entry->name));
888 /* Now build FAT, and write back information into directory */
891 s->cluster_count=sector2cluster(s, s->sector_count);
893 mapping = array_get_next(&(s->mapping));
895 mapping->dir_index = 0;
896 mapping->info.dir.parent_mapping_index = -1;
897 mapping->first_mapping_index = -1;
898 mapping->path = g_strdup(dirname);
899 i = strlen(mapping->path);
900 if (i > 0 && mapping->path[i - 1] == '/')
901 mapping->path[i - 1] = '\0';
902 mapping->mode = MODE_DIRECTORY;
903 mapping->read_only = 0;
904 s->path = mapping->path;
906 for (i = 0, cluster = 0; i < s->mapping.next; i++) {
907 /* MS-DOS expects the FAT to be 0 for the root directory
908 * (except for the media byte). */
909 /* LATER TODO: still true for FAT32? */
910 int fix_fat = (i != 0);
911 mapping = array_get(&(s->mapping), i);
913 if (mapping->mode & MODE_DIRECTORY) {
914 mapping->begin = cluster;
915 if(read_directory(s, i)) {
916 error_setg(errp, "Could not read directory %s",
920 mapping = array_get(&(s->mapping), i);
922 assert(mapping->mode == MODE_UNDEFINED);
923 mapping->mode=MODE_NORMAL;
924 mapping->begin = cluster;
925 if (mapping->end > 0) {
926 direntry_t* direntry = array_get(&(s->directory),
929 mapping->end = cluster + 1 + (mapping->end-1)/s->cluster_size;
930 set_begin_of_direntry(direntry, mapping->begin);
932 mapping->end = cluster + 1;
937 assert(mapping->begin < mapping->end);
939 /* next free cluster */
940 cluster = mapping->end;
942 if(cluster > s->cluster_count) {
944 "Directory does not fit in FAT%d (capacity %.2f MB)",
945 s->fat_type, s->sector_count / 2000.0);
949 /* fix fat for entry */
952 for(j = mapping->begin; j < mapping->end - 1; j++)
954 fat_set(s, mapping->end - 1, s->max_fat_value);
958 mapping = array_get(&(s->mapping), 0);
959 s->sectors_of_root_directory = mapping->end * s->sectors_per_cluster;
960 s->last_cluster_of_root_directory = mapping->end;
962 /* the FAT signature */
963 fat_set(s,0,s->max_fat_value);
964 fat_set(s,1,s->max_fat_value);
966 s->current_mapping = NULL;
968 bootsector = (bootsector_t *)(s->first_sectors
969 + s->offset_to_bootsector * 0x200);
970 bootsector->jump[0]=0xeb;
971 bootsector->jump[1]=0x3e;
972 bootsector->jump[2]=0x90;
973 memcpy(bootsector->name,"QEMU ",8);
974 bootsector->sector_size=cpu_to_le16(0x200);
975 bootsector->sectors_per_cluster=s->sectors_per_cluster;
976 bootsector->reserved_sectors=cpu_to_le16(1);
977 bootsector->number_of_fats=0x2; /* number of FATs */
978 bootsector->root_entries=cpu_to_le16(s->sectors_of_root_directory*0x10);
979 bootsector->total_sectors16=s->sector_count>0xffff?0:cpu_to_le16(s->sector_count);
980 /* media descriptor: hard disk=0xf8, floppy=0xf0 */
981 bootsector->media_type = (s->offset_to_bootsector > 0 ? 0xf8 : 0xf0);
982 s->fat.pointer[0] = bootsector->media_type;
983 bootsector->sectors_per_fat=cpu_to_le16(s->sectors_per_fat);
984 bootsector->sectors_per_track = cpu_to_le16(secs);
985 bootsector->number_of_heads = cpu_to_le16(heads);
986 bootsector->hidden_sectors = cpu_to_le32(s->offset_to_bootsector);
987 bootsector->total_sectors=cpu_to_le32(s->sector_count>0xffff?s->sector_count:0);
989 /* LATER TODO: if FAT32, this is wrong */
990 /* drive_number: fda=0, hda=0x80 */
991 bootsector->u.fat16.drive_number = s->offset_to_bootsector == 0 ? 0 : 0x80;
992 bootsector->u.fat16.signature=0x29;
993 bootsector->u.fat16.id=cpu_to_le32(0xfabe1afd);
995 memcpy(bootsector->u.fat16.volume_label, s->volume_label,
996 sizeof(bootsector->u.fat16.volume_label));
997 memcpy(bootsector->u.fat16.fat_type,
998 s->fat_type == 12 ? "FAT12 " : "FAT16 ", 8);
999 bootsector->magic[0]=0x55; bootsector->magic[1]=0xaa;
1005 static BDRVVVFATState *vvv = NULL;
1008 static int enable_write_target(BlockDriverState *bs, Error **errp);
1009 static int is_consistent(BDRVVVFATState *s);
1011 static QemuOptsList runtime_opts = {
1013 .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
1017 .type = QEMU_OPT_STRING,
1018 .help = "Host directory to map to the vvfat device",
1022 .type = QEMU_OPT_NUMBER,
1023 .help = "FAT type (12, 16 or 32)",
1027 .type = QEMU_OPT_BOOL,
1028 .help = "Create a floppy rather than a hard disk image",
1032 .type = QEMU_OPT_STRING,
1033 .help = "Use a volume label other than QEMU VVFAT",
1037 .type = QEMU_OPT_BOOL,
1038 .help = "Make the image writable",
1040 { /* end of list */ }
1044 static void vvfat_parse_filename(const char *filename, QDict *options,
1048 bool floppy = false;
1052 if (!strstart(filename, "fat:", NULL)) {
1053 error_setg(errp, "File name string must start with 'fat:'");
1058 if (strstr(filename, ":32:")) {
1060 } else if (strstr(filename, ":16:")) {
1062 } else if (strstr(filename, ":12:")) {
1066 if (strstr(filename, ":floppy:")) {
1070 if (strstr(filename, ":rw:")) {
1074 /* Get the directory name without options */
1075 i = strrchr(filename, ':') - filename;
1077 if (filename[i - 2] == ':' && qemu_isalpha(filename[i - 1])) {
1078 /* workaround for DOS drive names */
1084 /* Fill in the options QDict */
1085 qdict_put_str(options, "dir", filename);
1086 qdict_put_int(options, "fat-type", fat_type);
1087 qdict_put_bool(options, "floppy", floppy);
1088 qdict_put_bool(options, "rw", rw);
1091 static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
1094 BDRVVVFATState *s = bs->opaque;
1095 int cyls, heads, secs;
1097 const char *dirname, *label;
1099 Error *local_err = NULL;
1106 opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
1107 qemu_opts_absorb_qdict(opts, options, &local_err);
1109 error_propagate(errp, local_err);
1114 dirname = qemu_opt_get(opts, "dir");
1116 error_setg(errp, "vvfat block driver requires a 'dir' option");
1121 s->fat_type = qemu_opt_get_number(opts, "fat-type", 0);
1122 floppy = qemu_opt_get_bool(opts, "floppy", false);
1124 memset(s->volume_label, ' ', sizeof(s->volume_label));
1125 label = qemu_opt_get(opts, "label");
1127 size_t label_length = strlen(label);
1128 if (label_length > 11) {
1129 error_setg(errp, "vvfat label cannot be longer than 11 bytes");
1133 memcpy(s->volume_label, label, label_length);
1135 memcpy(s->volume_label, "QEMU VVFAT", 10);
1139 /* 1.44MB or 2.88MB floppy. 2.88MB can be FAT12 (default) or FAT16. */
1143 s->sectors_per_cluster = 2;
1145 secs = s->fat_type == 12 ? 18 : 36;
1146 s->sectors_per_cluster = 1;
1151 /* 32MB or 504MB disk*/
1155 s->offset_to_bootsector = 0x3f;
1156 cyls = s->fat_type == 12 ? 64 : 1024;
1161 switch (s->fat_type) {
1163 fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. "
1164 "You are welcome to do so!\n");
1170 error_setg(errp, "Valid FAT types are only 12, 16 and 32");
1178 /* LATER TODO: if FAT32, adjust */
1179 s->sectors_per_cluster=0x10;
1181 s->current_cluster=0xffffffff;
1184 s->qcow_filename = NULL;
1186 s->downcase_short_names = 1;
1188 fprintf(stderr, "vvfat %s chs %d,%d,%d\n",
1189 dirname, cyls, heads, secs);
1191 s->sector_count = cyls * heads * secs - s->offset_to_bootsector;
1193 if (qemu_opt_get_bool(opts, "rw", false)) {
1194 if (!bdrv_is_read_only(bs)) {
1195 ret = enable_write_target(bs, errp);
1202 "Unable to set VVFAT to 'rw' when drive is read-only");
1206 /* read only is the default for safety */
1207 ret = bdrv_set_read_only(bs, true, &local_err);
1209 error_propagate(errp, local_err);
1214 bs->total_sectors = cyls * heads * secs;
1216 if (init_directories(s, dirname, heads, secs, errp)) {
1221 s->sector_count = s->offset_to_root_dir
1222 + s->sectors_per_cluster * s->cluster_count;
1224 /* Disable migration when vvfat is used rw */
1226 error_setg(&s->migration_blocker,
1227 "The vvfat (rw) format used by node '%s' "
1228 "does not support live migration",
1229 bdrv_get_device_or_node_name(bs));
1230 ret = migrate_add_blocker(s->migration_blocker, &local_err);
1232 error_propagate(errp, local_err);
1233 error_free(s->migration_blocker);
1238 if (s->offset_to_bootsector > 0) {
1239 init_mbr(s, cyls, heads, secs);
1242 qemu_co_mutex_init(&s->lock);
1246 qemu_opts_del(opts);
1250 static void vvfat_refresh_limits(BlockDriverState *bs, Error **errp)
1252 bs->bl.request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O */
1255 static inline void vvfat_close_current_file(BDRVVVFATState *s)
1257 if(s->current_mapping) {
1258 s->current_mapping = NULL;
1259 if (s->current_fd) {
1260 qemu_close(s->current_fd);
1264 s->current_cluster = -1;
1267 /* mappings between index1 and index2-1 are supposed to be ordered
1268 * return value is the index of the last mapping for which end>cluster_num
1270 static inline int find_mapping_for_cluster_aux(BDRVVVFATState* s,int cluster_num,int index1,int index2)
1275 index3=(index1+index2)/2;
1276 mapping=array_get(&(s->mapping),index3);
1277 assert(mapping->begin < mapping->end);
1278 if(mapping->begin>=cluster_num) {
1279 assert(index2!=index3 || index2==0);
1285 return mapping->end<=cluster_num ? index2 : index1;
1288 assert(index1<=index2);
1289 DLOG(mapping=array_get(&(s->mapping),index1);
1290 assert(mapping->begin<=cluster_num);
1291 assert(index2 >= s->mapping.next ||
1292 ((mapping = array_get(&(s->mapping),index2)) &&
1293 mapping->end>cluster_num)));
1297 static inline mapping_t* find_mapping_for_cluster(BDRVVVFATState* s,int cluster_num)
1299 int index=find_mapping_for_cluster_aux(s,cluster_num,0,s->mapping.next);
1301 if(index>=s->mapping.next)
1303 mapping=array_get(&(s->mapping),index);
1304 if(mapping->begin>cluster_num)
1306 assert(mapping->begin<=cluster_num && mapping->end>cluster_num);
1310 static int open_file(BDRVVVFATState* s,mapping_t* mapping)
1314 if(!s->current_mapping ||
1315 strcmp(s->current_mapping->path,mapping->path)) {
1317 int fd = qemu_open(mapping->path, O_RDONLY | O_BINARY | O_LARGEFILE);
1320 vvfat_close_current_file(s);
1322 s->current_mapping = mapping;
1327 static inline int read_cluster(BDRVVVFATState *s,int cluster_num)
1329 if(s->current_cluster != cluster_num) {
1332 assert(!s->current_mapping || s->current_fd || (s->current_mapping->mode & MODE_DIRECTORY));
1333 if(!s->current_mapping
1334 || s->current_mapping->begin>cluster_num
1335 || s->current_mapping->end<=cluster_num) {
1336 /* binary search of mappings for file */
1337 mapping_t* mapping=find_mapping_for_cluster(s,cluster_num);
1339 assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
1341 if (mapping && mapping->mode & MODE_DIRECTORY) {
1342 vvfat_close_current_file(s);
1343 s->current_mapping = mapping;
1344 read_cluster_directory:
1345 offset = s->cluster_size*(cluster_num-s->current_mapping->begin);
1346 s->cluster = (unsigned char*)s->directory.pointer+offset
1347 + 0x20*s->current_mapping->info.dir.first_dir_index;
1348 assert(((s->cluster-(unsigned char*)s->directory.pointer)%s->cluster_size)==0);
1349 assert((char*)s->cluster+s->cluster_size <= s->directory.pointer+s->directory.next*s->directory.item_size);
1350 s->current_cluster = cluster_num;
1354 if(open_file(s,mapping))
1356 } else if (s->current_mapping->mode & MODE_DIRECTORY)
1357 goto read_cluster_directory;
1359 assert(s->current_fd);
1361 offset=s->cluster_size*(cluster_num-s->current_mapping->begin)+s->current_mapping->info.file.offset;
1362 if(lseek(s->current_fd, offset, SEEK_SET)!=offset)
1364 s->cluster=s->cluster_buffer;
1365 result=read(s->current_fd,s->cluster,s->cluster_size);
1367 s->current_cluster = -1;
1370 s->current_cluster = cluster_num;
1376 static void print_direntry(const direntry_t* direntry)
1381 fprintf(stderr, "direntry %p: ", direntry);
1384 if(is_long_name(direntry)) {
1385 unsigned char* c=(unsigned char*)direntry;
1387 for(i=1;i<11 && c[i] && c[i]!=0xff;i+=2)
1388 #define ADD_CHAR(c) {buffer[j] = (c); if (buffer[j] < ' ') buffer[j] = 0xb0; j++;}
1390 for(i=14;i<26 && c[i] && c[i]!=0xff;i+=2)
1392 for(i=28;i<32 && c[i] && c[i]!=0xff;i+=2)
1395 fprintf(stderr, "%s\n", buffer);
1399 ADD_CHAR(direntry->name[i]);
1401 fprintf(stderr,"%s attributes=0x%02x begin=%d size=%d\n",
1403 direntry->attributes,
1404 begin_of_direntry(direntry),le32_to_cpu(direntry->size));
1408 static void print_mapping(const mapping_t* mapping)
1410 fprintf(stderr, "mapping (%p): begin, end = %d, %d, dir_index = %d, "
1411 "first_mapping_index = %d, name = %s, mode = 0x%x, " ,
1412 mapping, mapping->begin, mapping->end, mapping->dir_index,
1413 mapping->first_mapping_index, mapping->path, mapping->mode);
1415 if (mapping->mode & MODE_DIRECTORY)
1416 fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
1418 fprintf(stderr, "offset = %d\n", mapping->info.file.offset);
1422 static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
1423 uint8_t *buf, int nb_sectors)
1425 BDRVVVFATState *s = bs->opaque;
1428 for(i=0;i<nb_sectors;i++,sector_num++) {
1429 if (sector_num >= bs->total_sectors)
1434 ret = bdrv_is_allocated(s->qcow->bs, sector_num,
1435 nb_sectors - i, &n);
1440 DLOG(fprintf(stderr, "sectors %d+%d allocated\n",
1441 (int)sector_num, n));
1442 if (bdrv_read(s->qcow, sector_num, buf + i * 0x200, n)) {
1446 sector_num += n - 1;
1449 DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num));
1451 if (sector_num < s->offset_to_root_dir) {
1452 if (sector_num < s->offset_to_fat) {
1453 memcpy(buf + i * 0x200,
1454 &(s->first_sectors[sector_num * 0x200]),
1456 } else if (sector_num < s->offset_to_fat + s->sectors_per_fat) {
1457 memcpy(buf + i * 0x200,
1458 &(s->fat.pointer[(sector_num
1459 - s->offset_to_fat) * 0x200]),
1461 } else if (sector_num < s->offset_to_root_dir) {
1462 memcpy(buf + i * 0x200,
1463 &(s->fat.pointer[(sector_num - s->offset_to_fat
1464 - s->sectors_per_fat) * 0x200]),
1468 uint32_t sector = sector_num - s->offset_to_root_dir,
1469 sector_offset_in_cluster=(sector%s->sectors_per_cluster),
1470 cluster_num=sector/s->sectors_per_cluster;
1471 if(cluster_num > s->cluster_count || read_cluster(s, cluster_num) != 0) {
1472 /* LATER TODO: strict: return -1; */
1473 memset(buf+i*0x200,0,0x200);
1476 memcpy(buf+i*0x200,s->cluster+sector_offset_in_cluster*0x200,0x200);
1482 static int coroutine_fn
1483 vvfat_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
1484 QEMUIOVector *qiov, int flags)
1487 BDRVVVFATState *s = bs->opaque;
1488 uint64_t sector_num = offset >> BDRV_SECTOR_BITS;
1489 int nb_sectors = bytes >> BDRV_SECTOR_BITS;
1492 assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
1493 assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
1495 buf = g_try_malloc(bytes);
1496 if (bytes && buf == NULL) {
1500 qemu_co_mutex_lock(&s->lock);
1501 ret = vvfat_read(bs, sector_num, buf, nb_sectors);
1502 qemu_co_mutex_unlock(&s->lock);
1504 qemu_iovec_from_buf(qiov, 0, buf, bytes);
1510 /* LATER TODO: statify all functions */
1513 * Idea of the write support (use snapshot):
1515 * 1. check if all data is consistent, recording renames, modifications,
1516 * new files and directories (in s->commits).
1518 * 2. if the data is not consistent, stop committing
1520 * 3. handle renames, and create new files and directories (do not yet
1521 * write their contents)
1523 * 4. walk the directories, fixing the mapping and direntries, and marking
1524 * the handled mappings as not deleted
1526 * 5. commit the contents of the files
1528 * 6. handle deleted files and directories
1532 typedef struct commit_t {
1535 struct { uint32_t cluster; } rename;
1536 struct { int dir_index; uint32_t modified_offset; } writeout;
1537 struct { uint32_t first_cluster; } new_file;
1538 struct { uint32_t cluster; } mkdir;
1540 /* DELETEs and RMDIRs are handled differently: see handle_deletes() */
1542 ACTION_RENAME, ACTION_WRITEOUT, ACTION_NEW_FILE, ACTION_MKDIR
1546 static void clear_commits(BDRVVVFATState* s)
1549 DLOG(fprintf(stderr, "clear_commits (%d commits)\n", s->commits.next));
1550 for (i = 0; i < s->commits.next; i++) {
1551 commit_t* commit = array_get(&(s->commits), i);
1552 assert(commit->path || commit->action == ACTION_WRITEOUT);
1553 if (commit->action != ACTION_WRITEOUT) {
1554 assert(commit->path);
1555 g_free(commit->path);
1557 assert(commit->path == NULL);
1559 s->commits.next = 0;
1562 static void schedule_rename(BDRVVVFATState* s,
1563 uint32_t cluster, char* new_path)
1565 commit_t* commit = array_get_next(&(s->commits));
1566 commit->path = new_path;
1567 commit->param.rename.cluster = cluster;
1568 commit->action = ACTION_RENAME;
1571 static void schedule_writeout(BDRVVVFATState* s,
1572 int dir_index, uint32_t modified_offset)
1574 commit_t* commit = array_get_next(&(s->commits));
1575 commit->path = NULL;
1576 commit->param.writeout.dir_index = dir_index;
1577 commit->param.writeout.modified_offset = modified_offset;
1578 commit->action = ACTION_WRITEOUT;
1581 static void schedule_new_file(BDRVVVFATState* s,
1582 char* path, uint32_t first_cluster)
1584 commit_t* commit = array_get_next(&(s->commits));
1585 commit->path = path;
1586 commit->param.new_file.first_cluster = first_cluster;
1587 commit->action = ACTION_NEW_FILE;
1590 static void schedule_mkdir(BDRVVVFATState* s, uint32_t cluster, char* path)
1592 commit_t* commit = array_get_next(&(s->commits));
1593 commit->path = path;
1594 commit->param.mkdir.cluster = cluster;
1595 commit->action = ACTION_MKDIR;
1600 * Since the sequence number is at most 0x3f, and the filename
1601 * length is at most 13 times the sequence number, the maximal
1602 * filename length is 0x3f * 13 bytes.
1604 unsigned char name[0x3f * 13 + 1];
1606 int sequence_number;
1609 static void lfn_init(long_file_name* lfn)
1611 lfn->sequence_number = lfn->len = 0;
1612 lfn->checksum = 0x100;
1615 /* return 0 if parsed successfully, > 0 if no long name, < 0 if error */
1616 static int parse_long_name(long_file_name* lfn,
1617 const direntry_t* direntry)
1620 const unsigned char* pointer = (const unsigned char*)direntry;
1622 if (!is_long_name(direntry))
1625 if (pointer[0] & 0x40) {
1626 lfn->sequence_number = pointer[0] & 0x3f;
1627 lfn->checksum = pointer[13];
1629 lfn->name[lfn->sequence_number * 13] = 0;
1630 } else if ((pointer[0] & 0x3f) != --lfn->sequence_number)
1632 else if (pointer[13] != lfn->checksum)
1634 else if (pointer[12] || pointer[26] || pointer[27])
1637 offset = 13 * (lfn->sequence_number - 1);
1638 for (i = 0, j = 1; i < 13; i++, j+=2) {
1644 if (pointer[j+1] == 0)
1645 lfn->name[offset + i] = pointer[j];
1646 else if (pointer[j+1] != 0xff || (pointer[0] & 0x40) == 0)
1649 lfn->name[offset + i] = 0;
1652 if (pointer[0] & 0x40)
1653 lfn->len = offset + strlen((char*)lfn->name + offset);
1658 /* returns 0 if successful, >0 if no short_name, and <0 on error */
1659 static int parse_short_name(BDRVVVFATState* s,
1660 long_file_name* lfn, direntry_t* direntry)
1664 if (!is_short_name(direntry))
1667 for (j = 7; j >= 0 && direntry->name[j] == ' '; j--);
1668 for (i = 0; i <= j; i++) {
1669 if (direntry->name[i] <= ' ' || direntry->name[i] > 0x7f)
1671 else if (s->downcase_short_names)
1672 lfn->name[i] = qemu_tolower(direntry->name[i]);
1674 lfn->name[i] = direntry->name[i];
1677 for (j = 2; j >= 0 && direntry->name[8 + j] == ' '; j--) {
1680 lfn->name[i++] = '.';
1681 lfn->name[i + j + 1] = '\0';
1682 for (;j >= 0; j--) {
1683 uint8_t c = direntry->name[8 + j];
1684 if (c <= ' ' || c > 0x7f) {
1686 } else if (s->downcase_short_names) {
1687 lfn->name[i + j] = qemu_tolower(c);
1689 lfn->name[i + j] = c;
1693 lfn->name[i + j + 1] = '\0';
1695 lfn->len = strlen((char*)lfn->name);
1700 static inline uint32_t modified_fat_get(BDRVVVFATState* s,
1701 unsigned int cluster)
1703 if (cluster < s->last_cluster_of_root_directory) {
1704 if (cluster + 1 == s->last_cluster_of_root_directory)
1705 return s->max_fat_value;
1710 if (s->fat_type==32) {
1711 uint32_t* entry=((uint32_t*)s->fat2)+cluster;
1712 return le32_to_cpu(*entry);
1713 } else if (s->fat_type==16) {
1714 uint16_t* entry=((uint16_t*)s->fat2)+cluster;
1715 return le16_to_cpu(*entry);
1717 const uint8_t* x=s->fat2+cluster*3/2;
1718 return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
1722 static inline bool cluster_was_modified(BDRVVVFATState *s,
1723 uint32_t cluster_num)
1725 int was_modified = 0;
1728 if (s->qcow == NULL) {
1732 for (i = 0; !was_modified && i < s->sectors_per_cluster; i++) {
1733 was_modified = bdrv_is_allocated(s->qcow->bs,
1734 cluster2sector(s, cluster_num) + i,
1739 * Note that this treats failures to learn allocation status the
1740 * same as if an allocation has occurred. It's as safe as
1741 * anything else, given that a failure to learn allocation status
1742 * will probably result in more failures.
1744 return !!was_modified;
1747 static const char* get_basename(const char* path)
1749 char* basename = strrchr(path, '/');
1750 if (basename == NULL)
1753 return basename + 1; /* strip '/' */
1757 * The array s->used_clusters holds the states of the clusters. If it is
1758 * part of a file, it has bit 2 set, in case of a directory, bit 1. If it
1759 * was modified, bit 3 is set.
1760 * If any cluster is allocated, but not part of a file or directory, this
1761 * driver refuses to commit.
1764 USED_DIRECTORY = 1, USED_FILE = 2, USED_ANY = 3, USED_ALLOCATED = 4
1768 * get_cluster_count_for_direntry() not only determines how many clusters
1769 * are occupied by direntry, but also if it was renamed or modified.
1771 * A file is thought to be renamed *only* if there already was a file with
1772 * exactly the same first cluster, but a different name.
1774 * Further, the files/directories handled by this function are
1775 * assumed to be *not* deleted (and *only* those).
1777 static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
1778 direntry_t* direntry, const char* path)
1781 * This is a little bit tricky:
1782 * IF the guest OS just inserts a cluster into the file chain,
1783 * and leaves the rest alone, (i.e. the original file had clusters
1784 * 15 -> 16, but now has 15 -> 32 -> 16), then the following happens:
1786 * - do_commit will write the cluster into the file at the given
1789 * - the cluster which is overwritten should be moved to a later
1790 * position in the file.
1792 * I am not aware that any OS does something as braindead, but this
1793 * situation could happen anyway when not committing for a long time.
1794 * Just to be sure that this does not bite us, detect it, and copy the
1795 * contents of the clusters to-be-overwritten into the qcow.
1798 int was_modified = 0;
1801 uint32_t cluster_num = begin_of_direntry(direntry);
1802 uint32_t offset = 0;
1803 int first_mapping_index = -1;
1804 mapping_t* mapping = NULL;
1805 const char* basename2 = NULL;
1807 vvfat_close_current_file(s);
1809 /* the root directory */
1810 if (cluster_num == 0)
1815 basename2 = get_basename(path);
1817 mapping = find_mapping_for_cluster(s, cluster_num);
1820 const char* basename;
1822 assert(mapping->mode & MODE_DELETED);
1823 mapping->mode &= ~MODE_DELETED;
1825 basename = get_basename(mapping->path);
1827 assert(mapping->mode & MODE_NORMAL);
1830 if (strcmp(basename, basename2))
1831 schedule_rename(s, cluster_num, g_strdup(path));
1832 } else if (is_file(direntry))
1834 schedule_new_file(s, g_strdup(path), cluster_num);
1843 if (!copy_it && cluster_was_modified(s, cluster_num)) {
1844 if (mapping == NULL ||
1845 mapping->begin > cluster_num ||
1846 mapping->end <= cluster_num)
1847 mapping = find_mapping_for_cluster(s, cluster_num);
1851 (mapping->mode & MODE_DIRECTORY) == 0) {
1853 /* was modified in qcow */
1854 if (offset != mapping->info.file.offset + s->cluster_size
1855 * (cluster_num - mapping->begin)) {
1856 /* offset of this cluster in file chain has changed */
1859 } else if (offset == 0) {
1860 const char* basename = get_basename(mapping->path);
1862 if (strcmp(basename, basename2))
1864 first_mapping_index = array_index(&(s->mapping), mapping);
1867 if (mapping->first_mapping_index != first_mapping_index
1868 && mapping->info.file.offset > 0) {
1873 /* need to write out? */
1874 if (!was_modified && is_file(direntry)) {
1876 schedule_writeout(s, mapping->dir_index, offset);
1884 * This is horribly inefficient, but that is okay, since
1885 * it is rarely executed, if at all.
1887 int64_t offset = cluster2sector(s, cluster_num);
1889 vvfat_close_current_file(s);
1890 for (i = 0; i < s->sectors_per_cluster; i++) {
1893 res = bdrv_is_allocated(s->qcow->bs, offset + i, 1, &dummy);
1898 res = vvfat_read(s->bs, offset, s->cluster_buffer, 1);
1902 res = bdrv_write(s->qcow, offset, s->cluster_buffer, 1);
1912 if (s->used_clusters[cluster_num] & USED_ANY)
1914 s->used_clusters[cluster_num] = USED_FILE;
1916 cluster_num = modified_fat_get(s, cluster_num);
1918 if (fat_eof(s, cluster_num))
1920 else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
1923 offset += s->cluster_size;
1928 * This function looks at the modified data (qcow).
1929 * It returns 0 upon inconsistency or error, and the number of clusters
1930 * used by the directory, its subdirectories and their files.
1932 static int check_directory_consistency(BDRVVVFATState *s,
1933 int cluster_num, const char* path)
1936 unsigned char* cluster = g_malloc(s->cluster_size);
1937 direntry_t* direntries = (direntry_t*)cluster;
1938 mapping_t* mapping = find_mapping_for_cluster(s, cluster_num);
1941 int path_len = strlen(path);
1942 char path2[PATH_MAX + 1];
1944 assert(path_len < PATH_MAX); /* len was tested before! */
1945 pstrcpy(path2, sizeof(path2), path);
1946 path2[path_len] = '/';
1947 path2[path_len + 1] = '\0';
1950 const char* basename = get_basename(mapping->path);
1951 const char* basename2 = get_basename(path);
1953 assert(mapping->mode & MODE_DIRECTORY);
1955 assert(mapping->mode & MODE_DELETED);
1956 mapping->mode &= ~MODE_DELETED;
1958 if (strcmp(basename, basename2))
1959 schedule_rename(s, cluster_num, g_strdup(path));
1962 schedule_mkdir(s, cluster_num, g_strdup(path));
1971 if (s->used_clusters[cluster_num] & USED_ANY) {
1972 fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
1975 s->used_clusters[cluster_num] = USED_DIRECTORY;
1977 DLOG(fprintf(stderr, "read cluster %d (sector %d)\n", (int)cluster_num, (int)cluster2sector(s, cluster_num)));
1978 subret = vvfat_read(s->bs, cluster2sector(s, cluster_num), cluster,
1979 s->sectors_per_cluster);
1981 fprintf(stderr, "Error fetching direntries\n");
1987 for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
1988 int cluster_count = 0;
1990 DLOG(fprintf(stderr, "check direntry %d:\n", i); print_direntry(direntries + i));
1991 if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
1992 is_free(direntries + i))
1995 subret = parse_long_name(&lfn, direntries + i);
1997 fprintf(stderr, "Error in long name\n");
2000 if (subret == 0 || is_free(direntries + i))
2003 if (fat_chksum(direntries+i) != lfn.checksum) {
2004 subret = parse_short_name(s, &lfn, direntries + i);
2006 fprintf(stderr, "Error in short name (%d)\n", subret);
2009 if (subret > 0 || !strcmp((char*)lfn.name, ".")
2010 || !strcmp((char*)lfn.name, ".."))
2013 lfn.checksum = 0x100; /* cannot use long name twice */
2015 if (path_len + 1 + lfn.len >= PATH_MAX) {
2016 fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
2019 pstrcpy(path2 + path_len + 1, sizeof(path2) - path_len - 1,
2022 if (is_directory(direntries + i)) {
2023 if (begin_of_direntry(direntries + i) == 0) {
2024 DLOG(fprintf(stderr, "invalid begin for directory: %s\n", path2); print_direntry(direntries + i));
2027 cluster_count = check_directory_consistency(s,
2028 begin_of_direntry(direntries + i), path2);
2029 if (cluster_count == 0) {
2030 DLOG(fprintf(stderr, "problem in directory %s:\n", path2); print_direntry(direntries + i));
2033 } else if (is_file(direntries + i)) {
2034 /* check file size with FAT */
2035 cluster_count = get_cluster_count_for_direntry(s, direntries + i, path2);
2036 if (cluster_count !=
2037 DIV_ROUND_UP(le32_to_cpu(direntries[i].size), s->cluster_size)) {
2038 DLOG(fprintf(stderr, "Cluster count mismatch\n"));
2042 abort(); /* cluster_count = 0; */
2044 ret += cluster_count;
2047 cluster_num = modified_fat_get(s, cluster_num);
2048 } while(!fat_eof(s, cluster_num));
2054 /* returns 1 on success */
2055 static int is_consistent(BDRVVVFATState* s)
2058 int used_clusters_count = 0;
2062 * - get modified FAT
2063 * - compare the two FATs (TODO)
2064 * - get buffer for marking used clusters
2065 * - recurse direntries from root (using bs->bdrv_read to make
2066 * sure to get the new data)
2067 * - check that the FAT agrees with the size
2068 * - count the number of clusters occupied by this directory and
2070 * - check that the cumulative used cluster count agrees with the
2072 * - if all is fine, return number of used clusters
2074 if (s->fat2 == NULL) {
2075 int size = 0x200 * s->sectors_per_fat;
2076 s->fat2 = g_malloc(size);
2077 memcpy(s->fat2, s->fat.pointer, size);
2079 check = vvfat_read(s->bs,
2080 s->offset_to_fat, s->fat2, s->sectors_per_fat);
2082 fprintf(stderr, "Could not copy fat\n");
2085 assert (s->used_clusters);
2086 for (i = 0; i < sector2cluster(s, s->sector_count); i++)
2087 s->used_clusters[i] &= ~USED_ANY;
2091 /* mark every mapped file/directory as deleted.
2092 * (check_directory_consistency() will unmark those still present). */
2094 for (i = 0; i < s->mapping.next; i++) {
2095 mapping_t* mapping = array_get(&(s->mapping), i);
2096 if (mapping->first_mapping_index < 0)
2097 mapping->mode |= MODE_DELETED;
2100 used_clusters_count = check_directory_consistency(s, 0, s->path);
2101 if (used_clusters_count <= 0) {
2102 DLOG(fprintf(stderr, "problem in directory\n"));
2106 check = s->last_cluster_of_root_directory;
2107 for (i = check; i < sector2cluster(s, s->sector_count); i++) {
2108 if (modified_fat_get(s, i)) {
2109 if(!s->used_clusters[i]) {
2110 DLOG(fprintf(stderr, "FAT was modified (%d), but cluster is not used?\n", i));
2116 if (s->used_clusters[i] == USED_ALLOCATED) {
2117 /* allocated, but not used... */
2118 DLOG(fprintf(stderr, "unused, modified cluster: %d\n", i));
2123 if (check != used_clusters_count)
2126 return used_clusters_count;
2129 static inline void adjust_mapping_indices(BDRVVVFATState* s,
2130 int offset, int adjust)
2134 for (i = 0; i < s->mapping.next; i++) {
2135 mapping_t* mapping = array_get(&(s->mapping), i);
2137 #define ADJUST_MAPPING_INDEX(name) \
2138 if (mapping->name >= offset) \
2139 mapping->name += adjust
2141 ADJUST_MAPPING_INDEX(first_mapping_index);
2142 if (mapping->mode & MODE_DIRECTORY)
2143 ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
2147 /* insert or update mapping */
2148 static mapping_t* insert_mapping(BDRVVVFATState* s,
2149 uint32_t begin, uint32_t end)
2152 * - find mapping where mapping->begin >= begin,
2153 * - if mapping->begin > begin: insert
2154 * - adjust all references to mappings!
2158 int index = find_mapping_for_cluster_aux(s, begin, 0, s->mapping.next);
2159 mapping_t* mapping = NULL;
2160 mapping_t* first_mapping = array_get(&(s->mapping), 0);
2162 if (index < s->mapping.next && (mapping = array_get(&(s->mapping), index))
2163 && mapping->begin < begin) {
2164 mapping->end = begin;
2166 mapping = array_get(&(s->mapping), index);
2168 if (index >= s->mapping.next || mapping->begin > begin) {
2169 mapping = array_insert(&(s->mapping), index, 1);
2170 mapping->path = NULL;
2171 adjust_mapping_indices(s, index, +1);
2174 mapping->begin = begin;
2177 DLOG(mapping_t* next_mapping;
2178 assert(index + 1 >= s->mapping.next ||
2179 ((next_mapping = array_get(&(s->mapping), index + 1)) &&
2180 next_mapping->begin >= end)));
2182 if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
2183 s->current_mapping = array_get(&(s->mapping),
2184 s->current_mapping - first_mapping);
2189 static int remove_mapping(BDRVVVFATState* s, int mapping_index)
2191 mapping_t* mapping = array_get(&(s->mapping), mapping_index);
2192 mapping_t* first_mapping = array_get(&(s->mapping), 0);
2195 if (mapping->first_mapping_index < 0) {
2196 g_free(mapping->path);
2199 /* remove from s->mapping */
2200 array_remove(&(s->mapping), mapping_index);
2202 /* adjust all references to mappings */
2203 adjust_mapping_indices(s, mapping_index, -1);
2205 if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
2206 s->current_mapping = array_get(&(s->mapping),
2207 s->current_mapping - first_mapping);
2212 static void adjust_dirindices(BDRVVVFATState* s, int offset, int adjust)
2215 for (i = 0; i < s->mapping.next; i++) {
2216 mapping_t* mapping = array_get(&(s->mapping), i);
2217 if (mapping->dir_index >= offset)
2218 mapping->dir_index += adjust;
2219 if ((mapping->mode & MODE_DIRECTORY) &&
2220 mapping->info.dir.first_dir_index >= offset)
2221 mapping->info.dir.first_dir_index += adjust;
2225 static direntry_t* insert_direntries(BDRVVVFATState* s,
2226 int dir_index, int count)
2229 * make room in s->directory,
2232 direntry_t* result = array_insert(&(s->directory), dir_index, count);
2235 adjust_dirindices(s, dir_index, count);
2239 static int remove_direntries(BDRVVVFATState* s, int dir_index, int count)
2241 int ret = array_remove_slice(&(s->directory), dir_index, count);
2244 adjust_dirindices(s, dir_index, -count);
2249 * Adapt the mappings of the cluster chain starting at first cluster
2250 * (i.e. if a file starts at first_cluster, the chain is followed according
2251 * to the modified fat, and the corresponding entries in s->mapping are
2254 static int commit_mappings(BDRVVVFATState* s,
2255 uint32_t first_cluster, int dir_index)
2257 mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2258 direntry_t* direntry = array_get(&(s->directory), dir_index);
2259 uint32_t cluster = first_cluster;
2261 vvfat_close_current_file(s);
2264 assert(mapping->begin == first_cluster);
2265 mapping->first_mapping_index = -1;
2266 mapping->dir_index = dir_index;
2267 mapping->mode = (dir_index <= 0 || is_directory(direntry)) ?
2268 MODE_DIRECTORY : MODE_NORMAL;
2270 while (!fat_eof(s, cluster)) {
2273 for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
2274 c = c1, c1 = modified_fat_get(s, c1));
2277 if (c > mapping->end) {
2278 int index = array_index(&(s->mapping), mapping);
2279 int i, max_i = s->mapping.next - index;
2280 for (i = 1; i < max_i && mapping[i].begin < c; i++);
2282 remove_mapping(s, index + 1);
2284 assert(mapping == array_get(&(s->mapping), s->mapping.next - 1)
2285 || mapping[1].begin >= c);
2288 if (!fat_eof(s, c1)) {
2289 int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next);
2290 mapping_t* next_mapping = i >= s->mapping.next ? NULL :
2291 array_get(&(s->mapping), i);
2293 if (next_mapping == NULL || next_mapping->begin > c1) {
2294 int i1 = array_index(&(s->mapping), mapping);
2296 next_mapping = insert_mapping(s, c1, c1+1);
2300 mapping = array_get(&(s->mapping), i1);
2303 next_mapping->dir_index = mapping->dir_index;
2304 next_mapping->first_mapping_index =
2305 mapping->first_mapping_index < 0 ?
2306 array_index(&(s->mapping), mapping) :
2307 mapping->first_mapping_index;
2308 next_mapping->path = mapping->path;
2309 next_mapping->mode = mapping->mode;
2310 next_mapping->read_only = mapping->read_only;
2311 if (mapping->mode & MODE_DIRECTORY) {
2312 next_mapping->info.dir.parent_mapping_index =
2313 mapping->info.dir.parent_mapping_index;
2314 next_mapping->info.dir.first_dir_index =
2315 mapping->info.dir.first_dir_index +
2316 0x10 * s->sectors_per_cluster *
2317 (mapping->end - mapping->begin);
2319 next_mapping->info.file.offset = mapping->info.file.offset +
2320 mapping->end - mapping->begin;
2322 mapping = next_mapping;
2331 static int commit_direntries(BDRVVVFATState* s,
2332 int dir_index, int parent_mapping_index)
2334 direntry_t* direntry = array_get(&(s->directory), dir_index);
2335 uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
2336 mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2338 int factor = 0x10 * s->sectors_per_cluster;
2339 int old_cluster_count, new_cluster_count;
2340 int current_dir_index = mapping->info.dir.first_dir_index;
2341 int first_dir_index = current_dir_index;
2345 DLOG(fprintf(stderr, "commit_direntries for %s, parent_mapping_index %d\n", mapping->path, parent_mapping_index));
2349 assert(mapping->begin == first_cluster);
2350 assert(mapping->info.dir.first_dir_index < s->directory.next);
2351 assert(mapping->mode & MODE_DIRECTORY);
2352 assert(dir_index == 0 || is_directory(direntry));
2354 mapping->info.dir.parent_mapping_index = parent_mapping_index;
2356 if (first_cluster == 0) {
2357 old_cluster_count = new_cluster_count =
2358 s->last_cluster_of_root_directory;
2360 for (old_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2362 old_cluster_count++;
2364 for (new_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2365 c = modified_fat_get(s, c))
2366 new_cluster_count++;
2369 if (new_cluster_count > old_cluster_count) {
2370 if (insert_direntries(s,
2371 current_dir_index + factor * old_cluster_count,
2372 factor * (new_cluster_count - old_cluster_count)) == NULL)
2374 } else if (new_cluster_count < old_cluster_count)
2375 remove_direntries(s,
2376 current_dir_index + factor * new_cluster_count,
2377 factor * (old_cluster_count - new_cluster_count));
2379 for (c = first_cluster; !fat_eof(s, c); c = modified_fat_get(s, c)) {
2380 direntry_t *first_direntry;
2381 void* direntry = array_get(&(s->directory), current_dir_index);
2382 int ret = vvfat_read(s->bs, cluster2sector(s, c), direntry,
2383 s->sectors_per_cluster);
2387 /* The first directory entry on the filesystem is the volume name */
2388 first_direntry = (direntry_t*) s->directory.pointer;
2389 assert(!memcmp(first_direntry->name, s->volume_label, 11));
2391 current_dir_index += factor;
2394 ret = commit_mappings(s, first_cluster, dir_index);
2399 for (i = 0; i < factor * new_cluster_count; i++) {
2400 direntry = array_get(&(s->directory), first_dir_index + i);
2401 if (is_directory(direntry) && !is_dot(direntry)) {
2402 mapping = find_mapping_for_cluster(s, first_cluster);
2403 assert(mapping->mode & MODE_DIRECTORY);
2404 ret = commit_direntries(s, first_dir_index + i,
2405 array_index(&(s->mapping), mapping));
2414 /* commit one file (adjust contents, adjust mapping),
2415 return first_mapping_index */
2416 static int commit_one_file(BDRVVVFATState* s,
2417 int dir_index, uint32_t offset)
2419 direntry_t* direntry = array_get(&(s->directory), dir_index);
2420 uint32_t c = begin_of_direntry(direntry);
2421 uint32_t first_cluster = c;
2422 mapping_t* mapping = find_mapping_for_cluster(s, c);
2423 uint32_t size = filesize_of_direntry(direntry);
2424 char* cluster = g_malloc(s->cluster_size);
2428 assert(offset < size);
2429 assert((offset % s->cluster_size) == 0);
2431 for (i = s->cluster_size; i < offset; i += s->cluster_size)
2432 c = modified_fat_get(s, c);
2434 fd = qemu_open(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666);
2436 fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path,
2437 strerror(errno), errno);
2442 if (lseek(fd, offset, SEEK_SET) != offset) {
2449 while (offset < size) {
2451 int rest_size = (size - offset > s->cluster_size ?
2452 s->cluster_size : size - offset);
2455 c1 = modified_fat_get(s, c);
2457 assert((size - offset == 0 && fat_eof(s, c)) ||
2458 (size > offset && c >=2 && !fat_eof(s, c)));
2460 ret = vvfat_read(s->bs, cluster2sector(s, c),
2461 (uint8_t*)cluster, (rest_size + 0x1ff) / 0x200);
2469 if (write(fd, cluster, rest_size) < 0) {
2475 offset += rest_size;
2479 if (ftruncate(fd, size)) {
2480 perror("ftruncate()");
2488 return commit_mappings(s, first_cluster, dir_index);
2492 /* test, if all mappings point to valid direntries */
2493 static void check1(BDRVVVFATState* s)
2496 for (i = 0; i < s->mapping.next; i++) {
2497 mapping_t* mapping = array_get(&(s->mapping), i);
2498 if (mapping->mode & MODE_DELETED) {
2499 fprintf(stderr, "deleted\n");
2502 assert(mapping->dir_index < s->directory.next);
2503 direntry_t* direntry = array_get(&(s->directory), mapping->dir_index);
2504 assert(mapping->begin == begin_of_direntry(direntry) || mapping->first_mapping_index >= 0);
2505 if (mapping->mode & MODE_DIRECTORY) {
2506 assert(mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster * (mapping->end - mapping->begin) <= s->directory.next);
2507 assert((mapping->info.dir.first_dir_index % (0x10 * s->sectors_per_cluster)) == 0);
2512 /* test, if all direntries have mappings */
2513 static void check2(BDRVVVFATState* s)
2516 int first_mapping = -1;
2518 for (i = 0; i < s->directory.next; i++) {
2519 direntry_t* direntry = array_get(&(s->directory), i);
2521 if (is_short_name(direntry) && begin_of_direntry(direntry)) {
2522 mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
2524 assert(mapping->dir_index == i || is_dot(direntry));
2525 assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry));
2528 if ((i % (0x10 * s->sectors_per_cluster)) == 0) {
2532 for (j = 0; j < s->mapping.next; j++) {
2533 mapping_t* mapping = array_get(&(s->mapping), j);
2534 if (mapping->mode & MODE_DELETED)
2536 if (mapping->mode & MODE_DIRECTORY) {
2537 if (mapping->info.dir.first_dir_index <= i && mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster > i) {
2538 assert(++count == 1);
2539 if (mapping->first_mapping_index == -1)
2540 first_mapping = array_index(&(s->mapping), mapping);
2542 assert(first_mapping == mapping->first_mapping_index);
2543 if (mapping->info.dir.parent_mapping_index < 0)
2546 mapping_t* parent = array_get(&(s->mapping), mapping->info.dir.parent_mapping_index);
2547 assert(parent->mode & MODE_DIRECTORY);
2548 assert(parent->info.dir.first_dir_index < mapping->info.dir.first_dir_index);
2560 static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2565 fprintf(stderr, "handle_renames\n");
2566 for (i = 0; i < s->commits.next; i++) {
2567 commit_t* commit = array_get(&(s->commits), i);
2568 fprintf(stderr, "%d, %s (%d, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action);
2572 for (i = 0; i < s->commits.next;) {
2573 commit_t* commit = array_get(&(s->commits), i);
2574 if (commit->action == ACTION_RENAME) {
2575 mapping_t* mapping = find_mapping_for_cluster(s,
2576 commit->param.rename.cluster);
2577 char* old_path = mapping->path;
2579 assert(commit->path);
2580 mapping->path = commit->path;
2581 if (rename(old_path, mapping->path))
2584 if (mapping->mode & MODE_DIRECTORY) {
2585 int l1 = strlen(mapping->path);
2586 int l2 = strlen(old_path);
2588 direntry_t* direntry = array_get(&(s->directory),
2589 mapping->info.dir.first_dir_index);
2590 uint32_t c = mapping->begin;
2594 while (!fat_eof(s, c)) {
2596 direntry_t* d = direntry + i;
2598 if (is_file(d) || (is_directory(d) && !is_dot(d))) {
2599 mapping_t* m = find_mapping_for_cluster(s,
2600 begin_of_direntry(d));
2601 int l = strlen(m->path);
2602 char* new_path = g_malloc(l + diff + 1);
2604 assert(!strncmp(m->path, mapping->path, l2));
2606 pstrcpy(new_path, l + diff + 1, mapping->path);
2607 pstrcpy(new_path + l1, l + diff + 1 - l1,
2610 schedule_rename(s, m->begin, new_path);
2613 } while((i % (0x10 * s->sectors_per_cluster)) != 0);
2619 array_remove(&(s->commits), i);
2621 } else if (commit->action == ACTION_MKDIR) {
2623 int j, parent_path_len;
2626 if (mkdir(commit->path))
2629 if (mkdir(commit->path, 0755))
2633 mapping = insert_mapping(s, commit->param.mkdir.cluster,
2634 commit->param.mkdir.cluster + 1);
2635 if (mapping == NULL)
2638 mapping->mode = MODE_DIRECTORY;
2639 mapping->read_only = 0;
2640 mapping->path = commit->path;
2641 j = s->directory.next;
2643 insert_direntries(s, s->directory.next,
2644 0x10 * s->sectors_per_cluster);
2645 mapping->info.dir.first_dir_index = j;
2647 parent_path_len = strlen(commit->path)
2648 - strlen(get_basename(commit->path)) - 1;
2649 for (j = 0; j < s->mapping.next; j++) {
2650 mapping_t* m = array_get(&(s->mapping), j);
2651 if (m->first_mapping_index < 0 && m != mapping &&
2652 !strncmp(m->path, mapping->path, parent_path_len) &&
2653 strlen(m->path) == parent_path_len)
2656 assert(j < s->mapping.next);
2657 mapping->info.dir.parent_mapping_index = j;
2659 array_remove(&(s->commits), i);
2669 * TODO: make sure that the short name is not matching *another* file
2671 static int handle_commits(BDRVVVFATState* s)
2675 vvfat_close_current_file(s);
2677 for (i = 0; !fail && i < s->commits.next; i++) {
2678 commit_t* commit = array_get(&(s->commits), i);
2679 switch(commit->action) {
2680 case ACTION_RENAME: case ACTION_MKDIR:
2684 case ACTION_WRITEOUT: {
2686 /* these variables are only used by assert() below */
2687 direntry_t* entry = array_get(&(s->directory),
2688 commit->param.writeout.dir_index);
2689 uint32_t begin = begin_of_direntry(entry);
2690 mapping_t* mapping = find_mapping_for_cluster(s, begin);
2694 assert(mapping->begin == begin);
2695 assert(commit->path == NULL);
2697 if (commit_one_file(s, commit->param.writeout.dir_index,
2698 commit->param.writeout.modified_offset))
2703 case ACTION_NEW_FILE: {
2704 int begin = commit->param.new_file.first_cluster;
2705 mapping_t* mapping = find_mapping_for_cluster(s, begin);
2710 for (i = 0; i < s->directory.next; i++) {
2711 entry = array_get(&(s->directory), i);
2712 if (is_file(entry) && begin_of_direntry(entry) == begin)
2716 if (i >= s->directory.next) {
2721 /* make sure there exists an initial mapping */
2722 if (mapping && mapping->begin != begin) {
2723 mapping->end = begin;
2726 if (mapping == NULL) {
2727 mapping = insert_mapping(s, begin, begin+1);
2729 /* most members will be fixed in commit_mappings() */
2730 assert(commit->path);
2731 mapping->path = commit->path;
2732 mapping->read_only = 0;
2733 mapping->mode = MODE_NORMAL;
2734 mapping->info.file.offset = 0;
2736 if (commit_one_file(s, i, 0))
2745 if (i > 0 && array_remove_slice(&(s->commits), 0, i))
2750 static int handle_deletes(BDRVVVFATState* s)
2752 int i, deferred = 1, deleted = 1;
2754 /* delete files corresponding to mappings marked as deleted */
2755 /* handle DELETEs and unused mappings (modified_fat_get(s, mapping->begin) == 0) */
2756 while (deferred && deleted) {
2760 for (i = 1; i < s->mapping.next; i++) {
2761 mapping_t* mapping = array_get(&(s->mapping), i);
2762 if (mapping->mode & MODE_DELETED) {
2763 direntry_t* entry = array_get(&(s->directory),
2764 mapping->dir_index);
2766 if (is_free(entry)) {
2767 /* remove file/directory */
2768 if (mapping->mode & MODE_DIRECTORY) {
2769 int j, next_dir_index = s->directory.next,
2770 first_dir_index = mapping->info.dir.first_dir_index;
2772 if (rmdir(mapping->path) < 0) {
2773 if (errno == ENOTEMPTY) {
2780 for (j = 1; j < s->mapping.next; j++) {
2781 mapping_t* m = array_get(&(s->mapping), j);
2782 if (m->mode & MODE_DIRECTORY &&
2783 m->info.dir.first_dir_index >
2785 m->info.dir.first_dir_index <
2788 m->info.dir.first_dir_index;
2790 remove_direntries(s, first_dir_index,
2791 next_dir_index - first_dir_index);
2796 if (unlink(mapping->path))
2800 DLOG(fprintf(stderr, "DELETE (%d)\n", i); print_mapping(mapping); print_direntry(entry));
2801 remove_mapping(s, i);
2810 * synchronize mapping with new state:
2812 * - copy FAT (with bdrv_read)
2813 * - mark all filenames corresponding to mappings as deleted
2814 * - recurse direntries from root (using bs->bdrv_read)
2815 * - delete files corresponding to mappings marked as deleted
2817 static int do_commit(BDRVVVFATState* s)
2821 /* the real meat are the commits. Nothing to do? Move along! */
2822 if (s->commits.next == 0)
2825 vvfat_close_current_file(s);
2827 ret = handle_renames_and_mkdirs(s);
2829 fprintf(stderr, "Error handling renames (%d)\n", ret);
2834 /* copy FAT (with bdrv_read) */
2835 memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
2837 /* recurse direntries from root (using bs->bdrv_read) */
2838 ret = commit_direntries(s, 0, -1);
2840 fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
2845 ret = handle_commits(s);
2847 fprintf(stderr, "Error handling commits (%d)\n", ret);
2852 ret = handle_deletes(s);
2854 fprintf(stderr, "Error deleting\n");
2859 if (s->qcow->bs->drv->bdrv_make_empty) {
2860 s->qcow->bs->drv->bdrv_make_empty(s->qcow->bs);
2863 memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
2869 static int try_commit(BDRVVVFATState* s)
2871 vvfat_close_current_file(s);
2873 if(!is_consistent(s))
2875 return do_commit(s);
2878 static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
2879 const uint8_t *buf, int nb_sectors)
2881 BDRVVVFATState *s = bs->opaque;
2886 /* Check if we're operating in read-only mode */
2887 if (s->qcow == NULL) {
2891 vvfat_close_current_file(s);
2894 * Some sanity checks:
2895 * - do not allow writing to the boot sector
2896 * - do not allow to write non-ASCII filenames
2899 if (sector_num < s->offset_to_fat)
2902 for (i = sector2cluster(s, sector_num);
2903 i <= sector2cluster(s, sector_num + nb_sectors - 1);) {
2904 mapping_t* mapping = find_mapping_for_cluster(s, i);
2906 if (mapping->read_only) {
2907 fprintf(stderr, "Tried to write to write-protected file %s\n",
2912 if (mapping->mode & MODE_DIRECTORY) {
2913 int begin = cluster2sector(s, i);
2914 int end = begin + s->sectors_per_cluster, k;
2916 const direntry_t* direntries;
2921 if (begin < sector_num)
2923 if (end > sector_num + nb_sectors)
2924 end = sector_num + nb_sectors;
2925 dir_index = mapping->dir_index +
2926 0x10 * (begin - mapping->begin * s->sectors_per_cluster);
2927 direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
2929 for (k = 0; k < (end - begin) * 0x10; k++) {
2930 /* do not allow non-ASCII filenames */
2931 if (parse_long_name(&lfn, direntries + k) < 0) {
2932 fprintf(stderr, "Warning: non-ASCII filename\n");
2935 /* no access to the direntry of a read-only file */
2936 else if (is_short_name(direntries+k) &&
2937 (direntries[k].attributes & 1)) {
2938 if (memcmp(direntries + k,
2939 array_get(&(s->directory), dir_index + k),
2940 sizeof(direntry_t))) {
2941 fprintf(stderr, "Warning: tried to write to write-protected file\n");
2953 * Use qcow backend. Commit later.
2955 DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
2956 ret = bdrv_write(s->qcow, sector_num, buf, nb_sectors);
2958 fprintf(stderr, "Error writing to qcow backend\n");
2962 for (i = sector2cluster(s, sector_num);
2963 i <= sector2cluster(s, sector_num + nb_sectors - 1); i++)
2965 s->used_clusters[i] |= USED_ALLOCATED;
2968 /* TODO: add timeout */
2975 static int coroutine_fn
2976 vvfat_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
2977 QEMUIOVector *qiov, int flags)
2980 BDRVVVFATState *s = bs->opaque;
2981 uint64_t sector_num = offset >> BDRV_SECTOR_BITS;
2982 int nb_sectors = bytes >> BDRV_SECTOR_BITS;
2985 assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
2986 assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
2988 buf = g_try_malloc(bytes);
2989 if (bytes && buf == NULL) {
2992 qemu_iovec_to_buf(qiov, 0, buf, bytes);
2994 qemu_co_mutex_lock(&s->lock);
2995 ret = vvfat_write(bs, sector_num, buf, nb_sectors);
2996 qemu_co_mutex_unlock(&s->lock);
3003 static int64_t coroutine_fn vvfat_co_get_block_status(BlockDriverState *bs,
3004 int64_t sector_num, int nb_sectors, int *n, BlockDriverState **file)
3006 *n = bs->total_sectors - sector_num;
3007 if (*n > nb_sectors) {
3009 } else if (*n < 0) {
3012 return BDRV_BLOCK_DATA;
3015 static int coroutine_fn
3016 write_target_commit(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
3017 QEMUIOVector *qiov, int flags)
3019 BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
3020 return try_commit(s);
3023 static void write_target_close(BlockDriverState *bs) {
3024 BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
3025 bdrv_unref_child(s->bs, s->qcow);
3026 g_free(s->qcow_filename);
3029 static BlockDriver vvfat_write_target = {
3030 .format_name = "vvfat_write_target",
3031 .instance_size = sizeof(void*),
3032 .bdrv_co_pwritev = write_target_commit,
3033 .bdrv_close = write_target_close,
3036 static void vvfat_qcow_options(int *child_flags, QDict *child_options,
3037 int parent_flags, QDict *parent_options)
3039 qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "off");
3040 *child_flags = BDRV_O_NO_FLUSH;
3043 static const BdrvChildRole child_vvfat_qcow = {
3044 .inherit_options = vvfat_qcow_options,
3047 static int enable_write_target(BlockDriverState *bs, Error **errp)
3049 BDRVVVFATState *s = bs->opaque;
3050 BlockDriver *bdrv_qcow = NULL;
3051 BlockDriverState *backing;
3052 QemuOpts *opts = NULL;
3054 int size = sector2cluster(s, s->sector_count);
3057 s->used_clusters = calloc(size, 1);
3059 array_init(&(s->commits), sizeof(commit_t));
3061 s->qcow_filename = g_malloc(PATH_MAX);
3062 ret = get_tmp_filename(s->qcow_filename, PATH_MAX);
3064 error_setg_errno(errp, -ret, "can't create temporary file");
3068 bdrv_qcow = bdrv_find_format("qcow");
3070 error_setg(errp, "Failed to locate qcow driver");
3075 opts = qemu_opts_create(bdrv_qcow->create_opts, NULL, 0, &error_abort);
3076 qemu_opt_set_number(opts, BLOCK_OPT_SIZE, s->sector_count * 512,
3078 qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, "fat:", &error_abort);
3080 ret = bdrv_create(bdrv_qcow, s->qcow_filename, opts, errp);
3081 qemu_opts_del(opts);
3086 options = qdict_new();
3087 qdict_put_str(options, "write-target.driver", "qcow");
3088 s->qcow = bdrv_open_child(s->qcow_filename, options, "write-target", bs,
3089 &child_vvfat_qcow, false, errp);
3097 unlink(s->qcow_filename);
3100 backing = bdrv_new_open_driver(&vvfat_write_target, NULL, BDRV_O_ALLOW_RDWR,
3102 *(void**) backing->opaque = s;
3104 bdrv_set_backing_hd(s->bs, backing, &error_abort);
3105 bdrv_unref(backing);
3110 g_free(s->qcow_filename);
3111 s->qcow_filename = NULL;
3115 static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c,
3116 const BdrvChildRole *role,
3117 uint64_t perm, uint64_t shared,
3118 uint64_t *nperm, uint64_t *nshared)
3120 BDRVVVFATState *s = bs->opaque;
3122 assert(c == s->qcow || role == &child_backing);
3125 /* This is a private node, nobody should try to attach to it */
3126 *nperm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE;
3127 *nshared = BLK_PERM_WRITE_UNCHANGED;
3129 /* The backing file is there so 'commit' can use it. vvfat doesn't
3130 * access it in any way. */
3132 *nshared = BLK_PERM_ALL;
3136 static void vvfat_close(BlockDriverState *bs)
3138 BDRVVVFATState *s = bs->opaque;
3140 vvfat_close_current_file(s);
3141 array_free(&(s->fat));
3142 array_free(&(s->directory));
3143 array_free(&(s->mapping));
3144 g_free(s->cluster_buffer);
3147 migrate_del_blocker(s->migration_blocker);
3148 error_free(s->migration_blocker);
3152 static BlockDriver bdrv_vvfat = {
3153 .format_name = "vvfat",
3154 .protocol_name = "fat",
3155 .instance_size = sizeof(BDRVVVFATState),
3157 .bdrv_parse_filename = vvfat_parse_filename,
3158 .bdrv_file_open = vvfat_open,
3159 .bdrv_refresh_limits = vvfat_refresh_limits,
3160 .bdrv_close = vvfat_close,
3161 .bdrv_child_perm = vvfat_child_perm,
3163 .bdrv_co_preadv = vvfat_co_preadv,
3164 .bdrv_co_pwritev = vvfat_co_pwritev,
3165 .bdrv_co_get_block_status = vvfat_co_get_block_status,
3168 static void bdrv_vvfat_init(void)
3170 bdrv_register(&bdrv_vvfat);
3173 block_init(bdrv_vvfat_init);
3176 static void checkpoint(void) {
3177 assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2);
3180 assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY));
3182 if (((direntry_t*)vvv->directory.pointer)[1].attributes != 0xf)
3183 fprintf(stderr, "Nonono!\n");
3185 direntry_t* direntry;
3186 assert(vvv->mapping.size >= vvv->mapping.item_size * vvv->mapping.next);
3187 assert(vvv->directory.size >= vvv->directory.item_size * vvv->directory.next);
3188 if (vvv->mapping.next<47)
3190 assert((mapping = array_get(&(vvv->mapping), 47)));
3191 assert(mapping->dir_index < vvv->directory.next);
3192 direntry = array_get(&(vvv->directory), mapping->dir_index);
3193 assert(!memcmp(direntry->name, "USB H ", 11) || direntry->name[0]==0);