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