]> git.proxmox.com Git - mirror_qemu.git/blob - block/vvfat.c
Merge branch 'ppc-for-upstream' of git://repo.or.cz/qemu/agraf
[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, int flags)
992 {
993 BDRVVVFATState *s = bs->opaque;
994 int i, cyls, heads, secs;
995
996 #ifdef DEBUG
997 vvv = s;
998 #endif
999
1000 DLOG(if (stderr == NULL) {
1001 stderr = fopen("vvfat.log", "a");
1002 setbuf(stderr, NULL);
1003 })
1004
1005 s->bs = bs;
1006
1007 /* LATER TODO: if FAT32, adjust */
1008 s->sectors_per_cluster=0x10;
1009
1010 s->current_cluster=0xffffffff;
1011
1012 s->first_sectors_number=0x40;
1013 /* read only is the default for safety */
1014 bs->read_only = 1;
1015 s->qcow = s->write_target = NULL;
1016 s->qcow_filename = NULL;
1017 s->fat2 = NULL;
1018 s->downcase_short_names = 1;
1019
1020 if (!strstart(dirname, "fat:", NULL))
1021 return -1;
1022
1023 if (strstr(dirname, ":32:")) {
1024 fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. You are welcome to do so!\n");
1025 s->fat_type = 32;
1026 } else if (strstr(dirname, ":16:")) {
1027 s->fat_type = 16;
1028 } else if (strstr(dirname, ":12:")) {
1029 s->fat_type = 12;
1030 }
1031
1032 if (strstr(dirname, ":floppy:")) {
1033 /* 1.44MB or 2.88MB floppy. 2.88MB can be FAT12 (default) or FAT16. */
1034 if (!s->fat_type) {
1035 s->fat_type = 12;
1036 secs = 36;
1037 s->sectors_per_cluster=2;
1038 } else {
1039 secs = s->fat_type == 12 ? 18 : 36;
1040 s->sectors_per_cluster=1;
1041 }
1042 s->first_sectors_number = 1;
1043 cyls = 80;
1044 heads = 2;
1045 } else {
1046 /* 32MB or 504MB disk*/
1047 if (!s->fat_type) {
1048 s->fat_type = 16;
1049 }
1050 cyls = s->fat_type == 12 ? 64 : 1024;
1051 heads = 16;
1052 secs = 63;
1053 }
1054 fprintf(stderr, "vvfat %s chs %d,%d,%d\n",
1055 dirname, cyls, heads, secs);
1056
1057 s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1);
1058
1059 if (strstr(dirname, ":rw:")) {
1060 if (enable_write_target(s))
1061 return -1;
1062 bs->read_only = 0;
1063 }
1064
1065 i = strrchr(dirname, ':') - dirname;
1066 assert(i >= 3);
1067 if (dirname[i-2] == ':' && qemu_isalpha(dirname[i-1]))
1068 /* workaround for DOS drive names */
1069 dirname += i-1;
1070 else
1071 dirname += i+1;
1072
1073 bs->total_sectors = cyls * heads * secs;
1074
1075 if (init_directories(s, dirname, heads, secs)) {
1076 return -1;
1077 }
1078
1079 s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
1080
1081 if (s->first_sectors_number == 0x40) {
1082 init_mbr(s, cyls, heads, secs);
1083 }
1084
1085 // assert(is_consistent(s));
1086 qemu_co_mutex_init(&s->lock);
1087
1088 /* Disable migration when vvfat is used rw */
1089 if (s->qcow) {
1090 error_set(&s->migration_blocker,
1091 QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
1092 "vvfat (rw)", bs->device_name, "live migration");
1093 migrate_add_blocker(s->migration_blocker);
1094 }
1095
1096 return 0;
1097 }
1098
1099 static inline void vvfat_close_current_file(BDRVVVFATState *s)
1100 {
1101 if(s->current_mapping) {
1102 s->current_mapping = NULL;
1103 if (s->current_fd) {
1104 qemu_close(s->current_fd);
1105 s->current_fd = 0;
1106 }
1107 }
1108 s->current_cluster = -1;
1109 }
1110
1111 /* mappings between index1 and index2-1 are supposed to be ordered
1112 * return value is the index of the last mapping for which end>cluster_num
1113 */
1114 static inline int find_mapping_for_cluster_aux(BDRVVVFATState* s,int cluster_num,int index1,int index2)
1115 {
1116 while(1) {
1117 int index3;
1118 mapping_t* mapping;
1119 index3=(index1+index2)/2;
1120 mapping=array_get(&(s->mapping),index3);
1121 assert(mapping->begin < mapping->end);
1122 if(mapping->begin>=cluster_num) {
1123 assert(index2!=index3 || index2==0);
1124 if(index2==index3)
1125 return index1;
1126 index2=index3;
1127 } else {
1128 if(index1==index3)
1129 return mapping->end<=cluster_num ? index2 : index1;
1130 index1=index3;
1131 }
1132 assert(index1<=index2);
1133 DLOG(mapping=array_get(&(s->mapping),index1);
1134 assert(mapping->begin<=cluster_num);
1135 assert(index2 >= s->mapping.next ||
1136 ((mapping = array_get(&(s->mapping),index2)) &&
1137 mapping->end>cluster_num)));
1138 }
1139 }
1140
1141 static inline mapping_t* find_mapping_for_cluster(BDRVVVFATState* s,int cluster_num)
1142 {
1143 int index=find_mapping_for_cluster_aux(s,cluster_num,0,s->mapping.next);
1144 mapping_t* mapping;
1145 if(index>=s->mapping.next)
1146 return NULL;
1147 mapping=array_get(&(s->mapping),index);
1148 if(mapping->begin>cluster_num)
1149 return NULL;
1150 assert(mapping->begin<=cluster_num && mapping->end>cluster_num);
1151 return mapping;
1152 }
1153
1154 static int open_file(BDRVVVFATState* s,mapping_t* mapping)
1155 {
1156 if(!mapping)
1157 return -1;
1158 if(!s->current_mapping ||
1159 strcmp(s->current_mapping->path,mapping->path)) {
1160 /* open file */
1161 int fd = qemu_open(mapping->path, O_RDONLY | O_BINARY | O_LARGEFILE);
1162 if(fd<0)
1163 return -1;
1164 vvfat_close_current_file(s);
1165 s->current_fd = fd;
1166 s->current_mapping = mapping;
1167 }
1168 return 0;
1169 }
1170
1171 static inline int read_cluster(BDRVVVFATState *s,int cluster_num)
1172 {
1173 if(s->current_cluster != cluster_num) {
1174 int result=0;
1175 off_t offset;
1176 assert(!s->current_mapping || s->current_fd || (s->current_mapping->mode & MODE_DIRECTORY));
1177 if(!s->current_mapping
1178 || s->current_mapping->begin>cluster_num
1179 || s->current_mapping->end<=cluster_num) {
1180 /* binary search of mappings for file */
1181 mapping_t* mapping=find_mapping_for_cluster(s,cluster_num);
1182
1183 assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
1184
1185 if (mapping && mapping->mode & MODE_DIRECTORY) {
1186 vvfat_close_current_file(s);
1187 s->current_mapping = mapping;
1188 read_cluster_directory:
1189 offset = s->cluster_size*(cluster_num-s->current_mapping->begin);
1190 s->cluster = (unsigned char*)s->directory.pointer+offset
1191 + 0x20*s->current_mapping->info.dir.first_dir_index;
1192 assert(((s->cluster-(unsigned char*)s->directory.pointer)%s->cluster_size)==0);
1193 assert((char*)s->cluster+s->cluster_size <= s->directory.pointer+s->directory.next*s->directory.item_size);
1194 s->current_cluster = cluster_num;
1195 return 0;
1196 }
1197
1198 if(open_file(s,mapping))
1199 return -2;
1200 } else if (s->current_mapping->mode & MODE_DIRECTORY)
1201 goto read_cluster_directory;
1202
1203 assert(s->current_fd);
1204
1205 offset=s->cluster_size*(cluster_num-s->current_mapping->begin)+s->current_mapping->info.file.offset;
1206 if(lseek(s->current_fd, offset, SEEK_SET)!=offset)
1207 return -3;
1208 s->cluster=s->cluster_buffer;
1209 result=read(s->current_fd,s->cluster,s->cluster_size);
1210 if(result<0) {
1211 s->current_cluster = -1;
1212 return -1;
1213 }
1214 s->current_cluster = cluster_num;
1215 }
1216 return 0;
1217 }
1218
1219 #ifdef DEBUG
1220 static void print_direntry(const direntry_t* direntry)
1221 {
1222 int j = 0;
1223 char buffer[1024];
1224
1225 fprintf(stderr, "direntry %p: ", direntry);
1226 if(!direntry)
1227 return;
1228 if(is_long_name(direntry)) {
1229 unsigned char* c=(unsigned char*)direntry;
1230 int i;
1231 for(i=1;i<11 && c[i] && c[i]!=0xff;i+=2)
1232 #define ADD_CHAR(c) {buffer[j] = (c); if (buffer[j] < ' ') buffer[j] = 0xb0; j++;}
1233 ADD_CHAR(c[i]);
1234 for(i=14;i<26 && c[i] && c[i]!=0xff;i+=2)
1235 ADD_CHAR(c[i]);
1236 for(i=28;i<32 && c[i] && c[i]!=0xff;i+=2)
1237 ADD_CHAR(c[i]);
1238 buffer[j] = 0;
1239 fprintf(stderr, "%s\n", buffer);
1240 } else {
1241 int i;
1242 for(i=0;i<11;i++)
1243 ADD_CHAR(direntry->name[i]);
1244 buffer[j] = 0;
1245 fprintf(stderr,"%s attributes=0x%02x begin=%d size=%d\n",
1246 buffer,
1247 direntry->attributes,
1248 begin_of_direntry(direntry),le32_to_cpu(direntry->size));
1249 }
1250 }
1251
1252 static void print_mapping(const mapping_t* mapping)
1253 {
1254 fprintf(stderr, "mapping (%p): begin, end = %d, %d, dir_index = %d, "
1255 "first_mapping_index = %d, name = %s, mode = 0x%x, " ,
1256 mapping, mapping->begin, mapping->end, mapping->dir_index,
1257 mapping->first_mapping_index, mapping->path, mapping->mode);
1258
1259 if (mapping->mode & MODE_DIRECTORY)
1260 fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
1261 else
1262 fprintf(stderr, "offset = %d\n", mapping->info.file.offset);
1263 }
1264 #endif
1265
1266 static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
1267 uint8_t *buf, int nb_sectors)
1268 {
1269 BDRVVVFATState *s = bs->opaque;
1270 int i;
1271
1272 for(i=0;i<nb_sectors;i++,sector_num++) {
1273 if (sector_num >= bs->total_sectors)
1274 return -1;
1275 if (s->qcow) {
1276 int n;
1277 if (bdrv_is_allocated(s->qcow, sector_num, nb_sectors-i, &n)) {
1278 DLOG(fprintf(stderr, "sectors %d+%d allocated\n", (int)sector_num, n));
1279 if (bdrv_read(s->qcow, sector_num, buf + i*0x200, n)) {
1280 return -1;
1281 }
1282 i += n - 1;
1283 sector_num += n - 1;
1284 continue;
1285 }
1286 DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num));
1287 }
1288 if(sector_num<s->faked_sectors) {
1289 if(sector_num<s->first_sectors_number)
1290 memcpy(buf+i*0x200,&(s->first_sectors[sector_num*0x200]),0x200);
1291 else if(sector_num-s->first_sectors_number<s->sectors_per_fat)
1292 memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number)*0x200]),0x200);
1293 else if(sector_num-s->first_sectors_number-s->sectors_per_fat<s->sectors_per_fat)
1294 memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number-s->sectors_per_fat)*0x200]),0x200);
1295 } else {
1296 uint32_t sector=sector_num-s->faked_sectors,
1297 sector_offset_in_cluster=(sector%s->sectors_per_cluster),
1298 cluster_num=sector/s->sectors_per_cluster;
1299 if(cluster_num > s->cluster_count || read_cluster(s, cluster_num) != 0) {
1300 /* LATER TODO: strict: return -1; */
1301 memset(buf+i*0x200,0,0x200);
1302 continue;
1303 }
1304 memcpy(buf+i*0x200,s->cluster+sector_offset_in_cluster*0x200,0x200);
1305 }
1306 }
1307 return 0;
1308 }
1309
1310 static coroutine_fn int vvfat_co_read(BlockDriverState *bs, int64_t sector_num,
1311 uint8_t *buf, int nb_sectors)
1312 {
1313 int ret;
1314 BDRVVVFATState *s = bs->opaque;
1315 qemu_co_mutex_lock(&s->lock);
1316 ret = vvfat_read(bs, sector_num, buf, nb_sectors);
1317 qemu_co_mutex_unlock(&s->lock);
1318 return ret;
1319 }
1320
1321 /* LATER TODO: statify all functions */
1322
1323 /*
1324 * Idea of the write support (use snapshot):
1325 *
1326 * 1. check if all data is consistent, recording renames, modifications,
1327 * new files and directories (in s->commits).
1328 *
1329 * 2. if the data is not consistent, stop committing
1330 *
1331 * 3. handle renames, and create new files and directories (do not yet
1332 * write their contents)
1333 *
1334 * 4. walk the directories, fixing the mapping and direntries, and marking
1335 * the handled mappings as not deleted
1336 *
1337 * 5. commit the contents of the files
1338 *
1339 * 6. handle deleted files and directories
1340 *
1341 */
1342
1343 typedef struct commit_t {
1344 char* path;
1345 union {
1346 struct { uint32_t cluster; } rename;
1347 struct { int dir_index; uint32_t modified_offset; } writeout;
1348 struct { uint32_t first_cluster; } new_file;
1349 struct { uint32_t cluster; } mkdir;
1350 } param;
1351 /* DELETEs and RMDIRs are handled differently: see handle_deletes() */
1352 enum {
1353 ACTION_RENAME, ACTION_WRITEOUT, ACTION_NEW_FILE, ACTION_MKDIR
1354 } action;
1355 } commit_t;
1356
1357 static void clear_commits(BDRVVVFATState* s)
1358 {
1359 int i;
1360 DLOG(fprintf(stderr, "clear_commits (%d commits)\n", s->commits.next));
1361 for (i = 0; i < s->commits.next; i++) {
1362 commit_t* commit = array_get(&(s->commits), i);
1363 assert(commit->path || commit->action == ACTION_WRITEOUT);
1364 if (commit->action != ACTION_WRITEOUT) {
1365 assert(commit->path);
1366 g_free(commit->path);
1367 } else
1368 assert(commit->path == NULL);
1369 }
1370 s->commits.next = 0;
1371 }
1372
1373 static void schedule_rename(BDRVVVFATState* s,
1374 uint32_t cluster, char* new_path)
1375 {
1376 commit_t* commit = array_get_next(&(s->commits));
1377 commit->path = new_path;
1378 commit->param.rename.cluster = cluster;
1379 commit->action = ACTION_RENAME;
1380 }
1381
1382 static void schedule_writeout(BDRVVVFATState* s,
1383 int dir_index, uint32_t modified_offset)
1384 {
1385 commit_t* commit = array_get_next(&(s->commits));
1386 commit->path = NULL;
1387 commit->param.writeout.dir_index = dir_index;
1388 commit->param.writeout.modified_offset = modified_offset;
1389 commit->action = ACTION_WRITEOUT;
1390 }
1391
1392 static void schedule_new_file(BDRVVVFATState* s,
1393 char* path, uint32_t first_cluster)
1394 {
1395 commit_t* commit = array_get_next(&(s->commits));
1396 commit->path = path;
1397 commit->param.new_file.first_cluster = first_cluster;
1398 commit->action = ACTION_NEW_FILE;
1399 }
1400
1401 static void schedule_mkdir(BDRVVVFATState* s, uint32_t cluster, char* path)
1402 {
1403 commit_t* commit = array_get_next(&(s->commits));
1404 commit->path = path;
1405 commit->param.mkdir.cluster = cluster;
1406 commit->action = ACTION_MKDIR;
1407 }
1408
1409 typedef struct {
1410 /*
1411 * Since the sequence number is at most 0x3f, and the filename
1412 * length is at most 13 times the sequence number, the maximal
1413 * filename length is 0x3f * 13 bytes.
1414 */
1415 unsigned char name[0x3f * 13 + 1];
1416 int checksum, len;
1417 int sequence_number;
1418 } long_file_name;
1419
1420 static void lfn_init(long_file_name* lfn)
1421 {
1422 lfn->sequence_number = lfn->len = 0;
1423 lfn->checksum = 0x100;
1424 }
1425
1426 /* return 0 if parsed successfully, > 0 if no long name, < 0 if error */
1427 static int parse_long_name(long_file_name* lfn,
1428 const direntry_t* direntry)
1429 {
1430 int i, j, offset;
1431 const unsigned char* pointer = (const unsigned char*)direntry;
1432
1433 if (!is_long_name(direntry))
1434 return 1;
1435
1436 if (pointer[0] & 0x40) {
1437 lfn->sequence_number = pointer[0] & 0x3f;
1438 lfn->checksum = pointer[13];
1439 lfn->name[0] = 0;
1440 lfn->name[lfn->sequence_number * 13] = 0;
1441 } else if ((pointer[0] & 0x3f) != --lfn->sequence_number)
1442 return -1;
1443 else if (pointer[13] != lfn->checksum)
1444 return -2;
1445 else if (pointer[12] || pointer[26] || pointer[27])
1446 return -3;
1447
1448 offset = 13 * (lfn->sequence_number - 1);
1449 for (i = 0, j = 1; i < 13; i++, j+=2) {
1450 if (j == 11)
1451 j = 14;
1452 else if (j == 26)
1453 j = 28;
1454
1455 if (pointer[j+1] == 0)
1456 lfn->name[offset + i] = pointer[j];
1457 else if (pointer[j+1] != 0xff || (pointer[0] & 0x40) == 0)
1458 return -4;
1459 else
1460 lfn->name[offset + i] = 0;
1461 }
1462
1463 if (pointer[0] & 0x40)
1464 lfn->len = offset + strlen((char*)lfn->name + offset);
1465
1466 return 0;
1467 }
1468
1469 /* returns 0 if successful, >0 if no short_name, and <0 on error */
1470 static int parse_short_name(BDRVVVFATState* s,
1471 long_file_name* lfn, direntry_t* direntry)
1472 {
1473 int i, j;
1474
1475 if (!is_short_name(direntry))
1476 return 1;
1477
1478 for (j = 7; j >= 0 && direntry->name[j] == ' '; j--);
1479 for (i = 0; i <= j; i++) {
1480 if (direntry->name[i] <= ' ' || direntry->name[i] > 0x7f)
1481 return -1;
1482 else if (s->downcase_short_names)
1483 lfn->name[i] = qemu_tolower(direntry->name[i]);
1484 else
1485 lfn->name[i] = direntry->name[i];
1486 }
1487
1488 for (j = 2; j >= 0 && direntry->extension[j] == ' '; j--);
1489 if (j >= 0) {
1490 lfn->name[i++] = '.';
1491 lfn->name[i + j + 1] = '\0';
1492 for (;j >= 0; j--) {
1493 if (direntry->extension[j] <= ' ' || direntry->extension[j] > 0x7f)
1494 return -2;
1495 else if (s->downcase_short_names)
1496 lfn->name[i + j] = qemu_tolower(direntry->extension[j]);
1497 else
1498 lfn->name[i + j] = direntry->extension[j];
1499 }
1500 } else
1501 lfn->name[i + j + 1] = '\0';
1502
1503 lfn->len = strlen((char*)lfn->name);
1504
1505 return 0;
1506 }
1507
1508 static inline uint32_t modified_fat_get(BDRVVVFATState* s,
1509 unsigned int cluster)
1510 {
1511 if (cluster < s->last_cluster_of_root_directory) {
1512 if (cluster + 1 == s->last_cluster_of_root_directory)
1513 return s->max_fat_value;
1514 else
1515 return cluster + 1;
1516 }
1517
1518 if (s->fat_type==32) {
1519 uint32_t* entry=((uint32_t*)s->fat2)+cluster;
1520 return le32_to_cpu(*entry);
1521 } else if (s->fat_type==16) {
1522 uint16_t* entry=((uint16_t*)s->fat2)+cluster;
1523 return le16_to_cpu(*entry);
1524 } else {
1525 const uint8_t* x=s->fat2+cluster*3/2;
1526 return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
1527 }
1528 }
1529
1530 static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num)
1531 {
1532 int was_modified = 0;
1533 int i, dummy;
1534
1535 if (s->qcow == NULL)
1536 return 0;
1537
1538 for (i = 0; !was_modified && i < s->sectors_per_cluster; i++)
1539 was_modified = bdrv_is_allocated(s->qcow,
1540 cluster2sector(s, cluster_num) + i, 1, &dummy);
1541
1542 return was_modified;
1543 }
1544
1545 static const char* get_basename(const char* path)
1546 {
1547 char* basename = strrchr(path, '/');
1548 if (basename == NULL)
1549 return path;
1550 else
1551 return basename + 1; /* strip '/' */
1552 }
1553
1554 /*
1555 * The array s->used_clusters holds the states of the clusters. If it is
1556 * part of a file, it has bit 2 set, in case of a directory, bit 1. If it
1557 * was modified, bit 3 is set.
1558 * If any cluster is allocated, but not part of a file or directory, this
1559 * driver refuses to commit.
1560 */
1561 typedef enum {
1562 USED_DIRECTORY = 1, USED_FILE = 2, USED_ANY = 3, USED_ALLOCATED = 4
1563 } used_t;
1564
1565 /*
1566 * get_cluster_count_for_direntry() not only determines how many clusters
1567 * are occupied by direntry, but also if it was renamed or modified.
1568 *
1569 * A file is thought to be renamed *only* if there already was a file with
1570 * exactly the same first cluster, but a different name.
1571 *
1572 * Further, the files/directories handled by this function are
1573 * assumed to be *not* deleted (and *only* those).
1574 */
1575 static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
1576 direntry_t* direntry, const char* path)
1577 {
1578 /*
1579 * This is a little bit tricky:
1580 * IF the guest OS just inserts a cluster into the file chain,
1581 * and leaves the rest alone, (i.e. the original file had clusters
1582 * 15 -> 16, but now has 15 -> 32 -> 16), then the following happens:
1583 *
1584 * - do_commit will write the cluster into the file at the given
1585 * offset, but
1586 *
1587 * - the cluster which is overwritten should be moved to a later
1588 * position in the file.
1589 *
1590 * I am not aware that any OS does something as braindead, but this
1591 * situation could happen anyway when not committing for a long time.
1592 * Just to be sure that this does not bite us, detect it, and copy the
1593 * contents of the clusters to-be-overwritten into the qcow.
1594 */
1595 int copy_it = 0;
1596 int was_modified = 0;
1597 int32_t ret = 0;
1598
1599 uint32_t cluster_num = begin_of_direntry(direntry);
1600 uint32_t offset = 0;
1601 int first_mapping_index = -1;
1602 mapping_t* mapping = NULL;
1603 const char* basename2 = NULL;
1604
1605 vvfat_close_current_file(s);
1606
1607 /* the root directory */
1608 if (cluster_num == 0)
1609 return 0;
1610
1611 /* write support */
1612 if (s->qcow) {
1613 basename2 = get_basename(path);
1614
1615 mapping = find_mapping_for_cluster(s, cluster_num);
1616
1617 if (mapping) {
1618 const char* basename;
1619
1620 assert(mapping->mode & MODE_DELETED);
1621 mapping->mode &= ~MODE_DELETED;
1622
1623 basename = get_basename(mapping->path);
1624
1625 assert(mapping->mode & MODE_NORMAL);
1626
1627 /* rename */
1628 if (strcmp(basename, basename2))
1629 schedule_rename(s, cluster_num, g_strdup(path));
1630 } else if (is_file(direntry))
1631 /* new file */
1632 schedule_new_file(s, g_strdup(path), cluster_num);
1633 else {
1634 abort();
1635 return 0;
1636 }
1637 }
1638
1639 while(1) {
1640 if (s->qcow) {
1641 if (!copy_it && cluster_was_modified(s, cluster_num)) {
1642 if (mapping == NULL ||
1643 mapping->begin > cluster_num ||
1644 mapping->end <= cluster_num)
1645 mapping = find_mapping_for_cluster(s, cluster_num);
1646
1647
1648 if (mapping &&
1649 (mapping->mode & MODE_DIRECTORY) == 0) {
1650
1651 /* was modified in qcow */
1652 if (offset != mapping->info.file.offset + s->cluster_size
1653 * (cluster_num - mapping->begin)) {
1654 /* offset of this cluster in file chain has changed */
1655 abort();
1656 copy_it = 1;
1657 } else if (offset == 0) {
1658 const char* basename = get_basename(mapping->path);
1659
1660 if (strcmp(basename, basename2))
1661 copy_it = 1;
1662 first_mapping_index = array_index(&(s->mapping), mapping);
1663 }
1664
1665 if (mapping->first_mapping_index != first_mapping_index
1666 && mapping->info.file.offset > 0) {
1667 abort();
1668 copy_it = 1;
1669 }
1670
1671 /* need to write out? */
1672 if (!was_modified && is_file(direntry)) {
1673 was_modified = 1;
1674 schedule_writeout(s, mapping->dir_index, offset);
1675 }
1676 }
1677 }
1678
1679 if (copy_it) {
1680 int i, dummy;
1681 /*
1682 * This is horribly inefficient, but that is okay, since
1683 * it is rarely executed, if at all.
1684 */
1685 int64_t offset = cluster2sector(s, cluster_num);
1686
1687 vvfat_close_current_file(s);
1688 for (i = 0; i < s->sectors_per_cluster; i++) {
1689 if (!bdrv_is_allocated(s->qcow, offset + i, 1, &dummy)) {
1690 if (vvfat_read(s->bs, offset, s->cluster_buffer, 1)) {
1691 return -1;
1692 }
1693 if (bdrv_write(s->qcow, offset, s->cluster_buffer, 1)) {
1694 return -2;
1695 }
1696 }
1697 }
1698 }
1699 }
1700
1701 ret++;
1702 if (s->used_clusters[cluster_num] & USED_ANY)
1703 return 0;
1704 s->used_clusters[cluster_num] = USED_FILE;
1705
1706 cluster_num = modified_fat_get(s, cluster_num);
1707
1708 if (fat_eof(s, cluster_num))
1709 return ret;
1710 else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
1711 return -1;
1712
1713 offset += s->cluster_size;
1714 }
1715 }
1716
1717 /*
1718 * This function looks at the modified data (qcow).
1719 * It returns 0 upon inconsistency or error, and the number of clusters
1720 * used by the directory, its subdirectories and their files.
1721 */
1722 static int check_directory_consistency(BDRVVVFATState *s,
1723 int cluster_num, const char* path)
1724 {
1725 int ret = 0;
1726 unsigned char* cluster = g_malloc(s->cluster_size);
1727 direntry_t* direntries = (direntry_t*)cluster;
1728 mapping_t* mapping = find_mapping_for_cluster(s, cluster_num);
1729
1730 long_file_name lfn;
1731 int path_len = strlen(path);
1732 char path2[PATH_MAX + 1];
1733
1734 assert(path_len < PATH_MAX); /* len was tested before! */
1735 pstrcpy(path2, sizeof(path2), path);
1736 path2[path_len] = '/';
1737 path2[path_len + 1] = '\0';
1738
1739 if (mapping) {
1740 const char* basename = get_basename(mapping->path);
1741 const char* basename2 = get_basename(path);
1742
1743 assert(mapping->mode & MODE_DIRECTORY);
1744
1745 assert(mapping->mode & MODE_DELETED);
1746 mapping->mode &= ~MODE_DELETED;
1747
1748 if (strcmp(basename, basename2))
1749 schedule_rename(s, cluster_num, g_strdup(path));
1750 } else
1751 /* new directory */
1752 schedule_mkdir(s, cluster_num, g_strdup(path));
1753
1754 lfn_init(&lfn);
1755 do {
1756 int i;
1757 int subret = 0;
1758
1759 ret++;
1760
1761 if (s->used_clusters[cluster_num] & USED_ANY) {
1762 fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
1763 return 0;
1764 }
1765 s->used_clusters[cluster_num] = USED_DIRECTORY;
1766
1767 DLOG(fprintf(stderr, "read cluster %d (sector %d)\n", (int)cluster_num, (int)cluster2sector(s, cluster_num)));
1768 subret = vvfat_read(s->bs, cluster2sector(s, cluster_num), cluster,
1769 s->sectors_per_cluster);
1770 if (subret) {
1771 fprintf(stderr, "Error fetching direntries\n");
1772 fail:
1773 g_free(cluster);
1774 return 0;
1775 }
1776
1777 for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
1778 int cluster_count = 0;
1779
1780 DLOG(fprintf(stderr, "check direntry %d:\n", i); print_direntry(direntries + i));
1781 if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
1782 is_free(direntries + i))
1783 continue;
1784
1785 subret = parse_long_name(&lfn, direntries + i);
1786 if (subret < 0) {
1787 fprintf(stderr, "Error in long name\n");
1788 goto fail;
1789 }
1790 if (subret == 0 || is_free(direntries + i))
1791 continue;
1792
1793 if (fat_chksum(direntries+i) != lfn.checksum) {
1794 subret = parse_short_name(s, &lfn, direntries + i);
1795 if (subret < 0) {
1796 fprintf(stderr, "Error in short name (%d)\n", subret);
1797 goto fail;
1798 }
1799 if (subret > 0 || !strcmp((char*)lfn.name, ".")
1800 || !strcmp((char*)lfn.name, ".."))
1801 continue;
1802 }
1803 lfn.checksum = 0x100; /* cannot use long name twice */
1804
1805 if (path_len + 1 + lfn.len >= PATH_MAX) {
1806 fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
1807 goto fail;
1808 }
1809 pstrcpy(path2 + path_len + 1, sizeof(path2) - path_len - 1,
1810 (char*)lfn.name);
1811
1812 if (is_directory(direntries + i)) {
1813 if (begin_of_direntry(direntries + i) == 0) {
1814 DLOG(fprintf(stderr, "invalid begin for directory: %s\n", path2); print_direntry(direntries + i));
1815 goto fail;
1816 }
1817 cluster_count = check_directory_consistency(s,
1818 begin_of_direntry(direntries + i), path2);
1819 if (cluster_count == 0) {
1820 DLOG(fprintf(stderr, "problem in directory %s:\n", path2); print_direntry(direntries + i));
1821 goto fail;
1822 }
1823 } else if (is_file(direntries + i)) {
1824 /* check file size with FAT */
1825 cluster_count = get_cluster_count_for_direntry(s, direntries + i, path2);
1826 if (cluster_count !=
1827 (le32_to_cpu(direntries[i].size) + s->cluster_size
1828 - 1) / s->cluster_size) {
1829 DLOG(fprintf(stderr, "Cluster count mismatch\n"));
1830 goto fail;
1831 }
1832 } else
1833 abort(); /* cluster_count = 0; */
1834
1835 ret += cluster_count;
1836 }
1837
1838 cluster_num = modified_fat_get(s, cluster_num);
1839 } while(!fat_eof(s, cluster_num));
1840
1841 g_free(cluster);
1842 return ret;
1843 }
1844
1845 /* returns 1 on success */
1846 static int is_consistent(BDRVVVFATState* s)
1847 {
1848 int i, check;
1849 int used_clusters_count = 0;
1850
1851 DLOG(checkpoint());
1852 /*
1853 * - get modified FAT
1854 * - compare the two FATs (TODO)
1855 * - get buffer for marking used clusters
1856 * - recurse direntries from root (using bs->bdrv_read to make
1857 * sure to get the new data)
1858 * - check that the FAT agrees with the size
1859 * - count the number of clusters occupied by this directory and
1860 * its files
1861 * - check that the cumulative used cluster count agrees with the
1862 * FAT
1863 * - if all is fine, return number of used clusters
1864 */
1865 if (s->fat2 == NULL) {
1866 int size = 0x200 * s->sectors_per_fat;
1867 s->fat2 = g_malloc(size);
1868 memcpy(s->fat2, s->fat.pointer, size);
1869 }
1870 check = vvfat_read(s->bs,
1871 s->first_sectors_number, s->fat2, s->sectors_per_fat);
1872 if (check) {
1873 fprintf(stderr, "Could not copy fat\n");
1874 return 0;
1875 }
1876 assert (s->used_clusters);
1877 for (i = 0; i < sector2cluster(s, s->sector_count); i++)
1878 s->used_clusters[i] &= ~USED_ANY;
1879
1880 clear_commits(s);
1881
1882 /* mark every mapped file/directory as deleted.
1883 * (check_directory_consistency() will unmark those still present). */
1884 if (s->qcow)
1885 for (i = 0; i < s->mapping.next; i++) {
1886 mapping_t* mapping = array_get(&(s->mapping), i);
1887 if (mapping->first_mapping_index < 0)
1888 mapping->mode |= MODE_DELETED;
1889 }
1890
1891 used_clusters_count = check_directory_consistency(s, 0, s->path);
1892 if (used_clusters_count <= 0) {
1893 DLOG(fprintf(stderr, "problem in directory\n"));
1894 return 0;
1895 }
1896
1897 check = s->last_cluster_of_root_directory;
1898 for (i = check; i < sector2cluster(s, s->sector_count); i++) {
1899 if (modified_fat_get(s, i)) {
1900 if(!s->used_clusters[i]) {
1901 DLOG(fprintf(stderr, "FAT was modified (%d), but cluster is not used?\n", i));
1902 return 0;
1903 }
1904 check++;
1905 }
1906
1907 if (s->used_clusters[i] == USED_ALLOCATED) {
1908 /* allocated, but not used... */
1909 DLOG(fprintf(stderr, "unused, modified cluster: %d\n", i));
1910 return 0;
1911 }
1912 }
1913
1914 if (check != used_clusters_count)
1915 return 0;
1916
1917 return used_clusters_count;
1918 }
1919
1920 static inline void adjust_mapping_indices(BDRVVVFATState* s,
1921 int offset, int adjust)
1922 {
1923 int i;
1924
1925 for (i = 0; i < s->mapping.next; i++) {
1926 mapping_t* mapping = array_get(&(s->mapping), i);
1927
1928 #define ADJUST_MAPPING_INDEX(name) \
1929 if (mapping->name >= offset) \
1930 mapping->name += adjust
1931
1932 ADJUST_MAPPING_INDEX(first_mapping_index);
1933 if (mapping->mode & MODE_DIRECTORY)
1934 ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
1935 }
1936 }
1937
1938 /* insert or update mapping */
1939 static mapping_t* insert_mapping(BDRVVVFATState* s,
1940 uint32_t begin, uint32_t end)
1941 {
1942 /*
1943 * - find mapping where mapping->begin >= begin,
1944 * - if mapping->begin > begin: insert
1945 * - adjust all references to mappings!
1946 * - else: adjust
1947 * - replace name
1948 */
1949 int index = find_mapping_for_cluster_aux(s, begin, 0, s->mapping.next);
1950 mapping_t* mapping = NULL;
1951 mapping_t* first_mapping = array_get(&(s->mapping), 0);
1952
1953 if (index < s->mapping.next && (mapping = array_get(&(s->mapping), index))
1954 && mapping->begin < begin) {
1955 mapping->end = begin;
1956 index++;
1957 mapping = array_get(&(s->mapping), index);
1958 }
1959 if (index >= s->mapping.next || mapping->begin > begin) {
1960 mapping = array_insert(&(s->mapping), index, 1);
1961 mapping->path = NULL;
1962 adjust_mapping_indices(s, index, +1);
1963 }
1964
1965 mapping->begin = begin;
1966 mapping->end = end;
1967
1968 DLOG(mapping_t* next_mapping;
1969 assert(index + 1 >= s->mapping.next ||
1970 ((next_mapping = array_get(&(s->mapping), index + 1)) &&
1971 next_mapping->begin >= end)));
1972
1973 if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1974 s->current_mapping = array_get(&(s->mapping),
1975 s->current_mapping - first_mapping);
1976
1977 return mapping;
1978 }
1979
1980 static int remove_mapping(BDRVVVFATState* s, int mapping_index)
1981 {
1982 mapping_t* mapping = array_get(&(s->mapping), mapping_index);
1983 mapping_t* first_mapping = array_get(&(s->mapping), 0);
1984
1985 /* free mapping */
1986 if (mapping->first_mapping_index < 0) {
1987 g_free(mapping->path);
1988 }
1989
1990 /* remove from s->mapping */
1991 array_remove(&(s->mapping), mapping_index);
1992
1993 /* adjust all references to mappings */
1994 adjust_mapping_indices(s, mapping_index, -1);
1995
1996 if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1997 s->current_mapping = array_get(&(s->mapping),
1998 s->current_mapping - first_mapping);
1999
2000 return 0;
2001 }
2002
2003 static void adjust_dirindices(BDRVVVFATState* s, int offset, int adjust)
2004 {
2005 int i;
2006 for (i = 0; i < s->mapping.next; i++) {
2007 mapping_t* mapping = array_get(&(s->mapping), i);
2008 if (mapping->dir_index >= offset)
2009 mapping->dir_index += adjust;
2010 if ((mapping->mode & MODE_DIRECTORY) &&
2011 mapping->info.dir.first_dir_index >= offset)
2012 mapping->info.dir.first_dir_index += adjust;
2013 }
2014 }
2015
2016 static direntry_t* insert_direntries(BDRVVVFATState* s,
2017 int dir_index, int count)
2018 {
2019 /*
2020 * make room in s->directory,
2021 * adjust_dirindices
2022 */
2023 direntry_t* result = array_insert(&(s->directory), dir_index, count);
2024 if (result == NULL)
2025 return NULL;
2026 adjust_dirindices(s, dir_index, count);
2027 return result;
2028 }
2029
2030 static int remove_direntries(BDRVVVFATState* s, int dir_index, int count)
2031 {
2032 int ret = array_remove_slice(&(s->directory), dir_index, count);
2033 if (ret)
2034 return ret;
2035 adjust_dirindices(s, dir_index, -count);
2036 return 0;
2037 }
2038
2039 /*
2040 * Adapt the mappings of the cluster chain starting at first cluster
2041 * (i.e. if a file starts at first_cluster, the chain is followed according
2042 * to the modified fat, and the corresponding entries in s->mapping are
2043 * adjusted)
2044 */
2045 static int commit_mappings(BDRVVVFATState* s,
2046 uint32_t first_cluster, int dir_index)
2047 {
2048 mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2049 direntry_t* direntry = array_get(&(s->directory), dir_index);
2050 uint32_t cluster = first_cluster;
2051
2052 vvfat_close_current_file(s);
2053
2054 assert(mapping);
2055 assert(mapping->begin == first_cluster);
2056 mapping->first_mapping_index = -1;
2057 mapping->dir_index = dir_index;
2058 mapping->mode = (dir_index <= 0 || is_directory(direntry)) ?
2059 MODE_DIRECTORY : MODE_NORMAL;
2060
2061 while (!fat_eof(s, cluster)) {
2062 uint32_t c, c1;
2063
2064 for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
2065 c = c1, c1 = modified_fat_get(s, c1));
2066
2067 c++;
2068 if (c > mapping->end) {
2069 int index = array_index(&(s->mapping), mapping);
2070 int i, max_i = s->mapping.next - index;
2071 for (i = 1; i < max_i && mapping[i].begin < c; i++);
2072 while (--i > 0)
2073 remove_mapping(s, index + 1);
2074 }
2075 assert(mapping == array_get(&(s->mapping), s->mapping.next - 1)
2076 || mapping[1].begin >= c);
2077 mapping->end = c;
2078
2079 if (!fat_eof(s, c1)) {
2080 int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next);
2081 mapping_t* next_mapping = i >= s->mapping.next ? NULL :
2082 array_get(&(s->mapping), i);
2083
2084 if (next_mapping == NULL || next_mapping->begin > c1) {
2085 int i1 = array_index(&(s->mapping), mapping);
2086
2087 next_mapping = insert_mapping(s, c1, c1+1);
2088
2089 if (c1 < c)
2090 i1++;
2091 mapping = array_get(&(s->mapping), i1);
2092 }
2093
2094 next_mapping->dir_index = mapping->dir_index;
2095 next_mapping->first_mapping_index =
2096 mapping->first_mapping_index < 0 ?
2097 array_index(&(s->mapping), mapping) :
2098 mapping->first_mapping_index;
2099 next_mapping->path = mapping->path;
2100 next_mapping->mode = mapping->mode;
2101 next_mapping->read_only = mapping->read_only;
2102 if (mapping->mode & MODE_DIRECTORY) {
2103 next_mapping->info.dir.parent_mapping_index =
2104 mapping->info.dir.parent_mapping_index;
2105 next_mapping->info.dir.first_dir_index =
2106 mapping->info.dir.first_dir_index +
2107 0x10 * s->sectors_per_cluster *
2108 (mapping->end - mapping->begin);
2109 } else
2110 next_mapping->info.file.offset = mapping->info.file.offset +
2111 mapping->end - mapping->begin;
2112
2113 mapping = next_mapping;
2114 }
2115
2116 cluster = c1;
2117 }
2118
2119 return 0;
2120 }
2121
2122 static int commit_direntries(BDRVVVFATState* s,
2123 int dir_index, int parent_mapping_index)
2124 {
2125 direntry_t* direntry = array_get(&(s->directory), dir_index);
2126 uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
2127 mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2128
2129 int factor = 0x10 * s->sectors_per_cluster;
2130 int old_cluster_count, new_cluster_count;
2131 int current_dir_index = mapping->info.dir.first_dir_index;
2132 int first_dir_index = current_dir_index;
2133 int ret, i;
2134 uint32_t c;
2135
2136 DLOG(fprintf(stderr, "commit_direntries for %s, parent_mapping_index %d\n", mapping->path, parent_mapping_index));
2137
2138 assert(direntry);
2139 assert(mapping);
2140 assert(mapping->begin == first_cluster);
2141 assert(mapping->info.dir.first_dir_index < s->directory.next);
2142 assert(mapping->mode & MODE_DIRECTORY);
2143 assert(dir_index == 0 || is_directory(direntry));
2144
2145 mapping->info.dir.parent_mapping_index = parent_mapping_index;
2146
2147 if (first_cluster == 0) {
2148 old_cluster_count = new_cluster_count =
2149 s->last_cluster_of_root_directory;
2150 } else {
2151 for (old_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2152 c = fat_get(s, c))
2153 old_cluster_count++;
2154
2155 for (new_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2156 c = modified_fat_get(s, c))
2157 new_cluster_count++;
2158 }
2159
2160 if (new_cluster_count > old_cluster_count) {
2161 if (insert_direntries(s,
2162 current_dir_index + factor * old_cluster_count,
2163 factor * (new_cluster_count - old_cluster_count)) == NULL)
2164 return -1;
2165 } else if (new_cluster_count < old_cluster_count)
2166 remove_direntries(s,
2167 current_dir_index + factor * new_cluster_count,
2168 factor * (old_cluster_count - new_cluster_count));
2169
2170 for (c = first_cluster; !fat_eof(s, c); c = modified_fat_get(s, c)) {
2171 void* direntry = array_get(&(s->directory), current_dir_index);
2172 int ret = vvfat_read(s->bs, cluster2sector(s, c), direntry,
2173 s->sectors_per_cluster);
2174 if (ret)
2175 return ret;
2176 assert(!strncmp(s->directory.pointer, "QEMU", 4));
2177 current_dir_index += factor;
2178 }
2179
2180 ret = commit_mappings(s, first_cluster, dir_index);
2181 if (ret)
2182 return ret;
2183
2184 /* recurse */
2185 for (i = 0; i < factor * new_cluster_count; i++) {
2186 direntry = array_get(&(s->directory), first_dir_index + i);
2187 if (is_directory(direntry) && !is_dot(direntry)) {
2188 mapping = find_mapping_for_cluster(s, first_cluster);
2189 assert(mapping->mode & MODE_DIRECTORY);
2190 ret = commit_direntries(s, first_dir_index + i,
2191 array_index(&(s->mapping), mapping));
2192 if (ret)
2193 return ret;
2194 }
2195 }
2196
2197 return 0;
2198 }
2199
2200 /* commit one file (adjust contents, adjust mapping),
2201 return first_mapping_index */
2202 static int commit_one_file(BDRVVVFATState* s,
2203 int dir_index, uint32_t offset)
2204 {
2205 direntry_t* direntry = array_get(&(s->directory), dir_index);
2206 uint32_t c = begin_of_direntry(direntry);
2207 uint32_t first_cluster = c;
2208 mapping_t* mapping = find_mapping_for_cluster(s, c);
2209 uint32_t size = filesize_of_direntry(direntry);
2210 char* cluster = g_malloc(s->cluster_size);
2211 uint32_t i;
2212 int fd = 0;
2213
2214 assert(offset < size);
2215 assert((offset % s->cluster_size) == 0);
2216
2217 for (i = s->cluster_size; i < offset; i += s->cluster_size)
2218 c = modified_fat_get(s, c);
2219
2220 fd = qemu_open(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666);
2221 if (fd < 0) {
2222 fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path,
2223 strerror(errno), errno);
2224 g_free(cluster);
2225 return fd;
2226 }
2227 if (offset > 0) {
2228 if (lseek(fd, offset, SEEK_SET) != offset) {
2229 qemu_close(fd);
2230 g_free(cluster);
2231 return -3;
2232 }
2233 }
2234
2235 while (offset < size) {
2236 uint32_t c1;
2237 int rest_size = (size - offset > s->cluster_size ?
2238 s->cluster_size : size - offset);
2239 int ret;
2240
2241 c1 = modified_fat_get(s, c);
2242
2243 assert((size - offset == 0 && fat_eof(s, c)) ||
2244 (size > offset && c >=2 && !fat_eof(s, c)));
2245
2246 ret = vvfat_read(s->bs, cluster2sector(s, c),
2247 (uint8_t*)cluster, (rest_size + 0x1ff) / 0x200);
2248
2249 if (ret < 0) {
2250 qemu_close(fd);
2251 g_free(cluster);
2252 return ret;
2253 }
2254
2255 if (write(fd, cluster, rest_size) < 0) {
2256 qemu_close(fd);
2257 g_free(cluster);
2258 return -2;
2259 }
2260
2261 offset += rest_size;
2262 c = c1;
2263 }
2264
2265 if (ftruncate(fd, size)) {
2266 perror("ftruncate()");
2267 qemu_close(fd);
2268 g_free(cluster);
2269 return -4;
2270 }
2271 qemu_close(fd);
2272 g_free(cluster);
2273
2274 return commit_mappings(s, first_cluster, dir_index);
2275 }
2276
2277 #ifdef DEBUG
2278 /* test, if all mappings point to valid direntries */
2279 static void check1(BDRVVVFATState* s)
2280 {
2281 int i;
2282 for (i = 0; i < s->mapping.next; i++) {
2283 mapping_t* mapping = array_get(&(s->mapping), i);
2284 if (mapping->mode & MODE_DELETED) {
2285 fprintf(stderr, "deleted\n");
2286 continue;
2287 }
2288 assert(mapping->dir_index < s->directory.next);
2289 direntry_t* direntry = array_get(&(s->directory), mapping->dir_index);
2290 assert(mapping->begin == begin_of_direntry(direntry) || mapping->first_mapping_index >= 0);
2291 if (mapping->mode & MODE_DIRECTORY) {
2292 assert(mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster * (mapping->end - mapping->begin) <= s->directory.next);
2293 assert((mapping->info.dir.first_dir_index % (0x10 * s->sectors_per_cluster)) == 0);
2294 }
2295 }
2296 }
2297
2298 /* test, if all direntries have mappings */
2299 static void check2(BDRVVVFATState* s)
2300 {
2301 int i;
2302 int first_mapping = -1;
2303
2304 for (i = 0; i < s->directory.next; i++) {
2305 direntry_t* direntry = array_get(&(s->directory), i);
2306
2307 if (is_short_name(direntry) && begin_of_direntry(direntry)) {
2308 mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
2309 assert(mapping);
2310 assert(mapping->dir_index == i || is_dot(direntry));
2311 assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry));
2312 }
2313
2314 if ((i % (0x10 * s->sectors_per_cluster)) == 0) {
2315 /* cluster start */
2316 int j, count = 0;
2317
2318 for (j = 0; j < s->mapping.next; j++) {
2319 mapping_t* mapping = array_get(&(s->mapping), j);
2320 if (mapping->mode & MODE_DELETED)
2321 continue;
2322 if (mapping->mode & MODE_DIRECTORY) {
2323 if (mapping->info.dir.first_dir_index <= i && mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster > i) {
2324 assert(++count == 1);
2325 if (mapping->first_mapping_index == -1)
2326 first_mapping = array_index(&(s->mapping), mapping);
2327 else
2328 assert(first_mapping == mapping->first_mapping_index);
2329 if (mapping->info.dir.parent_mapping_index < 0)
2330 assert(j == 0);
2331 else {
2332 mapping_t* parent = array_get(&(s->mapping), mapping->info.dir.parent_mapping_index);
2333 assert(parent->mode & MODE_DIRECTORY);
2334 assert(parent->info.dir.first_dir_index < mapping->info.dir.first_dir_index);
2335 }
2336 }
2337 }
2338 }
2339 if (count == 0)
2340 first_mapping = -1;
2341 }
2342 }
2343 }
2344 #endif
2345
2346 static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2347 {
2348 int i;
2349
2350 #ifdef DEBUG
2351 fprintf(stderr, "handle_renames\n");
2352 for (i = 0; i < s->commits.next; i++) {
2353 commit_t* commit = array_get(&(s->commits), i);
2354 fprintf(stderr, "%d, %s (%d, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action);
2355 }
2356 #endif
2357
2358 for (i = 0; i < s->commits.next;) {
2359 commit_t* commit = array_get(&(s->commits), i);
2360 if (commit->action == ACTION_RENAME) {
2361 mapping_t* mapping = find_mapping_for_cluster(s,
2362 commit->param.rename.cluster);
2363 char* old_path = mapping->path;
2364
2365 assert(commit->path);
2366 mapping->path = commit->path;
2367 if (rename(old_path, mapping->path))
2368 return -2;
2369
2370 if (mapping->mode & MODE_DIRECTORY) {
2371 int l1 = strlen(mapping->path);
2372 int l2 = strlen(old_path);
2373 int diff = l1 - l2;
2374 direntry_t* direntry = array_get(&(s->directory),
2375 mapping->info.dir.first_dir_index);
2376 uint32_t c = mapping->begin;
2377 int i = 0;
2378
2379 /* recurse */
2380 while (!fat_eof(s, c)) {
2381 do {
2382 direntry_t* d = direntry + i;
2383
2384 if (is_file(d) || (is_directory(d) && !is_dot(d))) {
2385 mapping_t* m = find_mapping_for_cluster(s,
2386 begin_of_direntry(d));
2387 int l = strlen(m->path);
2388 char* new_path = g_malloc(l + diff + 1);
2389
2390 assert(!strncmp(m->path, mapping->path, l2));
2391
2392 pstrcpy(new_path, l + diff + 1, mapping->path);
2393 pstrcpy(new_path + l1, l + diff + 1 - l1,
2394 m->path + l2);
2395
2396 schedule_rename(s, m->begin, new_path);
2397 }
2398 i++;
2399 } while((i % (0x10 * s->sectors_per_cluster)) != 0);
2400 c = fat_get(s, c);
2401 }
2402 }
2403
2404 g_free(old_path);
2405 array_remove(&(s->commits), i);
2406 continue;
2407 } else if (commit->action == ACTION_MKDIR) {
2408 mapping_t* mapping;
2409 int j, parent_path_len;
2410
2411 #ifdef __MINGW32__
2412 if (mkdir(commit->path))
2413 return -5;
2414 #else
2415 if (mkdir(commit->path, 0755))
2416 return -5;
2417 #endif
2418
2419 mapping = insert_mapping(s, commit->param.mkdir.cluster,
2420 commit->param.mkdir.cluster + 1);
2421 if (mapping == NULL)
2422 return -6;
2423
2424 mapping->mode = MODE_DIRECTORY;
2425 mapping->read_only = 0;
2426 mapping->path = commit->path;
2427 j = s->directory.next;
2428 assert(j);
2429 insert_direntries(s, s->directory.next,
2430 0x10 * s->sectors_per_cluster);
2431 mapping->info.dir.first_dir_index = j;
2432
2433 parent_path_len = strlen(commit->path)
2434 - strlen(get_basename(commit->path)) - 1;
2435 for (j = 0; j < s->mapping.next; j++) {
2436 mapping_t* m = array_get(&(s->mapping), j);
2437 if (m->first_mapping_index < 0 && m != mapping &&
2438 !strncmp(m->path, mapping->path, parent_path_len) &&
2439 strlen(m->path) == parent_path_len)
2440 break;
2441 }
2442 assert(j < s->mapping.next);
2443 mapping->info.dir.parent_mapping_index = j;
2444
2445 array_remove(&(s->commits), i);
2446 continue;
2447 }
2448
2449 i++;
2450 }
2451 return 0;
2452 }
2453
2454 /*
2455 * TODO: make sure that the short name is not matching *another* file
2456 */
2457 static int handle_commits(BDRVVVFATState* s)
2458 {
2459 int i, fail = 0;
2460
2461 vvfat_close_current_file(s);
2462
2463 for (i = 0; !fail && i < s->commits.next; i++) {
2464 commit_t* commit = array_get(&(s->commits), i);
2465 switch(commit->action) {
2466 case ACTION_RENAME: case ACTION_MKDIR:
2467 abort();
2468 fail = -2;
2469 break;
2470 case ACTION_WRITEOUT: {
2471 #ifndef NDEBUG
2472 /* these variables are only used by assert() below */
2473 direntry_t* entry = array_get(&(s->directory),
2474 commit->param.writeout.dir_index);
2475 uint32_t begin = begin_of_direntry(entry);
2476 mapping_t* mapping = find_mapping_for_cluster(s, begin);
2477 #endif
2478
2479 assert(mapping);
2480 assert(mapping->begin == begin);
2481 assert(commit->path == NULL);
2482
2483 if (commit_one_file(s, commit->param.writeout.dir_index,
2484 commit->param.writeout.modified_offset))
2485 fail = -3;
2486
2487 break;
2488 }
2489 case ACTION_NEW_FILE: {
2490 int begin = commit->param.new_file.first_cluster;
2491 mapping_t* mapping = find_mapping_for_cluster(s, begin);
2492 direntry_t* entry;
2493 int i;
2494
2495 /* find direntry */
2496 for (i = 0; i < s->directory.next; i++) {
2497 entry = array_get(&(s->directory), i);
2498 if (is_file(entry) && begin_of_direntry(entry) == begin)
2499 break;
2500 }
2501
2502 if (i >= s->directory.next) {
2503 fail = -6;
2504 continue;
2505 }
2506
2507 /* make sure there exists an initial mapping */
2508 if (mapping && mapping->begin != begin) {
2509 mapping->end = begin;
2510 mapping = NULL;
2511 }
2512 if (mapping == NULL) {
2513 mapping = insert_mapping(s, begin, begin+1);
2514 }
2515 /* most members will be fixed in commit_mappings() */
2516 assert(commit->path);
2517 mapping->path = commit->path;
2518 mapping->read_only = 0;
2519 mapping->mode = MODE_NORMAL;
2520 mapping->info.file.offset = 0;
2521
2522 if (commit_one_file(s, i, 0))
2523 fail = -7;
2524
2525 break;
2526 }
2527 default:
2528 abort();
2529 }
2530 }
2531 if (i > 0 && array_remove_slice(&(s->commits), 0, i))
2532 return -1;
2533 return fail;
2534 }
2535
2536 static int handle_deletes(BDRVVVFATState* s)
2537 {
2538 int i, deferred = 1, deleted = 1;
2539
2540 /* delete files corresponding to mappings marked as deleted */
2541 /* handle DELETEs and unused mappings (modified_fat_get(s, mapping->begin) == 0) */
2542 while (deferred && deleted) {
2543 deferred = 0;
2544 deleted = 0;
2545
2546 for (i = 1; i < s->mapping.next; i++) {
2547 mapping_t* mapping = array_get(&(s->mapping), i);
2548 if (mapping->mode & MODE_DELETED) {
2549 direntry_t* entry = array_get(&(s->directory),
2550 mapping->dir_index);
2551
2552 if (is_free(entry)) {
2553 /* remove file/directory */
2554 if (mapping->mode & MODE_DIRECTORY) {
2555 int j, next_dir_index = s->directory.next,
2556 first_dir_index = mapping->info.dir.first_dir_index;
2557
2558 if (rmdir(mapping->path) < 0) {
2559 if (errno == ENOTEMPTY) {
2560 deferred++;
2561 continue;
2562 } else
2563 return -5;
2564 }
2565
2566 for (j = 1; j < s->mapping.next; j++) {
2567 mapping_t* m = array_get(&(s->mapping), j);
2568 if (m->mode & MODE_DIRECTORY &&
2569 m->info.dir.first_dir_index >
2570 first_dir_index &&
2571 m->info.dir.first_dir_index <
2572 next_dir_index)
2573 next_dir_index =
2574 m->info.dir.first_dir_index;
2575 }
2576 remove_direntries(s, first_dir_index,
2577 next_dir_index - first_dir_index);
2578
2579 deleted++;
2580 }
2581 } else {
2582 if (unlink(mapping->path))
2583 return -4;
2584 deleted++;
2585 }
2586 DLOG(fprintf(stderr, "DELETE (%d)\n", i); print_mapping(mapping); print_direntry(entry));
2587 remove_mapping(s, i);
2588 }
2589 }
2590 }
2591
2592 return 0;
2593 }
2594
2595 /*
2596 * synchronize mapping with new state:
2597 *
2598 * - copy FAT (with bdrv_read)
2599 * - mark all filenames corresponding to mappings as deleted
2600 * - recurse direntries from root (using bs->bdrv_read)
2601 * - delete files corresponding to mappings marked as deleted
2602 */
2603 static int do_commit(BDRVVVFATState* s)
2604 {
2605 int ret = 0;
2606
2607 /* the real meat are the commits. Nothing to do? Move along! */
2608 if (s->commits.next == 0)
2609 return 0;
2610
2611 vvfat_close_current_file(s);
2612
2613 ret = handle_renames_and_mkdirs(s);
2614 if (ret) {
2615 fprintf(stderr, "Error handling renames (%d)\n", ret);
2616 abort();
2617 return ret;
2618 }
2619
2620 /* copy FAT (with bdrv_read) */
2621 memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
2622
2623 /* recurse direntries from root (using bs->bdrv_read) */
2624 ret = commit_direntries(s, 0, -1);
2625 if (ret) {
2626 fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
2627 abort();
2628 return ret;
2629 }
2630
2631 ret = handle_commits(s);
2632 if (ret) {
2633 fprintf(stderr, "Error handling commits (%d)\n", ret);
2634 abort();
2635 return ret;
2636 }
2637
2638 ret = handle_deletes(s);
2639 if (ret) {
2640 fprintf(stderr, "Error deleting\n");
2641 abort();
2642 return ret;
2643 }
2644
2645 if (s->qcow->drv->bdrv_make_empty) {
2646 s->qcow->drv->bdrv_make_empty(s->qcow);
2647 }
2648
2649 memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
2650
2651 DLOG(checkpoint());
2652 return 0;
2653 }
2654
2655 static int try_commit(BDRVVVFATState* s)
2656 {
2657 vvfat_close_current_file(s);
2658 DLOG(checkpoint());
2659 if(!is_consistent(s))
2660 return -1;
2661 return do_commit(s);
2662 }
2663
2664 static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
2665 const uint8_t *buf, int nb_sectors)
2666 {
2667 BDRVVVFATState *s = bs->opaque;
2668 int i, ret;
2669
2670 DLOG(checkpoint());
2671
2672 /* Check if we're operating in read-only mode */
2673 if (s->qcow == NULL) {
2674 return -EACCES;
2675 }
2676
2677 vvfat_close_current_file(s);
2678
2679 /*
2680 * Some sanity checks:
2681 * - do not allow writing to the boot sector
2682 * - do not allow to write non-ASCII filenames
2683 */
2684
2685 if (sector_num < s->first_sectors_number)
2686 return -1;
2687
2688 for (i = sector2cluster(s, sector_num);
2689 i <= sector2cluster(s, sector_num + nb_sectors - 1);) {
2690 mapping_t* mapping = find_mapping_for_cluster(s, i);
2691 if (mapping) {
2692 if (mapping->read_only) {
2693 fprintf(stderr, "Tried to write to write-protected file %s\n",
2694 mapping->path);
2695 return -1;
2696 }
2697
2698 if (mapping->mode & MODE_DIRECTORY) {
2699 int begin = cluster2sector(s, i);
2700 int end = begin + s->sectors_per_cluster, k;
2701 int dir_index;
2702 const direntry_t* direntries;
2703 long_file_name lfn;
2704
2705 lfn_init(&lfn);
2706
2707 if (begin < sector_num)
2708 begin = sector_num;
2709 if (end > sector_num + nb_sectors)
2710 end = sector_num + nb_sectors;
2711 dir_index = mapping->dir_index +
2712 0x10 * (begin - mapping->begin * s->sectors_per_cluster);
2713 direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
2714
2715 for (k = 0; k < (end - begin) * 0x10; k++) {
2716 /* do not allow non-ASCII filenames */
2717 if (parse_long_name(&lfn, direntries + k) < 0) {
2718 fprintf(stderr, "Warning: non-ASCII filename\n");
2719 return -1;
2720 }
2721 /* no access to the direntry of a read-only file */
2722 else if (is_short_name(direntries+k) &&
2723 (direntries[k].attributes & 1)) {
2724 if (memcmp(direntries + k,
2725 array_get(&(s->directory), dir_index + k),
2726 sizeof(direntry_t))) {
2727 fprintf(stderr, "Warning: tried to write to write-protected file\n");
2728 return -1;
2729 }
2730 }
2731 }
2732 }
2733 i = mapping->end;
2734 } else
2735 i++;
2736 }
2737
2738 /*
2739 * Use qcow backend. Commit later.
2740 */
2741 DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
2742 ret = bdrv_write(s->qcow, sector_num, buf, nb_sectors);
2743 if (ret < 0) {
2744 fprintf(stderr, "Error writing to qcow backend\n");
2745 return ret;
2746 }
2747
2748 for (i = sector2cluster(s, sector_num);
2749 i <= sector2cluster(s, sector_num + nb_sectors - 1); i++)
2750 if (i >= 0)
2751 s->used_clusters[i] |= USED_ALLOCATED;
2752
2753 DLOG(checkpoint());
2754 /* TODO: add timeout */
2755 try_commit(s);
2756
2757 DLOG(checkpoint());
2758 return 0;
2759 }
2760
2761 static coroutine_fn int vvfat_co_write(BlockDriverState *bs, int64_t sector_num,
2762 const uint8_t *buf, int nb_sectors)
2763 {
2764 int ret;
2765 BDRVVVFATState *s = bs->opaque;
2766 qemu_co_mutex_lock(&s->lock);
2767 ret = vvfat_write(bs, sector_num, buf, nb_sectors);
2768 qemu_co_mutex_unlock(&s->lock);
2769 return ret;
2770 }
2771
2772 static int coroutine_fn vvfat_co_is_allocated(BlockDriverState *bs,
2773 int64_t sector_num, int nb_sectors, int* n)
2774 {
2775 BDRVVVFATState* s = bs->opaque;
2776 *n = s->sector_count - sector_num;
2777 if (*n > nb_sectors)
2778 *n = nb_sectors;
2779 else if (*n < 0)
2780 return 0;
2781 return 1;
2782 }
2783
2784 static int write_target_commit(BlockDriverState *bs, int64_t sector_num,
2785 const uint8_t* buffer, int nb_sectors) {
2786 BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
2787 return try_commit(s);
2788 }
2789
2790 static void write_target_close(BlockDriverState *bs) {
2791 BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
2792 bdrv_delete(s->qcow);
2793 g_free(s->qcow_filename);
2794 }
2795
2796 static BlockDriver vvfat_write_target = {
2797 .format_name = "vvfat_write_target",
2798 .bdrv_write = write_target_commit,
2799 .bdrv_close = write_target_close,
2800 };
2801
2802 static int enable_write_target(BDRVVVFATState *s)
2803 {
2804 BlockDriver *bdrv_qcow;
2805 QEMUOptionParameter *options;
2806 int ret;
2807 int size = sector2cluster(s, s->sector_count);
2808 s->used_clusters = calloc(size, 1);
2809
2810 array_init(&(s->commits), sizeof(commit_t));
2811
2812 s->qcow_filename = g_malloc(1024);
2813 ret = get_tmp_filename(s->qcow_filename, 1024);
2814 if (ret < 0) {
2815 g_free(s->qcow_filename);
2816 s->qcow_filename = NULL;
2817 return ret;
2818 }
2819
2820 bdrv_qcow = bdrv_find_format("qcow");
2821 options = parse_option_parameters("", bdrv_qcow->create_options, NULL);
2822 set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512);
2823 set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:");
2824
2825 if (bdrv_create(bdrv_qcow, s->qcow_filename, options) < 0)
2826 return -1;
2827
2828 s->qcow = bdrv_new("");
2829 if (s->qcow == NULL) {
2830 return -1;
2831 }
2832
2833 ret = bdrv_open(s->qcow, s->qcow_filename,
2834 BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, bdrv_qcow);
2835 if (ret < 0) {
2836 return ret;
2837 }
2838
2839 #ifndef _WIN32
2840 unlink(s->qcow_filename);
2841 #endif
2842
2843 s->bs->backing_hd = calloc(sizeof(BlockDriverState), 1);
2844 s->bs->backing_hd->drv = &vvfat_write_target;
2845 s->bs->backing_hd->opaque = g_malloc(sizeof(void*));
2846 *(void**)s->bs->backing_hd->opaque = s;
2847
2848 return 0;
2849 }
2850
2851 static void vvfat_close(BlockDriverState *bs)
2852 {
2853 BDRVVVFATState *s = bs->opaque;
2854
2855 vvfat_close_current_file(s);
2856 array_free(&(s->fat));
2857 array_free(&(s->directory));
2858 array_free(&(s->mapping));
2859 g_free(s->cluster_buffer);
2860
2861 if (s->qcow) {
2862 migrate_del_blocker(s->migration_blocker);
2863 error_free(s->migration_blocker);
2864 }
2865 }
2866
2867 static BlockDriver bdrv_vvfat = {
2868 .format_name = "vvfat",
2869 .instance_size = sizeof(BDRVVVFATState),
2870 .bdrv_file_open = vvfat_open,
2871 .bdrv_rebind = vvfat_rebind,
2872 .bdrv_read = vvfat_co_read,
2873 .bdrv_write = vvfat_co_write,
2874 .bdrv_close = vvfat_close,
2875 .bdrv_co_is_allocated = vvfat_co_is_allocated,
2876 .protocol_name = "fat",
2877 };
2878
2879 static void bdrv_vvfat_init(void)
2880 {
2881 bdrv_register(&bdrv_vvfat);
2882 }
2883
2884 block_init(bdrv_vvfat_init);
2885
2886 #ifdef DEBUG
2887 static void checkpoint(void) {
2888 assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2);
2889 check1(vvv);
2890 check2(vvv);
2891 assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY));
2892 #if 0
2893 if (((direntry_t*)vvv->directory.pointer)[1].attributes != 0xf)
2894 fprintf(stderr, "Nonono!\n");
2895 mapping_t* mapping;
2896 direntry_t* direntry;
2897 assert(vvv->mapping.size >= vvv->mapping.item_size * vvv->mapping.next);
2898 assert(vvv->directory.size >= vvv->directory.item_size * vvv->directory.next);
2899 if (vvv->mapping.next<47)
2900 return;
2901 assert((mapping = array_get(&(vvv->mapping), 47)));
2902 assert(mapping->dir_index < vvv->directory.next);
2903 direntry = array_get(&(vvv->directory), mapping->dir_index);
2904 assert(!memcmp(direntry->name, "USB H ", 11) || direntry->name[0]==0);
2905 #endif
2906 }
2907 #endif