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