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