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