]> git.ipfire.org Git - thirdparty/qemu.git/blame - block/vvfat.c
mac_dbdma: always initialize channel field in DBDMA_channel
[thirdparty/qemu.git] / block / vvfat.c
CommitLineData
7ad9be64 1/* vim:set shiftwidth=4 ts=4: */
de167e41
FB
2/*
3 * QEMU Block driver for virtual VFAT (shadows a local directory)
5fafdf24 4 *
a046433a 5 * Copyright (c) 2004,2005 Johannes E. Schindelin
5fafdf24 6 *
de167e41
FB
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:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25#include <sys/stat.h>
26#include <dirent.h>
faf07963 27#include "qemu-common.h"
737e150e 28#include "block/block_int.h"
1de7afc9 29#include "qemu/module.h"
caf71f86 30#include "migration/migration.h"
7ad9be64
KW
31#include "qapi/qmp/qint.h"
32#include "qapi/qmp/qbool.h"
d49b6836 33#include "qapi/qmp/qstring.h"
de167e41 34
a046433a
FB
35#ifndef S_IWGRP
36#define S_IWGRP 0
37#endif
38#ifndef S_IWOTH
39#define S_IWOTH 0
40#endif
41
42/* TODO: add ":bootsector=blabla.img:" */
43/* LATER TODO: add automatic boot sector generation from
44 BOOTEASY.ASM and Ranish Partition Manager
5fafdf24 45 Note that DOS assumes the system files to be the first files in the
a046433a
FB
46 file system (test if the boot sector still relies on that fact)! */
47/* MAYBE TODO: write block-visofs.c */
48/* TODO: call try_commit() only after a timeout */
49
50/* #define DEBUG */
51
52#ifdef DEBUG
53
54#define DLOG(a) a
55
3f47aa8c 56static void checkpoint(void);
de167e41 57
a046433a
FB
58#ifdef __MINGW32__
59void nonono(const char* file, int line, const char* msg) {
60 fprintf(stderr, "Nonono! %s:%d %s\n", file, line, msg);
61 exit(-5);
62}
63#undef assert
6bcb76c3 64#define assert(a) do {if (!(a)) nonono(__FILE__, __LINE__, #a);}while(0)
a046433a
FB
65#endif
66
67#else
68
69#define DLOG(a)
70
71#endif
de167e41
FB
72
73/* dynamic array functions */
c227f099 74typedef struct array_t {
de167e41
FB
75 char* pointer;
76 unsigned int size,next,item_size;
c227f099 77} array_t;
de167e41 78
c227f099 79static inline void array_init(array_t* array,unsigned int item_size)
de167e41 80{
511d2b14 81 array->pointer = NULL;
de167e41
FB
82 array->size=0;
83 array->next=0;
84 array->item_size=item_size;
85}
86
c227f099 87static inline void array_free(array_t* array)
de167e41 88{
ce137829 89 g_free(array->pointer);
de167e41
FB
90 array->size=array->next=0;
91}
92
a046433a 93/* does not automatically grow */
c227f099 94static inline void* array_get(array_t* array,unsigned int index) {
a046433a
FB
95 assert(index < array->next);
96 return array->pointer + index * array->item_size;
97}
98
c227f099 99static inline int array_ensure_allocated(array_t* array, int index)
a046433a
FB
100{
101 if((index + 1) * array->item_size > array->size) {
102 int new_size = (index + 32) * array->item_size;
7267c094 103 array->pointer = g_realloc(array->pointer, new_size);
a046433a
FB
104 if (!array->pointer)
105 return -1;
106 array->size = new_size;
107 array->next = index + 1;
de167e41 108 }
a046433a
FB
109
110 return 0;
de167e41
FB
111}
112
c227f099 113static inline void* array_get_next(array_t* array) {
a046433a
FB
114 unsigned int next = array->next;
115 void* result;
116
117 if (array_ensure_allocated(array, next) < 0)
118 return NULL;
119
120 array->next = next + 1;
121 result = array_get(array, next);
122
de167e41
FB
123 return result;
124}
125
c227f099 126static inline void* array_insert(array_t* array,unsigned int index,unsigned int count) {
de167e41
FB
127 if((array->next+count)*array->item_size>array->size) {
128 int increment=count*array->item_size;
7267c094 129 array->pointer=g_realloc(array->pointer,array->size+increment);
de167e41 130 if(!array->pointer)
511d2b14 131 return NULL;
de167e41
FB
132 array->size+=increment;
133 }
134 memmove(array->pointer+(index+count)*array->item_size,
135 array->pointer+index*array->item_size,
136 (array->next-index)*array->item_size);
137 array->next+=count;
138 return array->pointer+index*array->item_size;
139}
140
141/* this performs a "roll", so that the element which was at index_from becomes
142 * index_to, but the order of all other elements is preserved. */
c227f099 143static inline int array_roll(array_t* array,int index_to,int index_from,int count)
de167e41
FB
144{
145 char* buf;
146 char* from;
147 char* to;
148 int is;
149
150 if(!array ||
151 index_to<0 || index_to>=array->next ||
152 index_from<0 || index_from>=array->next)
153 return -1;
3b46e624 154
de167e41
FB
155 if(index_to==index_from)
156 return 0;
157
158 is=array->item_size;
159 from=array->pointer+index_from*is;
160 to=array->pointer+index_to*is;
7267c094 161 buf=g_malloc(is*count);
de167e41
FB
162 memcpy(buf,from,is*count);
163
164 if(index_to<index_from)
165 memmove(to+is*count,to,from-to);
166 else
167 memmove(from,from+is*count,to-from);
3b46e624 168
de167e41
FB
169 memcpy(to,buf,is*count);
170
ce137829 171 g_free(buf);
de167e41
FB
172
173 return 0;
174}
175
c227f099 176static inline int array_remove_slice(array_t* array,int index, int count)
de167e41 177{
a046433a
FB
178 assert(index >=0);
179 assert(count > 0);
180 assert(index + count <= array->next);
181 if(array_roll(array,array->next-1,index,count))
de167e41 182 return -1;
a046433a 183 array->next -= count;
de167e41
FB
184 return 0;
185}
186
c227f099 187static int array_remove(array_t* array,int index)
a046433a
FB
188{
189 return array_remove_slice(array, index, 1);
190}
191
192/* return the index for a given member */
c227f099 193static int array_index(array_t* array, void* pointer)
a046433a
FB
194{
195 size_t offset = (char*)pointer - array->pointer;
a046433a
FB
196 assert((offset % array->item_size) == 0);
197 assert(offset/array->item_size < array->next);
198 return offset/array->item_size;
199}
200
de167e41 201/* These structures are used to fake a disk and the VFAT filesystem.
541dc0d4 202 * For this reason we need to use QEMU_PACKED. */
de167e41 203
c227f099 204typedef struct bootsector_t {
de167e41
FB
205 uint8_t jump[3];
206 uint8_t name[8];
207 uint16_t sector_size;
208 uint8_t sectors_per_cluster;
209 uint16_t reserved_sectors;
210 uint8_t number_of_fats;
211 uint16_t root_entries;
a046433a 212 uint16_t total_sectors16;
de167e41
FB
213 uint8_t media_type;
214 uint16_t sectors_per_fat;
215 uint16_t sectors_per_track;
216 uint16_t number_of_heads;
217 uint32_t hidden_sectors;
218 uint32_t total_sectors;
219 union {
220 struct {
221 uint8_t drive_number;
222 uint8_t current_head;
223 uint8_t signature;
224 uint32_t id;
225 uint8_t volume_label[11];
541dc0d4 226 } QEMU_PACKED fat16;
de167e41
FB
227 struct {
228 uint32_t sectors_per_fat;
229 uint16_t flags;
230 uint8_t major,minor;
231 uint32_t first_cluster_of_root_directory;
232 uint16_t info_sector;
233 uint16_t backup_boot_sector;
234 uint16_t ignored;
541dc0d4 235 } QEMU_PACKED fat32;
de167e41
FB
236 } u;
237 uint8_t fat_type[8];
238 uint8_t ignored[0x1c0];
239 uint8_t magic[2];
541dc0d4 240} QEMU_PACKED bootsector_t;
de167e41 241
b570094d
TS
242typedef struct {
243 uint8_t head;
244 uint8_t sector;
245 uint8_t cylinder;
c227f099 246} mbr_chs_t;
b570094d 247
c227f099 248typedef struct partition_t {
de167e41 249 uint8_t attributes; /* 0x80 = bootable */
c227f099 250 mbr_chs_t start_CHS;
b570094d 251 uint8_t fs_type; /* 0x1 = FAT12, 0x6 = FAT16, 0xe = FAT16_LBA, 0xb = FAT32, 0xc = FAT32_LBA */
c227f099 252 mbr_chs_t end_CHS;
de167e41 253 uint32_t start_sector_long;
b570094d 254 uint32_t length_sector_long;
541dc0d4 255} QEMU_PACKED partition_t;
de167e41 256
c227f099 257typedef struct mbr_t {
b570094d
TS
258 uint8_t ignored[0x1b8];
259 uint32_t nt_id;
260 uint8_t ignored2[2];
c227f099 261 partition_t partition[4];
de167e41 262 uint8_t magic[2];
541dc0d4 263} QEMU_PACKED mbr_t;
de167e41 264
c227f099 265typedef struct direntry_t {
f671d173 266 uint8_t name[8 + 3];
de167e41
FB
267 uint8_t attributes;
268 uint8_t reserved[2];
269 uint16_t ctime;
270 uint16_t cdate;
271 uint16_t adate;
272 uint16_t begin_hi;
273 uint16_t mtime;
274 uint16_t mdate;
275 uint16_t begin;
276 uint32_t size;
541dc0d4 277} QEMU_PACKED direntry_t;
de167e41
FB
278
279/* this structure are used to transparently access the files */
280
c227f099 281typedef struct mapping_t {
a046433a
FB
282 /* begin is the first cluster, end is the last+1 */
283 uint32_t begin,end;
de167e41
FB
284 /* as s->directory is growable, no pointer may be used here */
285 unsigned int dir_index;
a046433a
FB
286 /* the clusters of a file may be in any order; this points to the first */
287 int first_mapping_index;
288 union {
289 /* offset is
290 * - the offset in the file (in clusters) for a file, or
291 * - the next cluster of the directory for a directory, and
292 * - the address of the buffer for a faked entry
293 */
294 struct {
295 uint32_t offset;
296 } file;
297 struct {
298 int parent_mapping_index;
299 int first_dir_index;
300 } dir;
301 } info;
302 /* path contains the full path, i.e. it always starts with s->path */
303 char* path;
304
305 enum { MODE_UNDEFINED = 0, MODE_NORMAL = 1, MODE_MODIFIED = 2,
306 MODE_DIRECTORY = 4, MODE_FAKED = 8,
307 MODE_DELETED = 16, MODE_RENAMED = 32 } mode;
308 int read_only;
c227f099 309} mapping_t;
de167e41 310
a046433a 311#ifdef DEBUG
c227f099
AL
312static void print_direntry(const struct direntry_t*);
313static void print_mapping(const struct mapping_t* mapping);
a046433a 314#endif
de167e41
FB
315
316/* here begins the real VVFAT driver */
317
318typedef struct BDRVVVFATState {
848c66e8 319 CoMutex lock;
a046433a 320 BlockDriverState* bs; /* pointer to parent */
de167e41
FB
321 unsigned int first_sectors_number; /* 1 for a single partition, 0x40 for a disk with partition table */
322 unsigned char first_sectors[0x40*0x200];
3b46e624 323
de167e41 324 int fat_type; /* 16 or 32 */
c227f099 325 array_t fat,directory,mapping;
d5941dda 326 char volume_label[11];
3b46e624 327
de167e41
FB
328 unsigned int cluster_size;
329 unsigned int sectors_per_cluster;
330 unsigned int sectors_per_fat;
331 unsigned int sectors_of_root_directory;
a046433a 332 uint32_t last_cluster_of_root_directory;
de167e41
FB
333 unsigned int faked_sectors; /* how many sectors are faked before file data */
334 uint32_t sector_count; /* total number of sectors of the partition */
335 uint32_t cluster_count; /* total number of clusters of this partition */
de167e41 336 uint32_t max_fat_value;
3b46e624 337
de167e41 338 int current_fd;
c227f099 339 mapping_t* current_mapping;
a046433a
FB
340 unsigned char* cluster; /* points to current cluster */
341 unsigned char* cluster_buffer; /* points to a buffer to hold temp data */
de167e41
FB
342 unsigned int current_cluster;
343
344 /* write support */
a046433a
FB
345 BlockDriverState* write_target;
346 char* qcow_filename;
347 BlockDriverState* qcow;
348 void* fat2;
349 char* used_clusters;
c227f099 350 array_t commits;
a046433a
FB
351 const char* path;
352 int downcase_short_names;
3397f0cb
KW
353
354 Error *migration_blocker;
de167e41
FB
355} BDRVVVFATState;
356
b570094d
TS
357/* take the sector position spos and convert it to Cylinder/Head/Sector position
358 * if the position is outside the specified geometry, fill maximum value for CHS
359 * and return 1 to signal overflow.
360 */
4480e0f9
MA
361static int sector2CHS(mbr_chs_t *chs, int spos, int cyls, int heads, int secs)
362{
b570094d 363 int head,sector;
4480e0f9
MA
364 sector = spos % secs; spos /= secs;
365 head = spos % heads; spos /= heads;
366 if (spos >= cyls) {
b570094d
TS
367 /* Overflow,
368 it happens if 32bit sector positions are used, while CHS is only 24bit.
369 Windows/Dos is said to take 1023/255/63 as nonrepresentable CHS */
370 chs->head = 0xFF;
371 chs->sector = 0xFF;
372 chs->cylinder = 0xFF;
373 return 1;
374 }
375 chs->head = (uint8_t)head;
376 chs->sector = (uint8_t)( (sector+1) | ((spos>>8)<<6) );
377 chs->cylinder = (uint8_t)spos;
378 return 0;
379}
de167e41 380
4480e0f9 381static void init_mbr(BDRVVVFATState *s, int cyls, int heads, int secs)
de167e41
FB
382{
383 /* TODO: if the files mbr.img and bootsect.img exist, use them */
c227f099
AL
384 mbr_t* real_mbr=(mbr_t*)s->first_sectors;
385 partition_t* partition = &(real_mbr->partition[0]);
b570094d 386 int lba;
de167e41
FB
387
388 memset(s->first_sectors,0,512);
3b46e624 389
b570094d
TS
390 /* Win NT Disk Signature */
391 real_mbr->nt_id= cpu_to_le32(0xbe1afdfa);
392
de167e41 393 partition->attributes=0x80; /* bootable */
b570094d
TS
394
395 /* LBA is used when partition is outside the CHS geometry */
4480e0f9
MA
396 lba = sector2CHS(&partition->start_CHS, s->first_sectors_number - 1,
397 cyls, heads, secs);
398 lba |= sector2CHS(&partition->end_CHS, s->bs->total_sectors - 1,
399 cyls, heads, secs);
b570094d
TS
400
401 /*LBA partitions are identified only by start/length_sector_long not by CHS*/
f91cbefe
MA
402 partition->start_sector_long = cpu_to_le32(s->first_sectors_number - 1);
403 partition->length_sector_long = cpu_to_le32(s->bs->total_sectors
404 - s->first_sectors_number + 1);
b570094d 405
a046433a 406 /* FAT12/FAT16/FAT32 */
b570094d
TS
407 /* DOS uses different types when partition is LBA,
408 probably to prevent older versions from using CHS on them */
409 partition->fs_type= s->fat_type==12 ? 0x1:
410 s->fat_type==16 ? (lba?0xe:0x06):
411 /*fat_tyoe==32*/ (lba?0xc:0x0b);
de167e41
FB
412
413 real_mbr->magic[0]=0x55; real_mbr->magic[1]=0xaa;
414}
415
a046433a
FB
416/* direntry functions */
417
de167e41 418/* dest is assumed to hold 258 bytes, and pads with 0xffff up to next multiple of 26 */
60fe76f3 419static inline int short2long_name(char* dest,const char* src)
de167e41
FB
420{
421 int i;
1e080d5d 422 int len;
de167e41
FB
423 for(i=0;i<129 && src[i];i++) {
424 dest[2*i]=src[i];
425 dest[2*i+1]=0;
426 }
1e080d5d 427 len=2*i;
de167e41
FB
428 dest[2*i]=dest[2*i+1]=0;
429 for(i=2*i+2;(i%26);i++)
430 dest[i]=0xff;
1e080d5d 431 return len;
de167e41
FB
432}
433
c227f099 434static inline direntry_t* create_long_filename(BDRVVVFATState* s,const char* filename)
de167e41
FB
435{
436 char buffer[258];
437 int length=short2long_name(buffer,filename),
438 number_of_entries=(length+25)/26,i;
c227f099 439 direntry_t* entry;
de167e41
FB
440
441 for(i=0;i<number_of_entries;i++) {
442 entry=array_get_next(&(s->directory));
443 entry->attributes=0xf;
444 entry->reserved[0]=0;
445 entry->begin=0;
446 entry->name[0]=(number_of_entries-i)|(i==0?0x40:0);
447 }
1e080d5d 448 for(i=0;i<26*number_of_entries;i++) {
de167e41
FB
449 int offset=(i%26);
450 if(offset<10) offset=1+offset;
451 else if(offset<22) offset=14+offset-10;
452 else offset=28+offset-22;
453 entry=array_get(&(s->directory),s->directory.next-1-(i/26));
454 entry->name[offset]=buffer[i];
455 }
456 return array_get(&(s->directory),s->directory.next-number_of_entries);
457}
458
c227f099 459static char is_free(const direntry_t* direntry)
a046433a 460{
ad1a897e 461 return direntry->name[0]==0xe5 || direntry->name[0]==0x00;
a046433a
FB
462}
463
c227f099 464static char is_volume_label(const direntry_t* direntry)
a046433a
FB
465{
466 return direntry->attributes == 0x28;
467}
468
c227f099 469static char is_long_name(const direntry_t* direntry)
a046433a
FB
470{
471 return direntry->attributes == 0xf;
472}
473
c227f099 474static char is_short_name(const direntry_t* direntry)
a046433a
FB
475{
476 return !is_volume_label(direntry) && !is_long_name(direntry)
477 && !is_free(direntry);
478}
479
c227f099 480static char is_directory(const direntry_t* direntry)
a046433a
FB
481{
482 return direntry->attributes & 0x10 && direntry->name[0] != 0xe5;
483}
484
c227f099 485static inline char is_dot(const direntry_t* direntry)
a046433a
FB
486{
487 return is_short_name(direntry) && direntry->name[0] == '.';
488}
489
c227f099 490static char is_file(const direntry_t* direntry)
a046433a
FB
491{
492 return is_short_name(direntry) && !is_directory(direntry);
493}
494
c227f099 495static inline uint32_t begin_of_direntry(const direntry_t* direntry)
a046433a
FB
496{
497 return le16_to_cpu(direntry->begin)|(le16_to_cpu(direntry->begin_hi)<<16);
498}
499
c227f099 500static inline uint32_t filesize_of_direntry(const direntry_t* direntry)
a046433a
FB
501{
502 return le32_to_cpu(direntry->size);
503}
504
c227f099 505static void set_begin_of_direntry(direntry_t* direntry, uint32_t begin)
a046433a
FB
506{
507 direntry->begin = cpu_to_le16(begin & 0xffff);
508 direntry->begin_hi = cpu_to_le16((begin >> 16) & 0xffff);
509}
510
de167e41
FB
511/* fat functions */
512
c227f099 513static inline uint8_t fat_chksum(const direntry_t* entry)
de167e41
FB
514{
515 uint8_t chksum=0;
516 int i;
517
f671d173
SW
518 for (i = 0; i < ARRAY_SIZE(entry->name); i++) {
519 chksum = (((chksum & 0xfe) >> 1) |
520 ((chksum & 0x01) ? 0x80 : 0)) + entry->name[i];
5606c220 521 }
3b46e624 522
de167e41
FB
523 return chksum;
524}
525
526/* if return_time==0, this returns the fat_date, else the fat_time */
527static uint16_t fat_datetime(time_t time,int return_time) {
528 struct tm* t;
de167e41 529 struct tm t1;
6ab00cee 530 t = &t1;
de167e41 531 localtime_r(&time,t);
de167e41
FB
532 if(return_time)
533 return cpu_to_le16((t->tm_sec/2)|(t->tm_min<<5)|(t->tm_hour<<11));
534 return cpu_to_le16((t->tm_mday)|((t->tm_mon+1)<<5)|((t->tm_year-80)<<9));
535}
536
537static inline void fat_set(BDRVVVFATState* s,unsigned int cluster,uint32_t value)
538{
a046433a
FB
539 if(s->fat_type==32) {
540 uint32_t* entry=array_get(&(s->fat),cluster);
541 *entry=cpu_to_le32(value);
de167e41
FB
542 } else if(s->fat_type==16) {
543 uint16_t* entry=array_get(&(s->fat),cluster);
544 *entry=cpu_to_le16(value&0xffff);
545 } else {
a046433a
FB
546 int offset = (cluster*3/2);
547 unsigned char* p = array_get(&(s->fat), offset);
548 switch (cluster&1) {
549 case 0:
550 p[0] = value&0xff;
551 p[1] = (p[1]&0xf0) | ((value>>8)&0xf);
552 break;
553 case 1:
554 p[0] = (p[0]&0xf) | ((value&0xf)<<4);
555 p[1] = (value>>4);
556 break;
557 }
de167e41
FB
558 }
559}
560
561static inline uint32_t fat_get(BDRVVVFATState* s,unsigned int cluster)
562{
a046433a
FB
563 if(s->fat_type==32) {
564 uint32_t* entry=array_get(&(s->fat),cluster);
565 return le32_to_cpu(*entry);
de167e41
FB
566 } else if(s->fat_type==16) {
567 uint16_t* entry=array_get(&(s->fat),cluster);
568 return le16_to_cpu(*entry);
569 } else {
ffe8ab83 570 const uint8_t* x=(uint8_t*)(s->fat.pointer)+cluster*3/2;
a046433a 571 return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
de167e41
FB
572 }
573}
574
575static inline int fat_eof(BDRVVVFATState* s,uint32_t fat_entry)
576{
577 if(fat_entry>s->max_fat_value-8)
578 return -1;
579 return 0;
580}
581
582static inline void init_fat(BDRVVVFATState* s)
583{
a046433a
FB
584 if (s->fat_type == 12) {
585 array_init(&(s->fat),1);
586 array_ensure_allocated(&(s->fat),
587 s->sectors_per_fat * 0x200 * 3 / 2 - 1);
588 } else {
589 array_init(&(s->fat),(s->fat_type==32?4:2));
590 array_ensure_allocated(&(s->fat),
591 s->sectors_per_fat * 0x200 / s->fat.item_size - 1);
592 }
de167e41 593 memset(s->fat.pointer,0,s->fat.size);
3b46e624 594
de167e41
FB
595 switch(s->fat_type) {
596 case 12: s->max_fat_value=0xfff; break;
597 case 16: s->max_fat_value=0xffff; break;
a046433a 598 case 32: s->max_fat_value=0x0fffffff; break;
de167e41
FB
599 default: s->max_fat_value=0; /* error... */
600 }
601
602}
603
a046433a
FB
604/* TODO: in create_short_filename, 0xe5->0x05 is not yet handled! */
605/* TODO: in parse_short_filename, 0x05->0xe5 is not yet handled! */
c227f099 606static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,
a046433a 607 unsigned int directory_start, const char* filename, int is_dot)
de167e41 608{
a046433a 609 int i,j,long_index=s->directory.next;
c227f099
AL
610 direntry_t* entry = NULL;
611 direntry_t* entry_long = NULL;
de167e41
FB
612
613 if(is_dot) {
614 entry=array_get_next(&(s->directory));
f671d173 615 memset(entry->name, 0x20, sizeof(entry->name));
de167e41
FB
616 memcpy(entry->name,filename,strlen(filename));
617 return entry;
618 }
3b46e624 619
de167e41 620 entry_long=create_long_filename(s,filename);
3b46e624 621
5fafdf24 622 i = strlen(filename);
a046433a
FB
623 for(j = i - 1; j>0 && filename[j]!='.';j--);
624 if (j > 0)
625 i = (j > 8 ? 8 : j);
626 else if (i > 8)
627 i = 8;
628
de167e41 629 entry=array_get_next(&(s->directory));
f671d173 630 memset(entry->name, 0x20, sizeof(entry->name));
51a0f568 631 memcpy(entry->name, filename, i);
3b46e624 632
f671d173
SW
633 if (j > 0) {
634 for (i = 0; i < 3 && filename[j + 1 + i]; i++) {
635 entry->name[8 + i] = filename[j + 1 + i];
636 }
637 }
de167e41
FB
638
639 /* upcase & remove unwanted characters */
640 for(i=10;i>=0;i--) {
a046433a 641 if(i==10 || i==7) for(;i>0 && entry->name[i]==' ';i--);
de167e41 642 if(entry->name[i]<=' ' || entry->name[i]>0x7f
a046433a 643 || strchr(".*?<>|\":/\\[];,+='",entry->name[i]))
de167e41
FB
644 entry->name[i]='_';
645 else if(entry->name[i]>='a' && entry->name[i]<='z')
646 entry->name[i]+='A'-'a';
647 }
648
649 /* mangle duplicates */
650 while(1) {
c227f099 651 direntry_t* entry1=array_get(&(s->directory),directory_start);
de167e41
FB
652 int j;
653
654 for(;entry1<entry;entry1++)
a046433a 655 if(!is_long_name(entry1) && !memcmp(entry1->name,entry->name,11))
de167e41
FB
656 break; /* found dupe */
657 if(entry1==entry) /* no dupe found */
658 break;
659
5fafdf24 660 /* use all 8 characters of name */
de167e41
FB
661 if(entry->name[7]==' ') {
662 int j;
663 for(j=6;j>0 && entry->name[j]==' ';j--)
664 entry->name[j]='~';
665 }
666
667 /* increment number */
668 for(j=7;j>0 && entry->name[j]=='9';j--)
669 entry->name[j]='0';
670 if(j>0) {
671 if(entry->name[j]<'0' || entry->name[j]>'9')
672 entry->name[j]='0';
673 else
674 entry->name[j]++;
675 }
676 }
677
678 /* calculate checksum; propagate to long name */
679 if(entry_long) {
680 uint8_t chksum=fat_chksum(entry);
681
682 /* calculate anew, because realloc could have taken place */
683 entry_long=array_get(&(s->directory),long_index);
a046433a 684 while(entry_long<entry && is_long_name(entry_long)) {
de167e41
FB
685 entry_long->reserved[1]=chksum;
686 entry_long++;
687 }
688 }
689
690 return entry;
691}
692
a046433a
FB
693/*
694 * Read a directory. (the index of the corresponding mapping must be passed).
695 */
696static int read_directory(BDRVVVFATState* s, int mapping_index)
de167e41 697{
c227f099
AL
698 mapping_t* mapping = array_get(&(s->mapping), mapping_index);
699 direntry_t* direntry;
a046433a
FB
700 const char* dirname = mapping->path;
701 int first_cluster = mapping->begin;
702 int parent_index = mapping->info.dir.parent_mapping_index;
c227f099 703 mapping_t* parent_mapping = (mapping_t*)
511d2b14 704 (parent_index >= 0 ? array_get(&(s->mapping), parent_index) : NULL);
a046433a 705 int first_cluster_of_parent = parent_mapping ? parent_mapping->begin : -1;
de167e41
FB
706
707 DIR* dir=opendir(dirname);
708 struct dirent* entry;
de167e41
FB
709 int i;
710
a046433a
FB
711 assert(mapping->mode & MODE_DIRECTORY);
712
713 if(!dir) {
714 mapping->end = mapping->begin;
de167e41 715 return -1;
a046433a 716 }
3b46e624 717
a046433a
FB
718 i = mapping->info.dir.first_dir_index =
719 first_cluster == 0 ? 0 : s->directory.next;
720
5fafdf24 721 /* actually read the directory, and allocate the mappings */
de167e41
FB
722 while((entry=readdir(dir))) {
723 unsigned int length=strlen(dirname)+2+strlen(entry->d_name);
724 char* buffer;
c227f099 725 direntry_t* direntry;
a046433a 726 struct stat st;
de167e41
FB
727 int is_dot=!strcmp(entry->d_name,".");
728 int is_dotdot=!strcmp(entry->d_name,"..");
729
a046433a 730 if(first_cluster == 0 && (is_dotdot || is_dot))
de167e41 731 continue;
5fafdf24 732
d4df3dbc 733 buffer = g_malloc(length);
de167e41
FB
734 snprintf(buffer,length,"%s/%s",dirname,entry->d_name);
735
736 if(stat(buffer,&st)<0) {
ce137829 737 g_free(buffer);
de167e41
FB
738 continue;
739 }
740
741 /* create directory entry for this file */
a046433a
FB
742 direntry=create_short_and_long_name(s, i, entry->d_name,
743 is_dot || is_dotdot);
de167e41
FB
744 direntry->attributes=(S_ISDIR(st.st_mode)?0x10:0x20);
745 direntry->reserved[0]=direntry->reserved[1]=0;
746 direntry->ctime=fat_datetime(st.st_ctime,1);
747 direntry->cdate=fat_datetime(st.st_ctime,0);
748 direntry->adate=fat_datetime(st.st_atime,0);
749 direntry->begin_hi=0;
750 direntry->mtime=fat_datetime(st.st_mtime,1);
751 direntry->mdate=fat_datetime(st.st_mtime,0);
752 if(is_dotdot)
a046433a 753 set_begin_of_direntry(direntry, first_cluster_of_parent);
de167e41 754 else if(is_dot)
a046433a 755 set_begin_of_direntry(direntry, first_cluster);
de167e41 756 else
a046433a
FB
757 direntry->begin=0; /* do that later */
758 if (st.st_size > 0x7fffffff) {
759 fprintf(stderr, "File %s is larger than 2GB\n", buffer);
ce137829 760 g_free(buffer);
08089edc 761 closedir(dir);
a046433a
FB
762 return -2;
763 }
764 direntry->size=cpu_to_le32(S_ISDIR(st.st_mode)?0:st.st_size);
de167e41
FB
765
766 /* create mapping for this file */
a046433a 767 if(!is_dot && !is_dotdot && (S_ISDIR(st.st_mode) || st.st_size)) {
d4df3dbc 768 s->current_mapping = array_get_next(&(s->mapping));
de167e41
FB
769 s->current_mapping->begin=0;
770 s->current_mapping->end=st.st_size;
a046433a
FB
771 /*
772 * we get the direntry of the most recent direntry, which
773 * contains the short name and all the relevant information.
774 */
de167e41 775 s->current_mapping->dir_index=s->directory.next-1;
a046433a
FB
776 s->current_mapping->first_mapping_index = -1;
777 if (S_ISDIR(st.st_mode)) {
778 s->current_mapping->mode = MODE_DIRECTORY;
779 s->current_mapping->info.dir.parent_mapping_index =
780 mapping_index;
781 } else {
782 s->current_mapping->mode = MODE_UNDEFINED;
783 s->current_mapping->info.file.offset = 0;
784 }
785 s->current_mapping->path=buffer;
786 s->current_mapping->read_only =
787 (st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0;
b122c3b6
MA
788 } else {
789 g_free(buffer);
790 }
de167e41
FB
791 }
792 closedir(dir);
793
794 /* fill with zeroes up to the end of the cluster */
795 while(s->directory.next%(0x10*s->sectors_per_cluster)) {
c227f099
AL
796 direntry_t* direntry=array_get_next(&(s->directory));
797 memset(direntry,0,sizeof(direntry_t));
de167e41
FB
798 }
799
a046433a
FB
800/* TODO: if there are more entries, bootsector has to be adjusted! */
801#define ROOT_ENTRIES (0x02 * 0x10 * s->sectors_per_cluster)
802 if (mapping_index == 0 && s->directory.next < ROOT_ENTRIES) {
803 /* root directory */
804 int cur = s->directory.next;
805 array_ensure_allocated(&(s->directory), ROOT_ENTRIES - 1);
2b6a43a8 806 s->directory.next = ROOT_ENTRIES;
a046433a 807 memset(array_get(&(s->directory), cur), 0,
c227f099 808 (ROOT_ENTRIES - cur) * sizeof(direntry_t));
de167e41 809 }
5fafdf24 810
a046433a 811 /* reget the mapping, since s->mapping was possibly realloc()ed */
d4df3dbc 812 mapping = array_get(&(s->mapping), mapping_index);
a046433a
FB
813 first_cluster += (s->directory.next - mapping->info.dir.first_dir_index)
814 * 0x20 / s->cluster_size;
815 mapping->end = first_cluster;
816
d4df3dbc 817 direntry = array_get(&(s->directory), mapping->dir_index);
a046433a 818 set_begin_of_direntry(direntry, mapping->begin);
3b46e624 819
a046433a
FB
820 return 0;
821}
de167e41 822
a046433a
FB
823static inline uint32_t sector2cluster(BDRVVVFATState* s,off_t sector_num)
824{
825 return (sector_num-s->faked_sectors)/s->sectors_per_cluster;
826}
de167e41 827
a046433a
FB
828static inline off_t cluster2sector(BDRVVVFATState* s, uint32_t cluster_num)
829{
830 return s->faked_sectors + s->sectors_per_cluster * cluster_num;
831}
de167e41 832
a046433a 833static int init_directories(BDRVVVFATState* s,
d11c8917
MA
834 const char *dirname, int heads, int secs,
835 Error **errp)
de167e41 836{
c227f099
AL
837 bootsector_t* bootsector;
838 mapping_t* mapping;
de167e41
FB
839 unsigned int i;
840 unsigned int cluster;
841
842 memset(&(s->first_sectors[0]),0,0x40*0x200);
843
de167e41 844 s->cluster_size=s->sectors_per_cluster*0x200;
7267c094 845 s->cluster_buffer=g_malloc(s->cluster_size);
a046433a
FB
846
847 /*
848 * The formula: sc = spf+1+spf*spc*(512*8/fat_type),
849 * where sc is sector_count,
850 * spf is sectors_per_fat,
851 * spc is sectors_per_clusters, and
852 * fat_type = 12, 16 or 32.
853 */
854 i = 1+s->sectors_per_cluster*0x200*8/s->fat_type;
855 s->sectors_per_fat=(s->sector_count+i)/i; /* round up */
3b46e624 856
c227f099
AL
857 array_init(&(s->mapping),sizeof(mapping_t));
858 array_init(&(s->directory),sizeof(direntry_t));
de167e41
FB
859
860 /* add volume label */
861 {
c227f099 862 direntry_t* entry=array_get_next(&(s->directory));
de167e41 863 entry->attributes=0x28; /* archive | volume label */
d5941dda 864 memcpy(entry->name, s->volume_label, sizeof(entry->name));
de167e41
FB
865 }
866
de167e41
FB
867 /* Now build FAT, and write back information into directory */
868 init_fat(s);
869
a046433a
FB
870 s->faked_sectors=s->first_sectors_number+s->sectors_per_fat*2;
871 s->cluster_count=sector2cluster(s, s->sector_count);
872
873 mapping = array_get_next(&(s->mapping));
874 mapping->begin = 0;
875 mapping->dir_index = 0;
876 mapping->info.dir.parent_mapping_index = -1;
877 mapping->first_mapping_index = -1;
7267c094 878 mapping->path = g_strdup(dirname);
a046433a
FB
879 i = strlen(mapping->path);
880 if (i > 0 && mapping->path[i - 1] == '/')
881 mapping->path[i - 1] = '\0';
882 mapping->mode = MODE_DIRECTORY;
883 mapping->read_only = 0;
884 s->path = mapping->path;
885
886 for (i = 0, cluster = 0; i < s->mapping.next; i++) {
5fafdf24 887 /* MS-DOS expects the FAT to be 0 for the root directory
a046433a
FB
888 * (except for the media byte). */
889 /* LATER TODO: still true for FAT32? */
890 int fix_fat = (i != 0);
891 mapping = array_get(&(s->mapping), i);
892
893 if (mapping->mode & MODE_DIRECTORY) {
894 mapping->begin = cluster;
895 if(read_directory(s, i)) {
d11c8917
MA
896 error_setg(errp, "Could not read directory %s",
897 mapping->path);
de167e41
FB
898 return -1;
899 }
a046433a
FB
900 mapping = array_get(&(s->mapping), i);
901 } else {
902 assert(mapping->mode == MODE_UNDEFINED);
de167e41 903 mapping->mode=MODE_NORMAL;
a046433a
FB
904 mapping->begin = cluster;
905 if (mapping->end > 0) {
c227f099 906 direntry_t* direntry = array_get(&(s->directory),
a046433a
FB
907 mapping->dir_index);
908
909 mapping->end = cluster + 1 + (mapping->end-1)/s->cluster_size;
910 set_begin_of_direntry(direntry, mapping->begin);
911 } else {
912 mapping->end = cluster + 1;
913 fix_fat = 0;
de167e41 914 }
a046433a
FB
915 }
916
917 assert(mapping->begin < mapping->end);
918
8ce0f869
AZ
919 /* next free cluster */
920 cluster = mapping->end;
921
922 if(cluster > s->cluster_count) {
d11c8917
MA
923 error_setg(errp,
924 "Directory does not fit in FAT%d (capacity %.2f MB)",
925 s->fat_type, s->sector_count / 2000.0);
926 return -1;
8ce0f869
AZ
927 }
928
a046433a
FB
929 /* fix fat for entry */
930 if (fix_fat) {
8ce0f869 931 int j;
a046433a
FB
932 for(j = mapping->begin; j < mapping->end - 1; j++)
933 fat_set(s, j, j+1);
934 fat_set(s, mapping->end - 1, s->max_fat_value);
935 }
de167e41
FB
936 }
937
a046433a
FB
938 mapping = array_get(&(s->mapping), 0);
939 s->sectors_of_root_directory = mapping->end * s->sectors_per_cluster;
940 s->last_cluster_of_root_directory = mapping->end;
941
942 /* the FAT signature */
943 fat_set(s,0,s->max_fat_value);
944 fat_set(s,1,s->max_fat_value);
de167e41 945
a046433a
FB
946 s->current_mapping = NULL;
947
c227f099 948 bootsector=(bootsector_t*)(s->first_sectors+(s->first_sectors_number-1)*0x200);
de167e41
FB
949 bootsector->jump[0]=0xeb;
950 bootsector->jump[1]=0x3e;
951 bootsector->jump[2]=0x90;
952 memcpy(bootsector->name,"QEMU ",8);
953 bootsector->sector_size=cpu_to_le16(0x200);
954 bootsector->sectors_per_cluster=s->sectors_per_cluster;
955 bootsector->reserved_sectors=cpu_to_le16(1);
956 bootsector->number_of_fats=0x2; /* number of FATs */
957 bootsector->root_entries=cpu_to_le16(s->sectors_of_root_directory*0x10);
a046433a 958 bootsector->total_sectors16=s->sector_count>0xffff?0:cpu_to_le16(s->sector_count);
aad37c06 959 bootsector->media_type=(s->first_sectors_number>1?0xf8:0xf0); /* media descriptor (f8=hd, f0=3.5 fd)*/
a046433a 960 s->fat.pointer[0] = bootsector->media_type;
de167e41 961 bootsector->sectors_per_fat=cpu_to_le16(s->sectors_per_fat);
4480e0f9
MA
962 bootsector->sectors_per_track = cpu_to_le16(secs);
963 bootsector->number_of_heads = cpu_to_le16(heads);
de167e41 964 bootsector->hidden_sectors=cpu_to_le32(s->first_sectors_number==1?0:0x3f);
a046433a 965 bootsector->total_sectors=cpu_to_le32(s->sector_count>0xffff?s->sector_count:0);
de167e41 966
a046433a 967 /* LATER TODO: if FAT32, this is wrong */
aad37c06 968 bootsector->u.fat16.drive_number=s->first_sectors_number==1?0:0x80; /* fda=0, hda=0x80 */
de167e41
FB
969 bootsector->u.fat16.current_head=0;
970 bootsector->u.fat16.signature=0x29;
971 bootsector->u.fat16.id=cpu_to_le32(0xfabe1afd);
972
d5941dda
WB
973 memcpy(bootsector->u.fat16.volume_label, s->volume_label,
974 sizeof(bootsector->u.fat16.volume_label));
de167e41
FB
975 memcpy(bootsector->fat_type,(s->fat_type==12?"FAT12 ":s->fat_type==16?"FAT16 ":"FAT32 "),8);
976 bootsector->magic[0]=0x55; bootsector->magic[1]=0xaa;
977
978 return 0;
979}
980
83f64091 981#ifdef DEBUG
a046433a 982static BDRVVVFATState *vvv = NULL;
83f64091 983#endif
a046433a 984
68c70af1 985static int enable_write_target(BDRVVVFATState *s, Error **errp);
a046433a
FB
986static int is_consistent(BDRVVVFATState *s);
987
7ad9be64
KW
988static QemuOptsList runtime_opts = {
989 .name = "vvfat",
990 .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
991 .desc = {
992 {
993 .name = "dir",
994 .type = QEMU_OPT_STRING,
995 .help = "Host directory to map to the vvfat device",
996 },
997 {
998 .name = "fat-type",
999 .type = QEMU_OPT_NUMBER,
1000 .help = "FAT type (12, 16 or 32)",
1001 },
1002 {
1003 .name = "floppy",
1004 .type = QEMU_OPT_BOOL,
1005 .help = "Create a floppy rather than a hard disk image",
1006 },
d5941dda
WB
1007 {
1008 .name = "label",
1009 .type = QEMU_OPT_STRING,
1010 .help = "Use a volume label other than QEMU VVFAT",
1011 },
7ad9be64
KW
1012 {
1013 .name = "rw",
1014 .type = QEMU_OPT_BOOL,
1015 .help = "Make the image writable",
1016 },
1017 { /* end of list */ }
1018 },
1019};
1020
1021static void vvfat_parse_filename(const char *filename, QDict *options,
1022 Error **errp)
1023{
1024 int fat_type = 0;
1025 bool floppy = false;
1026 bool rw = false;
1027 int i;
1028
1029 if (!strstart(filename, "fat:", NULL)) {
1030 error_setg(errp, "File name string must start with 'fat:'");
1031 return;
1032 }
1033
1034 /* Parse options */
1035 if (strstr(filename, ":32:")) {
1036 fat_type = 32;
1037 } else if (strstr(filename, ":16:")) {
1038 fat_type = 16;
1039 } else if (strstr(filename, ":12:")) {
1040 fat_type = 12;
1041 }
1042
1043 if (strstr(filename, ":floppy:")) {
1044 floppy = true;
1045 }
1046
1047 if (strstr(filename, ":rw:")) {
1048 rw = true;
1049 }
1050
1051 /* Get the directory name without options */
1052 i = strrchr(filename, ':') - filename;
1053 assert(i >= 3);
1054 if (filename[i - 2] == ':' && qemu_isalpha(filename[i - 1])) {
1055 /* workaround for DOS drive names */
1056 filename += i - 1;
1057 } else {
1058 filename += i + 1;
1059 }
1060
1061 /* Fill in the options QDict */
1062 qdict_put(options, "dir", qstring_from_str(filename));
1063 qdict_put(options, "fat-type", qint_from_int(fat_type));
fc48ffc3
EB
1064 qdict_put(options, "floppy", qbool_from_bool(floppy));
1065 qdict_put(options, "rw", qbool_from_bool(rw));
7ad9be64
KW
1066}
1067
015a1036
HR
1068static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
1069 Error **errp)
de167e41
FB
1070{
1071 BDRVVVFATState *s = bs->opaque;
7ad9be64
KW
1072 int cyls, heads, secs;
1073 bool floppy;
d5941dda 1074 const char *dirname, *label;
7ad9be64
KW
1075 QemuOpts *opts;
1076 Error *local_err = NULL;
1077 int ret;
de167e41 1078
83f64091 1079#ifdef DEBUG
a046433a 1080 vvv = s;
83f64091 1081#endif
a046433a 1082
87ea75d5 1083 opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
7ad9be64 1084 qemu_opts_absorb_qdict(opts, options, &local_err);
84d18f06 1085 if (local_err) {
c0f92b52 1086 error_propagate(errp, local_err);
7ad9be64
KW
1087 ret = -EINVAL;
1088 goto fail;
1089 }
1090
1091 dirname = qemu_opt_get(opts, "dir");
1092 if (!dirname) {
c0f92b52 1093 error_setg(errp, "vvfat block driver requires a 'dir' option");
7ad9be64
KW
1094 ret = -EINVAL;
1095 goto fail;
1096 }
1097
1098 s->fat_type = qemu_opt_get_number(opts, "fat-type", 0);
1099 floppy = qemu_opt_get_bool(opts, "floppy", false);
1100
d5941dda
WB
1101 memset(s->volume_label, ' ', sizeof(s->volume_label));
1102 label = qemu_opt_get(opts, "label");
1103 if (label) {
1104 size_t label_length = strlen(label);
1105 if (label_length > 11) {
1106 error_setg(errp, "vvfat label cannot be longer than 11 bytes");
1107 ret = -EINVAL;
1108 goto fail;
1109 }
1110 memcpy(s->volume_label, label, label_length);
1111 }
1112
7ad9be64
KW
1113 if (floppy) {
1114 /* 1.44MB or 2.88MB floppy. 2.88MB can be FAT12 (default) or FAT16. */
1115 if (!s->fat_type) {
1116 s->fat_type = 12;
1117 secs = 36;
1118 s->sectors_per_cluster = 2;
1119 } else {
1120 secs = s->fat_type == 12 ? 18 : 36;
1121 s->sectors_per_cluster = 1;
1122 }
1123 s->first_sectors_number = 1;
1124 cyls = 80;
1125 heads = 2;
1126 } else {
1127 /* 32MB or 504MB disk*/
1128 if (!s->fat_type) {
1129 s->fat_type = 16;
1130 }
4c709660 1131 s->first_sectors_number = 0x40;
7ad9be64
KW
1132 cyls = s->fat_type == 12 ? 64 : 1024;
1133 heads = 16;
1134 secs = 63;
1135 }
1136
1137 switch (s->fat_type) {
1138 case 32:
1139 fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. "
1140 "You are welcome to do so!\n");
1141 break;
1142 case 16:
1143 case 12:
1144 break;
1145 default:
c0f92b52 1146 error_setg(errp, "Valid FAT types are only 12, 16 and 32");
7ad9be64
KW
1147 ret = -EINVAL;
1148 goto fail;
1149 }
1150
1151
a046433a
FB
1152 s->bs = bs;
1153
a046433a 1154 /* LATER TODO: if FAT32, adjust */
a046433a 1155 s->sectors_per_cluster=0x10;
de167e41
FB
1156
1157 s->current_cluster=0xffffffff;
de167e41 1158
a046433a
FB
1159 /* read only is the default for safety */
1160 bs->read_only = 1;
1161 s->qcow = s->write_target = NULL;
1162 s->qcow_filename = NULL;
1163 s->fat2 = NULL;
1164 s->downcase_short_names = 1;
3b46e624 1165
4480e0f9
MA
1166 fprintf(stderr, "vvfat %s chs %d,%d,%d\n",
1167 dirname, cyls, heads, secs);
a046433a 1168
4480e0f9 1169 s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1);
5a742b55 1170
7ad9be64 1171 if (qemu_opt_get_bool(opts, "rw", false)) {
68c70af1 1172 ret = enable_write_target(s, errp);
78f27bd0 1173 if (ret < 0) {
7ad9be64
KW
1174 goto fail;
1175 }
1176 bs->read_only = 0;
b570094d
TS
1177 }
1178
4480e0f9 1179 bs->total_sectors = cyls * heads * secs;
b570094d 1180
d11c8917 1181 if (init_directories(s, dirname, heads, secs, errp)) {
7ad9be64
KW
1182 ret = -EIO;
1183 goto fail;
4480e0f9 1184 }
de167e41 1185
b570094d
TS
1186 s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
1187
4480e0f9
MA
1188 if (s->first_sectors_number == 0x40) {
1189 init_mbr(s, cyls, heads, secs);
273e4e03 1190 }
a046433a
FB
1191
1192 // assert(is_consistent(s));
848c66e8 1193 qemu_co_mutex_init(&s->lock);
3397f0cb
KW
1194
1195 /* Disable migration when vvfat is used rw */
1196 if (s->qcow) {
81e5f78a
AG
1197 error_setg(&s->migration_blocker,
1198 "The vvfat (rw) format used by node '%s' "
1199 "does not support live migration",
1200 bdrv_get_device_or_node_name(bs));
3397f0cb
KW
1201 migrate_add_blocker(s->migration_blocker);
1202 }
1203
7ad9be64
KW
1204 ret = 0;
1205fail:
1206 qemu_opts_del(opts);
1207 return ret;
de167e41
FB
1208}
1209
1210static inline void vvfat_close_current_file(BDRVVVFATState *s)
1211{
1212 if(s->current_mapping) {
a046433a
FB
1213 s->current_mapping = NULL;
1214 if (s->current_fd) {
2e1e79da 1215 qemu_close(s->current_fd);
a046433a
FB
1216 s->current_fd = 0;
1217 }
de167e41 1218 }
a046433a 1219 s->current_cluster = -1;
de167e41
FB
1220}
1221
1222/* mappings between index1 and index2-1 are supposed to be ordered
1223 * return value is the index of the last mapping for which end>cluster_num
1224 */
1225static inline int find_mapping_for_cluster_aux(BDRVVVFATState* s,int cluster_num,int index1,int index2)
1226{
de167e41 1227 while(1) {
88bf7950 1228 int index3;
c227f099 1229 mapping_t* mapping;
de167e41
FB
1230 index3=(index1+index2)/2;
1231 mapping=array_get(&(s->mapping),index3);
a046433a
FB
1232 assert(mapping->begin < mapping->end);
1233 if(mapping->begin>=cluster_num) {
de167e41
FB
1234 assert(index2!=index3 || index2==0);
1235 if(index2==index3)
a046433a 1236 return index1;
de167e41
FB
1237 index2=index3;
1238 } else {
1239 if(index1==index3)
a046433a 1240 return mapping->end<=cluster_num ? index2 : index1;
de167e41
FB
1241 index1=index3;
1242 }
1243 assert(index1<=index2);
a046433a
FB
1244 DLOG(mapping=array_get(&(s->mapping),index1);
1245 assert(mapping->begin<=cluster_num);
5fafdf24 1246 assert(index2 >= s->mapping.next ||
a046433a
FB
1247 ((mapping = array_get(&(s->mapping),index2)) &&
1248 mapping->end>cluster_num)));
de167e41
FB
1249 }
1250}
1251
c227f099 1252static inline mapping_t* find_mapping_for_cluster(BDRVVVFATState* s,int cluster_num)
de167e41
FB
1253{
1254 int index=find_mapping_for_cluster_aux(s,cluster_num,0,s->mapping.next);
c227f099 1255 mapping_t* mapping;
de167e41 1256 if(index>=s->mapping.next)
511d2b14 1257 return NULL;
de167e41
FB
1258 mapping=array_get(&(s->mapping),index);
1259 if(mapping->begin>cluster_num)
511d2b14 1260 return NULL;
a046433a 1261 assert(mapping->begin<=cluster_num && mapping->end>cluster_num);
de167e41
FB
1262 return mapping;
1263}
1264
c227f099 1265static int open_file(BDRVVVFATState* s,mapping_t* mapping)
de167e41
FB
1266{
1267 if(!mapping)
1268 return -1;
de167e41 1269 if(!s->current_mapping ||
a046433a 1270 strcmp(s->current_mapping->path,mapping->path)) {
de167e41 1271 /* open file */
6165f4d8 1272 int fd = qemu_open(mapping->path, O_RDONLY | O_BINARY | O_LARGEFILE);
de167e41
FB
1273 if(fd<0)
1274 return -1;
1275 vvfat_close_current_file(s);
1276 s->current_fd = fd;
de167e41
FB
1277 s->current_mapping = mapping;
1278 }
1279 return 0;
1280}
1281
1282static inline int read_cluster(BDRVVVFATState *s,int cluster_num)
1283{
1284 if(s->current_cluster != cluster_num) {
1285 int result=0;
1286 off_t offset;
a046433a 1287 assert(!s->current_mapping || s->current_fd || (s->current_mapping->mode & MODE_DIRECTORY));
de167e41
FB
1288 if(!s->current_mapping
1289 || s->current_mapping->begin>cluster_num
1290 || s->current_mapping->end<=cluster_num) {
1291 /* binary search of mappings for file */
c227f099 1292 mapping_t* mapping=find_mapping_for_cluster(s,cluster_num);
a046433a
FB
1293
1294 assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
1295
1296 if (mapping && mapping->mode & MODE_DIRECTORY) {
1297 vvfat_close_current_file(s);
1298 s->current_mapping = mapping;
1299read_cluster_directory:
1300 offset = s->cluster_size*(cluster_num-s->current_mapping->begin);
ffe8ab83 1301 s->cluster = (unsigned char*)s->directory.pointer+offset
a046433a
FB
1302 + 0x20*s->current_mapping->info.dir.first_dir_index;
1303 assert(((s->cluster-(unsigned char*)s->directory.pointer)%s->cluster_size)==0);
1304 assert((char*)s->cluster+s->cluster_size <= s->directory.pointer+s->directory.next*s->directory.item_size);
1305 s->current_cluster = cluster_num;
1306 return 0;
1307 }
1308
1309 if(open_file(s,mapping))
de167e41 1310 return -2;
a046433a
FB
1311 } else if (s->current_mapping->mode & MODE_DIRECTORY)
1312 goto read_cluster_directory;
de167e41 1313
a046433a
FB
1314 assert(s->current_fd);
1315
1316 offset=s->cluster_size*(cluster_num-s->current_mapping->begin)+s->current_mapping->info.file.offset;
de167e41
FB
1317 if(lseek(s->current_fd, offset, SEEK_SET)!=offset)
1318 return -3;
a046433a 1319 s->cluster=s->cluster_buffer;
de167e41
FB
1320 result=read(s->current_fd,s->cluster,s->cluster_size);
1321 if(result<0) {
1322 s->current_cluster = -1;
1323 return -1;
1324 }
1325 s->current_cluster = cluster_num;
1326 }
1327 return 0;
1328}
1329
a046433a 1330#ifdef DEBUG
c227f099 1331static void print_direntry(const direntry_t* direntry)
de167e41 1332{
a046433a
FB
1333 int j = 0;
1334 char buffer[1024];
1335
3e89cb04 1336 fprintf(stderr, "direntry %p: ", direntry);
de167e41
FB
1337 if(!direntry)
1338 return;
a046433a 1339 if(is_long_name(direntry)) {
de167e41
FB
1340 unsigned char* c=(unsigned char*)direntry;
1341 int i;
1342 for(i=1;i<11 && c[i] && c[i]!=0xff;i+=2)
3891b370 1343#define ADD_CHAR(c) {buffer[j] = (c); if (buffer[j] < ' ') buffer[j] = 0xb0; j++;}
a046433a 1344 ADD_CHAR(c[i]);
de167e41 1345 for(i=14;i<26 && c[i] && c[i]!=0xff;i+=2)
a046433a 1346 ADD_CHAR(c[i]);
de167e41 1347 for(i=28;i<32 && c[i] && c[i]!=0xff;i+=2)
a046433a
FB
1348 ADD_CHAR(c[i]);
1349 buffer[j] = 0;
1350 fprintf(stderr, "%s\n", buffer);
de167e41
FB
1351 } else {
1352 int i;
1353 for(i=0;i<11;i++)
a046433a
FB
1354 ADD_CHAR(direntry->name[i]);
1355 buffer[j] = 0;
1356 fprintf(stderr,"%s attributes=0x%02x begin=%d size=%d\n",
1357 buffer,
de167e41 1358 direntry->attributes,
a046433a 1359 begin_of_direntry(direntry),le32_to_cpu(direntry->size));
de167e41
FB
1360 }
1361}
1362
c227f099 1363static void print_mapping(const mapping_t* mapping)
de167e41 1364{
3e89cb04
KW
1365 fprintf(stderr, "mapping (%p): begin, end = %d, %d, dir_index = %d, "
1366 "first_mapping_index = %d, name = %s, mode = 0x%x, " ,
1367 mapping, mapping->begin, mapping->end, mapping->dir_index,
1368 mapping->first_mapping_index, mapping->path, mapping->mode);
1369
a046433a
FB
1370 if (mapping->mode & MODE_DIRECTORY)
1371 fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
1372 else
1373 fprintf(stderr, "offset = %d\n", mapping->info.file.offset);
de167e41 1374}
a046433a 1375#endif
de167e41 1376
5fafdf24 1377static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
a046433a 1378 uint8_t *buf, int nb_sectors)
de167e41 1379{
a046433a 1380 BDRVVVFATState *s = bs->opaque;
de167e41 1381 int i;
de167e41 1382
a046433a 1383 for(i=0;i<nb_sectors;i++,sector_num++) {
e654bfe4 1384 if (sector_num >= bs->total_sectors)
a046433a
FB
1385 return -1;
1386 if (s->qcow) {
1387 int n;
7704df98 1388 if (bdrv_is_allocated(s->qcow, sector_num, nb_sectors-i, &n)) {
a046433a 1389DLOG(fprintf(stderr, "sectors %d+%d allocated\n", (int)sector_num, n));
7704df98
KW
1390 if (bdrv_read(s->qcow, sector_num, buf + i*0x200, n)) {
1391 return -1;
1392 }
1393 i += n - 1;
1394 sector_num += n - 1;
1395 continue;
1396 }
a046433a 1397DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num));
de167e41 1398 }
a046433a
FB
1399 if(sector_num<s->faked_sectors) {
1400 if(sector_num<s->first_sectors_number)
1401 memcpy(buf+i*0x200,&(s->first_sectors[sector_num*0x200]),0x200);
1402 else if(sector_num-s->first_sectors_number<s->sectors_per_fat)
1403 memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number)*0x200]),0x200);
1404 else if(sector_num-s->first_sectors_number-s->sectors_per_fat<s->sectors_per_fat)
1405 memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number-s->sectors_per_fat)*0x200]),0x200);
1406 } else {
1407 uint32_t sector=sector_num-s->faked_sectors,
1408 sector_offset_in_cluster=(sector%s->sectors_per_cluster),
1409 cluster_num=sector/s->sectors_per_cluster;
e654bfe4 1410 if(cluster_num > s->cluster_count || read_cluster(s, cluster_num) != 0) {
a046433a
FB
1411 /* LATER TODO: strict: return -1; */
1412 memset(buf+i*0x200,0,0x200);
1413 continue;
de167e41 1414 }
a046433a 1415 memcpy(buf+i*0x200,s->cluster+sector_offset_in_cluster*0x200,0x200);
de167e41
FB
1416 }
1417 }
de167e41
FB
1418 return 0;
1419}
1420
2914caa0
PB
1421static coroutine_fn int vvfat_co_read(BlockDriverState *bs, int64_t sector_num,
1422 uint8_t *buf, int nb_sectors)
1423{
1424 int ret;
1425 BDRVVVFATState *s = bs->opaque;
1426 qemu_co_mutex_lock(&s->lock);
1427 ret = vvfat_read(bs, sector_num, buf, nb_sectors);
1428 qemu_co_mutex_unlock(&s->lock);
1429 return ret;
1430}
1431
a046433a 1432/* LATER TODO: statify all functions */
de167e41 1433
a046433a
FB
1434/*
1435 * Idea of the write support (use snapshot):
de167e41 1436 *
a046433a
FB
1437 * 1. check if all data is consistent, recording renames, modifications,
1438 * new files and directories (in s->commits).
de167e41 1439 *
a046433a 1440 * 2. if the data is not consistent, stop committing
de167e41 1441 *
a046433a
FB
1442 * 3. handle renames, and create new files and directories (do not yet
1443 * write their contents)
de167e41 1444 *
a046433a
FB
1445 * 4. walk the directories, fixing the mapping and direntries, and marking
1446 * the handled mappings as not deleted
de167e41 1447 *
a046433a 1448 * 5. commit the contents of the files
de167e41 1449 *
a046433a 1450 * 6. handle deleted files and directories
de167e41
FB
1451 *
1452 */
1453
c227f099 1454typedef struct commit_t {
a046433a
FB
1455 char* path;
1456 union {
1457 struct { uint32_t cluster; } rename;
1458 struct { int dir_index; uint32_t modified_offset; } writeout;
1459 struct { uint32_t first_cluster; } new_file;
1460 struct { uint32_t cluster; } mkdir;
1461 } param;
1462 /* DELETEs and RMDIRs are handled differently: see handle_deletes() */
1463 enum {
1464 ACTION_RENAME, ACTION_WRITEOUT, ACTION_NEW_FILE, ACTION_MKDIR
1465 } action;
c227f099 1466} commit_t;
de167e41 1467
a046433a 1468static void clear_commits(BDRVVVFATState* s)
de167e41
FB
1469{
1470 int i;
a046433a
FB
1471DLOG(fprintf(stderr, "clear_commits (%d commits)\n", s->commits.next));
1472 for (i = 0; i < s->commits.next; i++) {
c227f099 1473 commit_t* commit = array_get(&(s->commits), i);
a046433a
FB
1474 assert(commit->path || commit->action == ACTION_WRITEOUT);
1475 if (commit->action != ACTION_WRITEOUT) {
1476 assert(commit->path);
ce137829 1477 g_free(commit->path);
a046433a
FB
1478 } else
1479 assert(commit->path == NULL);
de167e41 1480 }
a046433a 1481 s->commits.next = 0;
de167e41
FB
1482}
1483
a046433a
FB
1484static void schedule_rename(BDRVVVFATState* s,
1485 uint32_t cluster, char* new_path)
de167e41 1486{
c227f099 1487 commit_t* commit = array_get_next(&(s->commits));
a046433a
FB
1488 commit->path = new_path;
1489 commit->param.rename.cluster = cluster;
1490 commit->action = ACTION_RENAME;
de167e41
FB
1491}
1492
a046433a
FB
1493static void schedule_writeout(BDRVVVFATState* s,
1494 int dir_index, uint32_t modified_offset)
de167e41 1495{
c227f099 1496 commit_t* commit = array_get_next(&(s->commits));
a046433a
FB
1497 commit->path = NULL;
1498 commit->param.writeout.dir_index = dir_index;
1499 commit->param.writeout.modified_offset = modified_offset;
1500 commit->action = ACTION_WRITEOUT;
de167e41
FB
1501}
1502
a046433a
FB
1503static void schedule_new_file(BDRVVVFATState* s,
1504 char* path, uint32_t first_cluster)
de167e41 1505{
c227f099 1506 commit_t* commit = array_get_next(&(s->commits));
a046433a
FB
1507 commit->path = path;
1508 commit->param.new_file.first_cluster = first_cluster;
1509 commit->action = ACTION_NEW_FILE;
1510}
1511
1512static void schedule_mkdir(BDRVVVFATState* s, uint32_t cluster, char* path)
1513{
c227f099 1514 commit_t* commit = array_get_next(&(s->commits));
a046433a
FB
1515 commit->path = path;
1516 commit->param.mkdir.cluster = cluster;
1517 commit->action = ACTION_MKDIR;
1518}
1519
1520typedef struct {
64eaabda
TS
1521 /*
1522 * Since the sequence number is at most 0x3f, and the filename
1523 * length is at most 13 times the sequence number, the maximal
1524 * filename length is 0x3f * 13 bytes.
1525 */
1526 unsigned char name[0x3f * 13 + 1];
a046433a
FB
1527 int checksum, len;
1528 int sequence_number;
1529} long_file_name;
1530
1531static void lfn_init(long_file_name* lfn)
1532{
1533 lfn->sequence_number = lfn->len = 0;
1534 lfn->checksum = 0x100;
1535}
1536
1537/* return 0 if parsed successfully, > 0 if no long name, < 0 if error */
1538static int parse_long_name(long_file_name* lfn,
c227f099 1539 const direntry_t* direntry)
a046433a
FB
1540{
1541 int i, j, offset;
1542 const unsigned char* pointer = (const unsigned char*)direntry;
1543
1544 if (!is_long_name(direntry))
1545 return 1;
1546
1547 if (pointer[0] & 0x40) {
1548 lfn->sequence_number = pointer[0] & 0x3f;
1549 lfn->checksum = pointer[13];
1550 lfn->name[0] = 0;
59fdb018 1551 lfn->name[lfn->sequence_number * 13] = 0;
a046433a
FB
1552 } else if ((pointer[0] & 0x3f) != --lfn->sequence_number)
1553 return -1;
1554 else if (pointer[13] != lfn->checksum)
1555 return -2;
1556 else if (pointer[12] || pointer[26] || pointer[27])
1557 return -3;
1558
1559 offset = 13 * (lfn->sequence_number - 1);
1560 for (i = 0, j = 1; i < 13; i++, j+=2) {
1561 if (j == 11)
1562 j = 14;
1563 else if (j == 26)
1564 j = 28;
1565
1566 if (pointer[j+1] == 0)
1567 lfn->name[offset + i] = pointer[j];
1568 else if (pointer[j+1] != 0xff || (pointer[0] & 0x40) == 0)
1569 return -4;
1570 else
1571 lfn->name[offset + i] = 0;
de167e41 1572 }
a046433a
FB
1573
1574 if (pointer[0] & 0x40)
ffe8ab83 1575 lfn->len = offset + strlen((char*)lfn->name + offset);
a046433a 1576
de167e41
FB
1577 return 0;
1578}
1579
a046433a
FB
1580/* returns 0 if successful, >0 if no short_name, and <0 on error */
1581static int parse_short_name(BDRVVVFATState* s,
c227f099 1582 long_file_name* lfn, direntry_t* direntry)
de167e41 1583{
a046433a 1584 int i, j;
de167e41 1585
a046433a
FB
1586 if (!is_short_name(direntry))
1587 return 1;
1588
1589 for (j = 7; j >= 0 && direntry->name[j] == ' '; j--);
1590 for (i = 0; i <= j; i++) {
1591 if (direntry->name[i] <= ' ' || direntry->name[i] > 0x7f)
1592 return -1;
1593 else if (s->downcase_short_names)
47398b9c 1594 lfn->name[i] = qemu_tolower(direntry->name[i]);
a046433a
FB
1595 else
1596 lfn->name[i] = direntry->name[i];
de167e41
FB
1597 }
1598
f671d173
SW
1599 for (j = 2; j >= 0 && direntry->name[8 + j] == ' '; j--) {
1600 }
a046433a
FB
1601 if (j >= 0) {
1602 lfn->name[i++] = '.';
1603 lfn->name[i + j + 1] = '\0';
1604 for (;j >= 0; j--) {
f671d173
SW
1605 uint8_t c = direntry->name[8 + j];
1606 if (c <= ' ' || c > 0x7f) {
1607 return -2;
1608 } else if (s->downcase_short_names) {
1609 lfn->name[i + j] = qemu_tolower(c);
1610 } else {
1611 lfn->name[i + j] = c;
1612 }
a046433a
FB
1613 }
1614 } else
1615 lfn->name[i + j + 1] = '\0';
1616
ffe8ab83 1617 lfn->len = strlen((char*)lfn->name);
a046433a
FB
1618
1619 return 0;
de167e41
FB
1620}
1621
a046433a
FB
1622static inline uint32_t modified_fat_get(BDRVVVFATState* s,
1623 unsigned int cluster)
de167e41 1624{
a046433a
FB
1625 if (cluster < s->last_cluster_of_root_directory) {
1626 if (cluster + 1 == s->last_cluster_of_root_directory)
1627 return s->max_fat_value;
1628 else
1629 return cluster + 1;
1630 }
1631
1632 if (s->fat_type==32) {
1633 uint32_t* entry=((uint32_t*)s->fat2)+cluster;
1634 return le32_to_cpu(*entry);
1635 } else if (s->fat_type==16) {
1636 uint16_t* entry=((uint16_t*)s->fat2)+cluster;
1637 return le16_to_cpu(*entry);
1638 } else {
1639 const uint8_t* x=s->fat2+cluster*3/2;
1640 return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
1641 }
1642}
1643
1644static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num)
1645{
1646 int was_modified = 0;
1647 int i, dummy;
1648
1649 if (s->qcow == NULL)
de167e41 1650 return 0;
a046433a
FB
1651
1652 for (i = 0; !was_modified && i < s->sectors_per_cluster; i++)
7704df98 1653 was_modified = bdrv_is_allocated(s->qcow,
a046433a
FB
1654 cluster2sector(s, cluster_num) + i, 1, &dummy);
1655
1656 return was_modified;
de167e41
FB
1657}
1658
a046433a 1659static const char* get_basename(const char* path)
de167e41 1660{
a046433a
FB
1661 char* basename = strrchr(path, '/');
1662 if (basename == NULL)
1663 return path;
1664 else
1665 return basename + 1; /* strip '/' */
de167e41
FB
1666}
1667
a046433a
FB
1668/*
1669 * The array s->used_clusters holds the states of the clusters. If it is
1670 * part of a file, it has bit 2 set, in case of a directory, bit 1. If it
1671 * was modified, bit 3 is set.
1672 * If any cluster is allocated, but not part of a file or directory, this
1673 * driver refuses to commit.
1674 */
1675typedef enum {
1676 USED_DIRECTORY = 1, USED_FILE = 2, USED_ANY = 3, USED_ALLOCATED = 4
c227f099 1677} used_t;
de167e41 1678
a046433a
FB
1679/*
1680 * get_cluster_count_for_direntry() not only determines how many clusters
1681 * are occupied by direntry, but also if it was renamed or modified.
1682 *
1683 * A file is thought to be renamed *only* if there already was a file with
1684 * exactly the same first cluster, but a different name.
1685 *
1686 * Further, the files/directories handled by this function are
1687 * assumed to be *not* deleted (and *only* those).
1688 */
1689static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
c227f099 1690 direntry_t* direntry, const char* path)
de167e41 1691{
a046433a
FB
1692 /*
1693 * This is a little bit tricky:
1694 * IF the guest OS just inserts a cluster into the file chain,
1695 * and leaves the rest alone, (i.e. the original file had clusters
1696 * 15 -> 16, but now has 15 -> 32 -> 16), then the following happens:
1697 *
1698 * - do_commit will write the cluster into the file at the given
1699 * offset, but
1700 *
1701 * - the cluster which is overwritten should be moved to a later
1702 * position in the file.
1703 *
1704 * I am not aware that any OS does something as braindead, but this
1705 * situation could happen anyway when not committing for a long time.
1706 * Just to be sure that this does not bite us, detect it, and copy the
1707 * contents of the clusters to-be-overwritten into the qcow.
1708 */
1709 int copy_it = 0;
1710 int was_modified = 0;
1711 int32_t ret = 0;
1712
1713 uint32_t cluster_num = begin_of_direntry(direntry);
1714 uint32_t offset = 0;
1715 int first_mapping_index = -1;
c227f099 1716 mapping_t* mapping = NULL;
a046433a 1717 const char* basename2 = NULL;
de167e41 1718
a046433a 1719 vvfat_close_current_file(s);
de167e41 1720
a046433a
FB
1721 /* the root directory */
1722 if (cluster_num == 0)
de167e41 1723 return 0;
de167e41 1724
a046433a
FB
1725 /* write support */
1726 if (s->qcow) {
1727 basename2 = get_basename(path);
de167e41 1728
a046433a
FB
1729 mapping = find_mapping_for_cluster(s, cluster_num);
1730
1731 if (mapping) {
da2414e9
FB
1732 const char* basename;
1733
a046433a
FB
1734 assert(mapping->mode & MODE_DELETED);
1735 mapping->mode &= ~MODE_DELETED;
1736
da2414e9 1737 basename = get_basename(mapping->path);
a046433a
FB
1738
1739 assert(mapping->mode & MODE_NORMAL);
1740
1741 /* rename */
1742 if (strcmp(basename, basename2))
7267c094 1743 schedule_rename(s, cluster_num, g_strdup(path));
a046433a
FB
1744 } else if (is_file(direntry))
1745 /* new file */
7267c094 1746 schedule_new_file(s, g_strdup(path), cluster_num);
a046433a 1747 else {
43dc2a64 1748 abort();
a046433a
FB
1749 return 0;
1750 }
de167e41
FB
1751 }
1752
a046433a
FB
1753 while(1) {
1754 if (s->qcow) {
1755 if (!copy_it && cluster_was_modified(s, cluster_num)) {
1756 if (mapping == NULL ||
1757 mapping->begin > cluster_num ||
1758 mapping->end <= cluster_num)
1759 mapping = find_mapping_for_cluster(s, cluster_num);
de167e41 1760
a046433a
FB
1761
1762 if (mapping &&
1763 (mapping->mode & MODE_DIRECTORY) == 0) {
1764
1765 /* was modified in qcow */
1766 if (offset != mapping->info.file.offset + s->cluster_size
1767 * (cluster_num - mapping->begin)) {
1768 /* offset of this cluster in file chain has changed */
43dc2a64 1769 abort();
a046433a
FB
1770 copy_it = 1;
1771 } else if (offset == 0) {
1772 const char* basename = get_basename(mapping->path);
1773
1774 if (strcmp(basename, basename2))
1775 copy_it = 1;
1776 first_mapping_index = array_index(&(s->mapping), mapping);
1777 }
1778
1779 if (mapping->first_mapping_index != first_mapping_index
1780 && mapping->info.file.offset > 0) {
43dc2a64 1781 abort();
a046433a
FB
1782 copy_it = 1;
1783 }
1784
1785 /* need to write out? */
1786 if (!was_modified && is_file(direntry)) {
1787 was_modified = 1;
1788 schedule_writeout(s, mapping->dir_index, offset);
1789 }
1790 }
1791 }
1792
1793 if (copy_it) {
1794 int i, dummy;
1795 /*
1796 * This is horribly inefficient, but that is okay, since
1797 * it is rarely executed, if at all.
1798 */
1799 int64_t offset = cluster2sector(s, cluster_num);
1800
1801 vvfat_close_current_file(s);
7704df98
KW
1802 for (i = 0; i < s->sectors_per_cluster; i++) {
1803 if (!bdrv_is_allocated(s->qcow, offset + i, 1, &dummy)) {
1804 if (vvfat_read(s->bs, offset, s->cluster_buffer, 1)) {
1805 return -1;
1806 }
1807 if (bdrv_write(s->qcow, offset, s->cluster_buffer, 1)) {
1808 return -2;
1809 }
1810 }
1811 }
a046433a
FB
1812 }
1813 }
1814
1815 ret++;
1816 if (s->used_clusters[cluster_num] & USED_ANY)
1817 return 0;
1818 s->used_clusters[cluster_num] = USED_FILE;
1819
1820 cluster_num = modified_fat_get(s, cluster_num);
1821
1822 if (fat_eof(s, cluster_num))
1823 return ret;
1824 else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
1825 return -1;
1826
1827 offset += s->cluster_size;
1828 }
de167e41
FB
1829}
1830
a046433a 1831/*
5fafdf24 1832 * This function looks at the modified data (qcow).
a046433a
FB
1833 * It returns 0 upon inconsistency or error, and the number of clusters
1834 * used by the directory, its subdirectories and their files.
1835 */
1836static int check_directory_consistency(BDRVVVFATState *s,
1837 int cluster_num, const char* path)
de167e41 1838{
a046433a 1839 int ret = 0;
7267c094 1840 unsigned char* cluster = g_malloc(s->cluster_size);
c227f099
AL
1841 direntry_t* direntries = (direntry_t*)cluster;
1842 mapping_t* mapping = find_mapping_for_cluster(s, cluster_num);
a046433a
FB
1843
1844 long_file_name lfn;
1845 int path_len = strlen(path);
0d460d6f 1846 char path2[PATH_MAX + 1];
a046433a
FB
1847
1848 assert(path_len < PATH_MAX); /* len was tested before! */
363a37d5 1849 pstrcpy(path2, sizeof(path2), path);
a046433a
FB
1850 path2[path_len] = '/';
1851 path2[path_len + 1] = '\0';
1852
1853 if (mapping) {
1854 const char* basename = get_basename(mapping->path);
1855 const char* basename2 = get_basename(path);
1856
1857 assert(mapping->mode & MODE_DIRECTORY);
1858
1859 assert(mapping->mode & MODE_DELETED);
1860 mapping->mode &= ~MODE_DELETED;
1861
1862 if (strcmp(basename, basename2))
7267c094 1863 schedule_rename(s, cluster_num, g_strdup(path));
a046433a
FB
1864 } else
1865 /* new directory */
7267c094 1866 schedule_mkdir(s, cluster_num, g_strdup(path));
3b46e624 1867
a046433a
FB
1868 lfn_init(&lfn);
1869 do {
de167e41 1870 int i;
a046433a
FB
1871 int subret = 0;
1872
1873 ret++;
1874
1875 if (s->used_clusters[cluster_num] & USED_ANY) {
1876 fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
6262bbd3 1877 goto fail;
a046433a
FB
1878 }
1879 s->used_clusters[cluster_num] = USED_DIRECTORY;
1880
1881DLOG(fprintf(stderr, "read cluster %d (sector %d)\n", (int)cluster_num, (int)cluster2sector(s, cluster_num)));
1882 subret = vvfat_read(s->bs, cluster2sector(s, cluster_num), cluster,
1883 s->sectors_per_cluster);
1884 if (subret) {
1885 fprintf(stderr, "Error fetching direntries\n");
1886 fail:
ce137829 1887 g_free(cluster);
a046433a
FB
1888 return 0;
1889 }
1890
1891 for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
3f4cb3d3 1892 int cluster_count = 0;
a046433a 1893
b2bedb21 1894DLOG(fprintf(stderr, "check direntry %d:\n", i); print_direntry(direntries + i));
a046433a
FB
1895 if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
1896 is_free(direntries + i))
1897 continue;
1898
1899 subret = parse_long_name(&lfn, direntries + i);
1900 if (subret < 0) {
1901 fprintf(stderr, "Error in long name\n");
1902 goto fail;
de167e41 1903 }
a046433a
FB
1904 if (subret == 0 || is_free(direntries + i))
1905 continue;
1906
1907 if (fat_chksum(direntries+i) != lfn.checksum) {
1908 subret = parse_short_name(s, &lfn, direntries + i);
1909 if (subret < 0) {
1910 fprintf(stderr, "Error in short name (%d)\n", subret);
1911 goto fail;
1912 }
ffe8ab83
TS
1913 if (subret > 0 || !strcmp((char*)lfn.name, ".")
1914 || !strcmp((char*)lfn.name, ".."))
a046433a
FB
1915 continue;
1916 }
1917 lfn.checksum = 0x100; /* cannot use long name twice */
1918
1919 if (path_len + 1 + lfn.len >= PATH_MAX) {
1920 fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
1921 goto fail;
1922 }
363a37d5
BS
1923 pstrcpy(path2 + path_len + 1, sizeof(path2) - path_len - 1,
1924 (char*)lfn.name);
a046433a
FB
1925
1926 if (is_directory(direntries + i)) {
1927 if (begin_of_direntry(direntries + i) == 0) {
1928 DLOG(fprintf(stderr, "invalid begin for directory: %s\n", path2); print_direntry(direntries + i));
1929 goto fail;
1930 }
1931 cluster_count = check_directory_consistency(s,
1932 begin_of_direntry(direntries + i), path2);
1933 if (cluster_count == 0) {
1934 DLOG(fprintf(stderr, "problem in directory %s:\n", path2); print_direntry(direntries + i));
1935 goto fail;
1936 }
1937 } else if (is_file(direntries + i)) {
1938 /* check file size with FAT */
1939 cluster_count = get_cluster_count_for_direntry(s, direntries + i, path2);
1940 if (cluster_count !=
1941 (le32_to_cpu(direntries[i].size) + s->cluster_size
1942 - 1) / s->cluster_size) {
1943 DLOG(fprintf(stderr, "Cluster count mismatch\n"));
1944 goto fail;
1945 }
1946 } else
43dc2a64 1947 abort(); /* cluster_count = 0; */
a046433a
FB
1948
1949 ret += cluster_count;
de167e41 1950 }
de167e41 1951
a046433a
FB
1952 cluster_num = modified_fat_get(s, cluster_num);
1953 } while(!fat_eof(s, cluster_num));
de167e41 1954
ce137829 1955 g_free(cluster);
a046433a
FB
1956 return ret;
1957}
1958
1959/* returns 1 on success */
1960static int is_consistent(BDRVVVFATState* s)
1961{
1962 int i, check;
1963 int used_clusters_count = 0;
1964
1965DLOG(checkpoint());
1966 /*
1967 * - get modified FAT
1968 * - compare the two FATs (TODO)
1969 * - get buffer for marking used clusters
1970 * - recurse direntries from root (using bs->bdrv_read to make
1971 * sure to get the new data)
1972 * - check that the FAT agrees with the size
1973 * - count the number of clusters occupied by this directory and
1974 * its files
1975 * - check that the cumulative used cluster count agrees with the
1976 * FAT
1977 * - if all is fine, return number of used clusters
1978 */
1979 if (s->fat2 == NULL) {
1980 int size = 0x200 * s->sectors_per_fat;
7267c094 1981 s->fat2 = g_malloc(size);
a046433a
FB
1982 memcpy(s->fat2, s->fat.pointer, size);
1983 }
1984 check = vvfat_read(s->bs,
1985 s->first_sectors_number, s->fat2, s->sectors_per_fat);
1986 if (check) {
1987 fprintf(stderr, "Could not copy fat\n");
1988 return 0;
1989 }
1990 assert (s->used_clusters);
1991 for (i = 0; i < sector2cluster(s, s->sector_count); i++)
1992 s->used_clusters[i] &= ~USED_ANY;
1993
1994 clear_commits(s);
1995
1996 /* mark every mapped file/directory as deleted.
1997 * (check_directory_consistency() will unmark those still present). */
1998 if (s->qcow)
1999 for (i = 0; i < s->mapping.next; i++) {
c227f099 2000 mapping_t* mapping = array_get(&(s->mapping), i);
a046433a
FB
2001 if (mapping->first_mapping_index < 0)
2002 mapping->mode |= MODE_DELETED;
de167e41 2003 }
a046433a
FB
2004
2005 used_clusters_count = check_directory_consistency(s, 0, s->path);
2006 if (used_clusters_count <= 0) {
2007 DLOG(fprintf(stderr, "problem in directory\n"));
2008 return 0;
de167e41
FB
2009 }
2010
a046433a
FB
2011 check = s->last_cluster_of_root_directory;
2012 for (i = check; i < sector2cluster(s, s->sector_count); i++) {
2013 if (modified_fat_get(s, i)) {
2014 if(!s->used_clusters[i]) {
2015 DLOG(fprintf(stderr, "FAT was modified (%d), but cluster is not used?\n", i));
2016 return 0;
2017 }
2018 check++;
2019 }
2020
2021 if (s->used_clusters[i] == USED_ALLOCATED) {
2022 /* allocated, but not used... */
2023 DLOG(fprintf(stderr, "unused, modified cluster: %d\n", i));
2024 return 0;
2025 }
2026 }
2027
2028 if (check != used_clusters_count)
2029 return 0;
2030
2031 return used_clusters_count;
2032}
2033
2034static inline void adjust_mapping_indices(BDRVVVFATState* s,
2035 int offset, int adjust)
2036{
2037 int i;
2038
2039 for (i = 0; i < s->mapping.next; i++) {
c227f099 2040 mapping_t* mapping = array_get(&(s->mapping), i);
a046433a
FB
2041
2042#define ADJUST_MAPPING_INDEX(name) \
2043 if (mapping->name >= offset) \
2044 mapping->name += adjust
2045
2046 ADJUST_MAPPING_INDEX(first_mapping_index);
2047 if (mapping->mode & MODE_DIRECTORY)
2048 ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
de167e41 2049 }
a046433a
FB
2050}
2051
2052/* insert or update mapping */
c227f099 2053static mapping_t* insert_mapping(BDRVVVFATState* s,
a046433a
FB
2054 uint32_t begin, uint32_t end)
2055{
2056 /*
2057 * - find mapping where mapping->begin >= begin,
2058 * - if mapping->begin > begin: insert
2059 * - adjust all references to mappings!
2060 * - else: adjust
2061 * - replace name
2062 */
2063 int index = find_mapping_for_cluster_aux(s, begin, 0, s->mapping.next);
c227f099
AL
2064 mapping_t* mapping = NULL;
2065 mapping_t* first_mapping = array_get(&(s->mapping), 0);
a046433a
FB
2066
2067 if (index < s->mapping.next && (mapping = array_get(&(s->mapping), index))
2068 && mapping->begin < begin) {
2069 mapping->end = begin;
2070 index++;
2071 mapping = array_get(&(s->mapping), index);
2072 }
2073 if (index >= s->mapping.next || mapping->begin > begin) {
2074 mapping = array_insert(&(s->mapping), index, 1);
2075 mapping->path = NULL;
2076 adjust_mapping_indices(s, index, +1);
2077 }
2078
2079 mapping->begin = begin;
2080 mapping->end = end;
de167e41 2081
c227f099 2082DLOG(mapping_t* next_mapping;
a046433a
FB
2083assert(index + 1 >= s->mapping.next ||
2084((next_mapping = array_get(&(s->mapping), index + 1)) &&
2085 next_mapping->begin >= end)));
2086
c227f099 2087 if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
a046433a
FB
2088 s->current_mapping = array_get(&(s->mapping),
2089 s->current_mapping - first_mapping);
2090
2091 return mapping;
2092}
2093
2094static int remove_mapping(BDRVVVFATState* s, int mapping_index)
2095{
c227f099
AL
2096 mapping_t* mapping = array_get(&(s->mapping), mapping_index);
2097 mapping_t* first_mapping = array_get(&(s->mapping), 0);
a046433a
FB
2098
2099 /* free mapping */
ce137829
SW
2100 if (mapping->first_mapping_index < 0) {
2101 g_free(mapping->path);
2102 }
a046433a
FB
2103
2104 /* remove from s->mapping */
2105 array_remove(&(s->mapping), mapping_index);
2106
2107 /* adjust all references to mappings */
2108 adjust_mapping_indices(s, mapping_index, -1);
2109
c227f099 2110 if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
a046433a
FB
2111 s->current_mapping = array_get(&(s->mapping),
2112 s->current_mapping - first_mapping);
de167e41 2113
de167e41
FB
2114 return 0;
2115}
2116
a046433a
FB
2117static void adjust_dirindices(BDRVVVFATState* s, int offset, int adjust)
2118{
2119 int i;
2120 for (i = 0; i < s->mapping.next; i++) {
c227f099 2121 mapping_t* mapping = array_get(&(s->mapping), i);
a046433a
FB
2122 if (mapping->dir_index >= offset)
2123 mapping->dir_index += adjust;
2124 if ((mapping->mode & MODE_DIRECTORY) &&
2125 mapping->info.dir.first_dir_index >= offset)
2126 mapping->info.dir.first_dir_index += adjust;
2127 }
2128}
de167e41 2129
c227f099 2130static direntry_t* insert_direntries(BDRVVVFATState* s,
a046433a 2131 int dir_index, int count)
de167e41 2132{
a046433a
FB
2133 /*
2134 * make room in s->directory,
2135 * adjust_dirindices
2136 */
c227f099 2137 direntry_t* result = array_insert(&(s->directory), dir_index, count);
a046433a
FB
2138 if (result == NULL)
2139 return NULL;
2140 adjust_dirindices(s, dir_index, count);
de167e41
FB
2141 return result;
2142}
2143
a046433a
FB
2144static int remove_direntries(BDRVVVFATState* s, int dir_index, int count)
2145{
2146 int ret = array_remove_slice(&(s->directory), dir_index, count);
2147 if (ret)
2148 return ret;
2149 adjust_dirindices(s, dir_index, -count);
2150 return 0;
2151}
de167e41 2152
a046433a
FB
2153/*
2154 * Adapt the mappings of the cluster chain starting at first cluster
2155 * (i.e. if a file starts at first_cluster, the chain is followed according
2156 * to the modified fat, and the corresponding entries in s->mapping are
2157 * adjusted)
2158 */
2159static int commit_mappings(BDRVVVFATState* s,
2160 uint32_t first_cluster, int dir_index)
de167e41 2161{
c227f099
AL
2162 mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2163 direntry_t* direntry = array_get(&(s->directory), dir_index);
a046433a
FB
2164 uint32_t cluster = first_cluster;
2165
2166 vvfat_close_current_file(s);
2167
2168 assert(mapping);
2169 assert(mapping->begin == first_cluster);
2170 mapping->first_mapping_index = -1;
2171 mapping->dir_index = dir_index;
2172 mapping->mode = (dir_index <= 0 || is_directory(direntry)) ?
2173 MODE_DIRECTORY : MODE_NORMAL;
2174
2175 while (!fat_eof(s, cluster)) {
2176 uint32_t c, c1;
2177
2178 for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
2179 c = c1, c1 = modified_fat_get(s, c1));
2180
2181 c++;
2182 if (c > mapping->end) {
2183 int index = array_index(&(s->mapping), mapping);
2184 int i, max_i = s->mapping.next - index;
2185 for (i = 1; i < max_i && mapping[i].begin < c; i++);
2186 while (--i > 0)
2187 remove_mapping(s, index + 1);
2188 }
2189 assert(mapping == array_get(&(s->mapping), s->mapping.next - 1)
2190 || mapping[1].begin >= c);
2191 mapping->end = c;
2192
2193 if (!fat_eof(s, c1)) {
2194 int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next);
c227f099 2195 mapping_t* next_mapping = i >= s->mapping.next ? NULL :
a046433a
FB
2196 array_get(&(s->mapping), i);
2197
2198 if (next_mapping == NULL || next_mapping->begin > c1) {
2199 int i1 = array_index(&(s->mapping), mapping);
2200
2201 next_mapping = insert_mapping(s, c1, c1+1);
2202
2203 if (c1 < c)
2204 i1++;
2205 mapping = array_get(&(s->mapping), i1);
2206 }
2207
2208 next_mapping->dir_index = mapping->dir_index;
5fafdf24 2209 next_mapping->first_mapping_index =
a046433a
FB
2210 mapping->first_mapping_index < 0 ?
2211 array_index(&(s->mapping), mapping) :
2212 mapping->first_mapping_index;
2213 next_mapping->path = mapping->path;
2214 next_mapping->mode = mapping->mode;
2215 next_mapping->read_only = mapping->read_only;
2216 if (mapping->mode & MODE_DIRECTORY) {
2217 next_mapping->info.dir.parent_mapping_index =
2218 mapping->info.dir.parent_mapping_index;
2219 next_mapping->info.dir.first_dir_index =
2220 mapping->info.dir.first_dir_index +
2221 0x10 * s->sectors_per_cluster *
2222 (mapping->end - mapping->begin);
2223 } else
2224 next_mapping->info.file.offset = mapping->info.file.offset +
2225 mapping->end - mapping->begin;
2226
2227 mapping = next_mapping;
2228 }
3b46e624 2229
a046433a
FB
2230 cluster = c1;
2231 }
de167e41 2232
de167e41
FB
2233 return 0;
2234}
2235
a046433a
FB
2236static int commit_direntries(BDRVVVFATState* s,
2237 int dir_index, int parent_mapping_index)
de167e41 2238{
c227f099 2239 direntry_t* direntry = array_get(&(s->directory), dir_index);
a046433a 2240 uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
c227f099 2241 mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
a046433a
FB
2242
2243 int factor = 0x10 * s->sectors_per_cluster;
2244 int old_cluster_count, new_cluster_count;
2245 int current_dir_index = mapping->info.dir.first_dir_index;
2246 int first_dir_index = current_dir_index;
2247 int ret, i;
2248 uint32_t c;
2249
2250DLOG(fprintf(stderr, "commit_direntries for %s, parent_mapping_index %d\n", mapping->path, parent_mapping_index));
2251
2252 assert(direntry);
2253 assert(mapping);
2254 assert(mapping->begin == first_cluster);
2255 assert(mapping->info.dir.first_dir_index < s->directory.next);
2256 assert(mapping->mode & MODE_DIRECTORY);
2257 assert(dir_index == 0 || is_directory(direntry));
2258
2259 mapping->info.dir.parent_mapping_index = parent_mapping_index;
2260
2261 if (first_cluster == 0) {
2262 old_cluster_count = new_cluster_count =
2263 s->last_cluster_of_root_directory;
2264 } else {
2265 for (old_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2266 c = fat_get(s, c))
2267 old_cluster_count++;
de167e41 2268
a046433a
FB
2269 for (new_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2270 c = modified_fat_get(s, c))
2271 new_cluster_count++;
2272 }
de167e41 2273
a046433a
FB
2274 if (new_cluster_count > old_cluster_count) {
2275 if (insert_direntries(s,
2276 current_dir_index + factor * old_cluster_count,
2277 factor * (new_cluster_count - old_cluster_count)) == NULL)
2278 return -1;
2279 } else if (new_cluster_count < old_cluster_count)
2280 remove_direntries(s,
2281 current_dir_index + factor * new_cluster_count,
2282 factor * (old_cluster_count - new_cluster_count));
2283
2284 for (c = first_cluster; !fat_eof(s, c); c = modified_fat_get(s, c)) {
2285 void* direntry = array_get(&(s->directory), current_dir_index);
2286 int ret = vvfat_read(s->bs, cluster2sector(s, c), direntry,
2287 s->sectors_per_cluster);
2288 if (ret)
2289 return ret;
2290 assert(!strncmp(s->directory.pointer, "QEMU", 4));
2291 current_dir_index += factor;
2292 }
de167e41 2293
a046433a
FB
2294 ret = commit_mappings(s, first_cluster, dir_index);
2295 if (ret)
2296 return ret;
2297
2298 /* recurse */
2299 for (i = 0; i < factor * new_cluster_count; i++) {
2300 direntry = array_get(&(s->directory), first_dir_index + i);
2301 if (is_directory(direntry) && !is_dot(direntry)) {
2302 mapping = find_mapping_for_cluster(s, first_cluster);
2303 assert(mapping->mode & MODE_DIRECTORY);
2304 ret = commit_direntries(s, first_dir_index + i,
2305 array_index(&(s->mapping), mapping));
2306 if (ret)
2307 return ret;
2308 }
2309 }
de167e41 2310
a046433a
FB
2311 return 0;
2312}
de167e41 2313
a046433a
FB
2314/* commit one file (adjust contents, adjust mapping),
2315 return first_mapping_index */
2316static int commit_one_file(BDRVVVFATState* s,
2317 int dir_index, uint32_t offset)
2318{
c227f099 2319 direntry_t* direntry = array_get(&(s->directory), dir_index);
a046433a
FB
2320 uint32_t c = begin_of_direntry(direntry);
2321 uint32_t first_cluster = c;
c227f099 2322 mapping_t* mapping = find_mapping_for_cluster(s, c);
a046433a 2323 uint32_t size = filesize_of_direntry(direntry);
7267c094 2324 char* cluster = g_malloc(s->cluster_size);
a046433a
FB
2325 uint32_t i;
2326 int fd = 0;
2327
2328 assert(offset < size);
2329 assert((offset % s->cluster_size) == 0);
2330
2331 for (i = s->cluster_size; i < offset; i += s->cluster_size)
2332 c = modified_fat_get(s, c);
2333
6165f4d8 2334 fd = qemu_open(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666);
a046433a
FB
2335 if (fd < 0) {
2336 fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path,
2337 strerror(errno), errno);
ce137829 2338 g_free(cluster);
a046433a 2339 return fd;
de167e41 2340 }
ce137829
SW
2341 if (offset > 0) {
2342 if (lseek(fd, offset, SEEK_SET) != offset) {
2e1e79da 2343 qemu_close(fd);
ce137829
SW
2344 g_free(cluster);
2345 return -3;
2346 }
2347 }
a046433a
FB
2348
2349 while (offset < size) {
2350 uint32_t c1;
2351 int rest_size = (size - offset > s->cluster_size ?
2352 s->cluster_size : size - offset);
2353 int ret;
2354
2355 c1 = modified_fat_get(s, c);
2356
2357 assert((size - offset == 0 && fat_eof(s, c)) ||
2358 (size > offset && c >=2 && !fat_eof(s, c)));
a046433a
FB
2359
2360 ret = vvfat_read(s->bs, cluster2sector(s, c),
ffe8ab83 2361 (uint8_t*)cluster, (rest_size + 0x1ff) / 0x200);
a046433a 2362
ce137829 2363 if (ret < 0) {
2e1e79da 2364 qemu_close(fd);
ce137829
SW
2365 g_free(cluster);
2366 return ret;
2367 }
a046433a 2368
ce137829 2369 if (write(fd, cluster, rest_size) < 0) {
2e1e79da 2370 qemu_close(fd);
ce137829
SW
2371 g_free(cluster);
2372 return -2;
2373 }
a046433a
FB
2374
2375 offset += rest_size;
2376 c = c1;
2377 }
2378
2dedf83e
KS
2379 if (ftruncate(fd, size)) {
2380 perror("ftruncate()");
2e1e79da 2381 qemu_close(fd);
ce137829 2382 g_free(cluster);
2dedf83e
KS
2383 return -4;
2384 }
2e1e79da 2385 qemu_close(fd);
ce137829 2386 g_free(cluster);
a046433a
FB
2387
2388 return commit_mappings(s, first_cluster, dir_index);
2389}
2390
2391#ifdef DEBUG
2392/* test, if all mappings point to valid direntries */
2393static void check1(BDRVVVFATState* s)
2394{
2395 int i;
2396 for (i = 0; i < s->mapping.next; i++) {
c227f099 2397 mapping_t* mapping = array_get(&(s->mapping), i);
a046433a
FB
2398 if (mapping->mode & MODE_DELETED) {
2399 fprintf(stderr, "deleted\n");
2400 continue;
2401 }
a046433a 2402 assert(mapping->dir_index < s->directory.next);
c227f099 2403 direntry_t* direntry = array_get(&(s->directory), mapping->dir_index);
a046433a
FB
2404 assert(mapping->begin == begin_of_direntry(direntry) || mapping->first_mapping_index >= 0);
2405 if (mapping->mode & MODE_DIRECTORY) {
2406 assert(mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster * (mapping->end - mapping->begin) <= s->directory.next);
2407 assert((mapping->info.dir.first_dir_index % (0x10 * s->sectors_per_cluster)) == 0);
de167e41
FB
2408 }
2409 }
de167e41
FB
2410}
2411
a046433a
FB
2412/* test, if all direntries have mappings */
2413static void check2(BDRVVVFATState* s)
de167e41 2414{
de167e41 2415 int i;
a046433a 2416 int first_mapping = -1;
de167e41 2417
a046433a 2418 for (i = 0; i < s->directory.next; i++) {
c227f099 2419 direntry_t* direntry = array_get(&(s->directory), i);
de167e41 2420
a046433a 2421 if (is_short_name(direntry) && begin_of_direntry(direntry)) {
c227f099 2422 mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
a046433a
FB
2423 assert(mapping);
2424 assert(mapping->dir_index == i || is_dot(direntry));
2425 assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry));
2426 }
de167e41 2427
a046433a
FB
2428 if ((i % (0x10 * s->sectors_per_cluster)) == 0) {
2429 /* cluster start */
2430 int j, count = 0;
de167e41 2431
a046433a 2432 for (j = 0; j < s->mapping.next; j++) {
c227f099 2433 mapping_t* mapping = array_get(&(s->mapping), j);
a046433a 2434 if (mapping->mode & MODE_DELETED)
de167e41 2435 continue;
a046433a
FB
2436 if (mapping->mode & MODE_DIRECTORY) {
2437 if (mapping->info.dir.first_dir_index <= i && mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster > i) {
2438 assert(++count == 1);
2439 if (mapping->first_mapping_index == -1)
2440 first_mapping = array_index(&(s->mapping), mapping);
2441 else
2442 assert(first_mapping == mapping->first_mapping_index);
2443 if (mapping->info.dir.parent_mapping_index < 0)
2444 assert(j == 0);
2445 else {
c227f099 2446 mapping_t* parent = array_get(&(s->mapping), mapping->info.dir.parent_mapping_index);
a046433a
FB
2447 assert(parent->mode & MODE_DIRECTORY);
2448 assert(parent->info.dir.first_dir_index < mapping->info.dir.first_dir_index);
2449 }
2450 }
de167e41 2451 }
a046433a
FB
2452 }
2453 if (count == 0)
2454 first_mapping = -1;
2455 }
2456 }
2457}
2458#endif
de167e41 2459
a046433a
FB
2460static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2461{
2462 int i;
de167e41 2463
a046433a
FB
2464#ifdef DEBUG
2465 fprintf(stderr, "handle_renames\n");
2466 for (i = 0; i < s->commits.next; i++) {
c227f099 2467 commit_t* commit = array_get(&(s->commits), i);
a046433a
FB
2468 fprintf(stderr, "%d, %s (%d, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action);
2469 }
2470#endif
2471
2472 for (i = 0; i < s->commits.next;) {
c227f099 2473 commit_t* commit = array_get(&(s->commits), i);
a046433a 2474 if (commit->action == ACTION_RENAME) {
c227f099 2475 mapping_t* mapping = find_mapping_for_cluster(s,
a046433a
FB
2476 commit->param.rename.cluster);
2477 char* old_path = mapping->path;
2478
2479 assert(commit->path);
2480 mapping->path = commit->path;
2481 if (rename(old_path, mapping->path))
2482 return -2;
2483
2484 if (mapping->mode & MODE_DIRECTORY) {
2485 int l1 = strlen(mapping->path);
2486 int l2 = strlen(old_path);
2487 int diff = l1 - l2;
c227f099 2488 direntry_t* direntry = array_get(&(s->directory),
a046433a
FB
2489 mapping->info.dir.first_dir_index);
2490 uint32_t c = mapping->begin;
2491 int i = 0;
2492
2493 /* recurse */
2494 while (!fat_eof(s, c)) {
2495 do {
c227f099 2496 direntry_t* d = direntry + i;
a046433a
FB
2497
2498 if (is_file(d) || (is_directory(d) && !is_dot(d))) {
c227f099 2499 mapping_t* m = find_mapping_for_cluster(s,
a046433a
FB
2500 begin_of_direntry(d));
2501 int l = strlen(m->path);
7267c094 2502 char* new_path = g_malloc(l + diff + 1);
a046433a
FB
2503
2504 assert(!strncmp(m->path, mapping->path, l2));
2505
363a37d5
BS
2506 pstrcpy(new_path, l + diff + 1, mapping->path);
2507 pstrcpy(new_path + l1, l + diff + 1 - l1,
2508 m->path + l2);
a046433a
FB
2509
2510 schedule_rename(s, m->begin, new_path);
de167e41 2511 }
a046433a
FB
2512 i++;
2513 } while((i % (0x10 * s->sectors_per_cluster)) != 0);
2514 c = fat_get(s, c);
de167e41
FB
2515 }
2516 }
de167e41 2517
ce137829 2518 g_free(old_path);
a046433a
FB
2519 array_remove(&(s->commits), i);
2520 continue;
2521 } else if (commit->action == ACTION_MKDIR) {
c227f099 2522 mapping_t* mapping;
a046433a
FB
2523 int j, parent_path_len;
2524
48c2f068
FB
2525#ifdef __MINGW32__
2526 if (mkdir(commit->path))
2527 return -5;
2528#else
2529 if (mkdir(commit->path, 0755))
2530 return -5;
2531#endif
a046433a
FB
2532
2533 mapping = insert_mapping(s, commit->param.mkdir.cluster,
2534 commit->param.mkdir.cluster + 1);
2535 if (mapping == NULL)
2536 return -6;
2537
2538 mapping->mode = MODE_DIRECTORY;
2539 mapping->read_only = 0;
2540 mapping->path = commit->path;
2541 j = s->directory.next;
2542 assert(j);
2543 insert_direntries(s, s->directory.next,
2544 0x10 * s->sectors_per_cluster);
2545 mapping->info.dir.first_dir_index = j;
2546
2547 parent_path_len = strlen(commit->path)
2548 - strlen(get_basename(commit->path)) - 1;
2549 for (j = 0; j < s->mapping.next; j++) {
c227f099 2550 mapping_t* m = array_get(&(s->mapping), j);
a046433a
FB
2551 if (m->first_mapping_index < 0 && m != mapping &&
2552 !strncmp(m->path, mapping->path, parent_path_len) &&
2553 strlen(m->path) == parent_path_len)
2554 break;
2555 }
2556 assert(j < s->mapping.next);
2557 mapping->info.dir.parent_mapping_index = j;
2558
2559 array_remove(&(s->commits), i);
2560 continue;
2561 }
2562
2563 i++;
2564 }
2565 return 0;
2566}
2567
2568/*
2569 * TODO: make sure that the short name is not matching *another* file
2570 */
2571static int handle_commits(BDRVVVFATState* s)
2572{
2573 int i, fail = 0;
2574
2575 vvfat_close_current_file(s);
2576
2577 for (i = 0; !fail && i < s->commits.next; i++) {
c227f099 2578 commit_t* commit = array_get(&(s->commits), i);
a046433a
FB
2579 switch(commit->action) {
2580 case ACTION_RENAME: case ACTION_MKDIR:
43dc2a64 2581 abort();
a046433a
FB
2582 fail = -2;
2583 break;
2584 case ACTION_WRITEOUT: {
a6c6f76c
BS
2585#ifndef NDEBUG
2586 /* these variables are only used by assert() below */
c227f099 2587 direntry_t* entry = array_get(&(s->directory),
a046433a
FB
2588 commit->param.writeout.dir_index);
2589 uint32_t begin = begin_of_direntry(entry);
c227f099 2590 mapping_t* mapping = find_mapping_for_cluster(s, begin);
a6c6f76c 2591#endif
a046433a
FB
2592
2593 assert(mapping);
2594 assert(mapping->begin == begin);
2595 assert(commit->path == NULL);
2596
2597 if (commit_one_file(s, commit->param.writeout.dir_index,
2598 commit->param.writeout.modified_offset))
2599 fail = -3;
2600
2601 break;
2602 }
2603 case ACTION_NEW_FILE: {
2604 int begin = commit->param.new_file.first_cluster;
c227f099
AL
2605 mapping_t* mapping = find_mapping_for_cluster(s, begin);
2606 direntry_t* entry;
a046433a 2607 int i;
de167e41 2608
a046433a
FB
2609 /* find direntry */
2610 for (i = 0; i < s->directory.next; i++) {
2611 entry = array_get(&(s->directory), i);
2612 if (is_file(entry) && begin_of_direntry(entry) == begin)
2613 break;
de167e41 2614 }
de167e41 2615
a046433a
FB
2616 if (i >= s->directory.next) {
2617 fail = -6;
2618 continue;
2619 }
de167e41 2620
a046433a
FB
2621 /* make sure there exists an initial mapping */
2622 if (mapping && mapping->begin != begin) {
2623 mapping->end = begin;
2624 mapping = NULL;
2625 }
2626 if (mapping == NULL) {
2627 mapping = insert_mapping(s, begin, begin+1);
2628 }
2629 /* most members will be fixed in commit_mappings() */
2630 assert(commit->path);
2631 mapping->path = commit->path;
2632 mapping->read_only = 0;
2633 mapping->mode = MODE_NORMAL;
2634 mapping->info.file.offset = 0;
2635
2636 if (commit_one_file(s, i, 0))
2637 fail = -7;
2638
2639 break;
2640 }
2641 default:
43dc2a64 2642 abort();
a046433a
FB
2643 }
2644 }
2645 if (i > 0 && array_remove_slice(&(s->commits), 0, i))
2646 return -1;
2647 return fail;
2648}
2649
2650static int handle_deletes(BDRVVVFATState* s)
2651{
2652 int i, deferred = 1, deleted = 1;
2653
2654 /* delete files corresponding to mappings marked as deleted */
2655 /* handle DELETEs and unused mappings (modified_fat_get(s, mapping->begin) == 0) */
2656 while (deferred && deleted) {
2657 deferred = 0;
2658 deleted = 0;
2659
2660 for (i = 1; i < s->mapping.next; i++) {
c227f099 2661 mapping_t* mapping = array_get(&(s->mapping), i);
a046433a 2662 if (mapping->mode & MODE_DELETED) {
c227f099 2663 direntry_t* entry = array_get(&(s->directory),
a046433a
FB
2664 mapping->dir_index);
2665
2666 if (is_free(entry)) {
2667 /* remove file/directory */
2668 if (mapping->mode & MODE_DIRECTORY) {
2669 int j, next_dir_index = s->directory.next,
2670 first_dir_index = mapping->info.dir.first_dir_index;
2671
2672 if (rmdir(mapping->path) < 0) {
2673 if (errno == ENOTEMPTY) {
2674 deferred++;
2675 continue;
2676 } else
2677 return -5;
de167e41 2678 }
a046433a
FB
2679
2680 for (j = 1; j < s->mapping.next; j++) {
c227f099 2681 mapping_t* m = array_get(&(s->mapping), j);
a046433a
FB
2682 if (m->mode & MODE_DIRECTORY &&
2683 m->info.dir.first_dir_index >
2684 first_dir_index &&
2685 m->info.dir.first_dir_index <
2686 next_dir_index)
2687 next_dir_index =
2688 m->info.dir.first_dir_index;
de167e41 2689 }
a046433a
FB
2690 remove_direntries(s, first_dir_index,
2691 next_dir_index - first_dir_index);
de167e41 2692
a046433a 2693 deleted++;
de167e41 2694 }
a046433a
FB
2695 } else {
2696 if (unlink(mapping->path))
2697 return -4;
2698 deleted++;
de167e41 2699 }
a046433a
FB
2700 DLOG(fprintf(stderr, "DELETE (%d)\n", i); print_mapping(mapping); print_direntry(entry));
2701 remove_mapping(s, i);
de167e41
FB
2702 }
2703 }
2704 }
a046433a
FB
2705
2706 return 0;
2707}
2708
2709/*
2710 * synchronize mapping with new state:
2711 *
2712 * - copy FAT (with bdrv_read)
2713 * - mark all filenames corresponding to mappings as deleted
2714 * - recurse direntries from root (using bs->bdrv_read)
2715 * - delete files corresponding to mappings marked as deleted
2716 */
2717static int do_commit(BDRVVVFATState* s)
2718{
2719 int ret = 0;
2720
2721 /* the real meat are the commits. Nothing to do? Move along! */
2722 if (s->commits.next == 0)
2723 return 0;
2724
2725 vvfat_close_current_file(s);
2726
2727 ret = handle_renames_and_mkdirs(s);
2728 if (ret) {
2729 fprintf(stderr, "Error handling renames (%d)\n", ret);
43dc2a64 2730 abort();
a046433a
FB
2731 return ret;
2732 }
2733
5fafdf24 2734 /* copy FAT (with bdrv_read) */
a046433a
FB
2735 memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
2736
2737 /* recurse direntries from root (using bs->bdrv_read) */
2738 ret = commit_direntries(s, 0, -1);
2739 if (ret) {
2740 fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
43dc2a64 2741 abort();
a046433a
FB
2742 return ret;
2743 }
2744
2745 ret = handle_commits(s);
2746 if (ret) {
2747 fprintf(stderr, "Error handling commits (%d)\n", ret);
43dc2a64 2748 abort();
a046433a
FB
2749 return ret;
2750 }
2751
2752 ret = handle_deletes(s);
2753 if (ret) {
2754 fprintf(stderr, "Error deleting\n");
43dc2a64 2755 abort();
a046433a
FB
2756 return ret;
2757 }
2758
7704df98
KW
2759 if (s->qcow->drv->bdrv_make_empty) {
2760 s->qcow->drv->bdrv_make_empty(s->qcow);
2761 }
a046433a
FB
2762
2763 memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
2764
2765DLOG(checkpoint());
2766 return 0;
2767}
2768
2769static int try_commit(BDRVVVFATState* s)
2770{
2771 vvfat_close_current_file(s);
2772DLOG(checkpoint());
2773 if(!is_consistent(s))
2774 return -1;
2775 return do_commit(s);
2776}
2777
5fafdf24 2778static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
a046433a
FB
2779 const uint8_t *buf, int nb_sectors)
2780{
5fafdf24 2781 BDRVVVFATState *s = bs->opaque;
a046433a
FB
2782 int i, ret;
2783
2784DLOG(checkpoint());
2785
ac48e389
KW
2786 /* Check if we're operating in read-only mode */
2787 if (s->qcow == NULL) {
2788 return -EACCES;
2789 }
2790
a046433a
FB
2791 vvfat_close_current_file(s);
2792
2793 /*
2794 * Some sanity checks:
2795 * - do not allow writing to the boot sector
2796 * - do not allow to write non-ASCII filenames
2797 */
2798
2799 if (sector_num < s->first_sectors_number)
2800 return -1;
2801
2802 for (i = sector2cluster(s, sector_num);
2803 i <= sector2cluster(s, sector_num + nb_sectors - 1);) {
c227f099 2804 mapping_t* mapping = find_mapping_for_cluster(s, i);
a046433a
FB
2805 if (mapping) {
2806 if (mapping->read_only) {
2807 fprintf(stderr, "Tried to write to write-protected file %s\n",
2808 mapping->path);
2809 return -1;
2810 }
2811
2812 if (mapping->mode & MODE_DIRECTORY) {
2813 int begin = cluster2sector(s, i);
2814 int end = begin + s->sectors_per_cluster, k;
2815 int dir_index;
c227f099 2816 const direntry_t* direntries;
a046433a
FB
2817 long_file_name lfn;
2818
2819 lfn_init(&lfn);
2820
2821 if (begin < sector_num)
2822 begin = sector_num;
2823 if (end > sector_num + nb_sectors)
2824 end = sector_num + nb_sectors;
5fafdf24 2825 dir_index = mapping->dir_index +
a046433a 2826 0x10 * (begin - mapping->begin * s->sectors_per_cluster);
c227f099 2827 direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
a046433a
FB
2828
2829 for (k = 0; k < (end - begin) * 0x10; k++) {
2830 /* do not allow non-ASCII filenames */
2831 if (parse_long_name(&lfn, direntries + k) < 0) {
2832 fprintf(stderr, "Warning: non-ASCII filename\n");
2833 return -1;
2834 }
2835 /* no access to the direntry of a read-only file */
2836 else if (is_short_name(direntries+k) &&
2837 (direntries[k].attributes & 1)) {
2838 if (memcmp(direntries + k,
2839 array_get(&(s->directory), dir_index + k),
c227f099 2840 sizeof(direntry_t))) {
a046433a
FB
2841 fprintf(stderr, "Warning: tried to write to write-protected file\n");
2842 return -1;
2843 }
2844 }
2845 }
2846 }
2847 i = mapping->end;
2848 } else
2849 i++;
2850 }
2851
2852 /*
2853 * Use qcow backend. Commit later.
2854 */
2855DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
7704df98 2856 ret = bdrv_write(s->qcow, sector_num, buf, nb_sectors);
a046433a
FB
2857 if (ret < 0) {
2858 fprintf(stderr, "Error writing to qcow backend\n");
2859 return ret;
2860 }
2861
2862 for (i = sector2cluster(s, sector_num);
2863 i <= sector2cluster(s, sector_num + nb_sectors - 1); i++)
2864 if (i >= 0)
2865 s->used_clusters[i] |= USED_ALLOCATED;
2866
2867DLOG(checkpoint());
2868 /* TODO: add timeout */
2869 try_commit(s);
2870
2871DLOG(checkpoint());
2872 return 0;
2873}
2874
e183ef75
PB
2875static coroutine_fn int vvfat_co_write(BlockDriverState *bs, int64_t sector_num,
2876 const uint8_t *buf, int nb_sectors)
2877{
2878 int ret;
2879 BDRVVVFATState *s = bs->opaque;
2880 qemu_co_mutex_lock(&s->lock);
2881 ret = vvfat_write(bs, sector_num, buf, nb_sectors);
2882 qemu_co_mutex_unlock(&s->lock);
2883 return ret;
2884}
2885
b6b8a333 2886static int64_t coroutine_fn vvfat_co_get_block_status(BlockDriverState *bs,
a046433a
FB
2887 int64_t sector_num, int nb_sectors, int* n)
2888{
2889 BDRVVVFATState* s = bs->opaque;
2890 *n = s->sector_count - sector_num;
4bc74be9
PB
2891 if (*n > nb_sectors) {
2892 *n = nb_sectors;
2893 } else if (*n < 0) {
2894 return 0;
2895 }
2896 return BDRV_BLOCK_DATA;
a046433a
FB
2897}
2898
2899static int write_target_commit(BlockDriverState *bs, int64_t sector_num,
2900 const uint8_t* buffer, int nb_sectors) {
9217e26f 2901 BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
a046433a
FB
2902 return try_commit(s);
2903}
2904
2905static void write_target_close(BlockDriverState *bs) {
9217e26f 2906 BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
4f6fd349 2907 bdrv_unref(s->qcow);
ce137829 2908 g_free(s->qcow_filename);
a046433a
FB
2909}
2910
2911static BlockDriver vvfat_write_target = {
f9e96436
CH
2912 .format_name = "vvfat_write_target",
2913 .bdrv_write = write_target_commit,
2914 .bdrv_close = write_target_close,
a046433a
FB
2915};
2916
68c70af1 2917static int enable_write_target(BDRVVVFATState *s, Error **errp)
a046433a 2918{
facdbb02 2919 BlockDriver *bdrv_qcow = NULL;
5db15a57 2920 BlockDriverState *backing;
facdbb02 2921 QemuOpts *opts = NULL;
a655211a 2922 int ret;
a046433a 2923 int size = sector2cluster(s, s->sector_count);
e6641719
HR
2924 QDict *options;
2925
a046433a
FB
2926 s->used_clusters = calloc(size, 1);
2927
c227f099 2928 array_init(&(s->commits), sizeof(commit_t));
a046433a 2929
9a29e18f
JC
2930 s->qcow_filename = g_malloc(PATH_MAX);
2931 ret = get_tmp_filename(s->qcow_filename, PATH_MAX);
eba25057 2932 if (ret < 0) {
68c70af1 2933 error_setg_errno(errp, -ret, "can't create temporary file");
78f27bd0 2934 goto err;
eba25057 2935 }
91a073a9
KW
2936
2937 bdrv_qcow = bdrv_find_format("qcow");
1bcb15cf
HR
2938 if (!bdrv_qcow) {
2939 error_setg(errp, "Failed to locate qcow driver");
2940 ret = -ENOENT;
2941 goto err;
2942 }
2943
c282e1fd 2944 opts = qemu_opts_create(bdrv_qcow->create_opts, NULL, 0, &error_abort);
39101f25
MA
2945 qemu_opt_set_number(opts, BLOCK_OPT_SIZE, s->sector_count * 512,
2946 &error_abort);
f43e47db 2947 qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, "fat:", &error_abort);
91a073a9 2948
c282e1fd 2949 ret = bdrv_create(bdrv_qcow, s->qcow_filename, opts, errp);
facdbb02 2950 qemu_opts_del(opts);
78f27bd0
FZ
2951 if (ret < 0) {
2952 goto err;
2953 }
a655211a 2954
f67503e5 2955 s->qcow = NULL;
e6641719
HR
2956 options = qdict_new();
2957 qdict_put(options, "driver", qstring_from_str("qcow"));
2958 ret = bdrv_open(&s->qcow, s->qcow_filename, NULL, options,
68c70af1 2959 BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH,
6ebf9aa2 2960 errp);
a655211a 2961 if (ret < 0) {
78f27bd0 2962 goto err;
d6e9098e 2963 }
a046433a
FB
2964
2965#ifndef _WIN32
2966 unlink(s->qcow_filename);
2967#endif
2968
5db15a57
KW
2969 backing = bdrv_new();
2970 bdrv_set_backing_hd(s->bs, backing);
2971 bdrv_unref(backing);
2972
760e0063
KW
2973 s->bs->backing->bs->drv = &vvfat_write_target;
2974 s->bs->backing->bs->opaque = g_new(void *, 1);
2975 *(void**)s->bs->backing->bs->opaque = s;
a046433a 2976
de167e41 2977 return 0;
78f27bd0
FZ
2978
2979err:
2980 g_free(s->qcow_filename);
2981 s->qcow_filename = NULL;
2982 return ret;
de167e41
FB
2983}
2984
2985static void vvfat_close(BlockDriverState *bs)
2986{
2987 BDRVVVFATState *s = bs->opaque;
2988
2989 vvfat_close_current_file(s);
2990 array_free(&(s->fat));
2991 array_free(&(s->directory));
2992 array_free(&(s->mapping));
ce137829 2993 g_free(s->cluster_buffer);
3397f0cb
KW
2994
2995 if (s->qcow) {
2996 migrate_del_blocker(s->migration_blocker);
2997 error_free(s->migration_blocker);
2998 }
de167e41
FB
2999}
3000
5efa9d5a 3001static BlockDriver bdrv_vvfat = {
7ad9be64
KW
3002 .format_name = "vvfat",
3003 .protocol_name = "fat",
3004 .instance_size = sizeof(BDRVVVFATState),
3005
3006 .bdrv_parse_filename = vvfat_parse_filename,
3007 .bdrv_file_open = vvfat_open,
3008 .bdrv_close = vvfat_close,
7ad9be64
KW
3009
3010 .bdrv_read = vvfat_co_read,
3011 .bdrv_write = vvfat_co_write,
b6b8a333 3012 .bdrv_co_get_block_status = vvfat_co_get_block_status,
de167e41
FB
3013};
3014
5efa9d5a
AL
3015static void bdrv_vvfat_init(void)
3016{
3017 bdrv_register(&bdrv_vvfat);
3018}
3019
3020block_init(bdrv_vvfat_init);
3021
a046433a 3022#ifdef DEBUG
3f47aa8c 3023static void checkpoint(void) {
c227f099 3024 assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2);
a046433a
FB
3025 check1(vvv);
3026 check2(vvv);
3027 assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY));
3028#if 0
c227f099 3029 if (((direntry_t*)vvv->directory.pointer)[1].attributes != 0xf)
a046433a 3030 fprintf(stderr, "Nonono!\n");
c227f099
AL
3031 mapping_t* mapping;
3032 direntry_t* direntry;
a046433a
FB
3033 assert(vvv->mapping.size >= vvv->mapping.item_size * vvv->mapping.next);
3034 assert(vvv->directory.size >= vvv->directory.item_size * vvv->directory.next);
3035 if (vvv->mapping.next<47)
3036 return;
3037 assert((mapping = array_get(&(vvv->mapping), 47)));
3038 assert(mapping->dir_index < vvv->directory.next);
3039 direntry = array_get(&(vvv->directory), mapping->dir_index);
3040 assert(!memcmp(direntry->name, "USB H ", 11) || direntry->name[0]==0);
3041#endif
a046433a
FB
3042}
3043#endif