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