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