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