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