Revision 99a0949b block/vvfat.c
b/block/vvfat.c | ||
---|---|---|
71 | 71 |
#endif |
72 | 72 |
|
73 | 73 |
/* dynamic array functions */ |
74 |
typedef struct array_t {
|
|
74 |
typedef struct array { |
|
75 | 75 |
char* pointer; |
76 | 76 |
unsigned int size,next,item_size; |
77 |
} array_t;
|
|
77 |
} an_array;
|
|
78 | 78 |
|
79 |
static inline void array_init(array_t* array,unsigned int item_size)
|
|
79 |
static inline void array_init(an_array* array,unsigned int item_size)
|
|
80 | 80 |
{ |
81 | 81 |
array->pointer = NULL; |
82 | 82 |
array->size=0; |
... | ... | |
84 | 84 |
array->item_size=item_size; |
85 | 85 |
} |
86 | 86 |
|
87 |
static inline void array_free(array_t* array)
|
|
87 |
static inline void array_free(an_array* array)
|
|
88 | 88 |
{ |
89 | 89 |
if(array->pointer) |
90 | 90 |
free(array->pointer); |
... | ... | |
92 | 92 |
} |
93 | 93 |
|
94 | 94 |
/* does not automatically grow */ |
95 |
static inline void* array_get(array_t* array,unsigned int index) {
|
|
95 |
static inline void* array_get(an_array* array,unsigned int index) {
|
|
96 | 96 |
assert(index < array->next); |
97 | 97 |
return array->pointer + index * array->item_size; |
98 | 98 |
} |
99 | 99 |
|
100 |
static inline int array_ensure_allocated(array_t* array, int index)
|
|
100 |
static inline int array_ensure_allocated(an_array* array, int index)
|
|
101 | 101 |
{ |
102 | 102 |
if((index + 1) * array->item_size > array->size) { |
103 | 103 |
int new_size = (index + 32) * array->item_size; |
... | ... | |
111 | 111 |
return 0; |
112 | 112 |
} |
113 | 113 |
|
114 |
static inline void* array_get_next(array_t* array) {
|
|
114 |
static inline void* array_get_next(an_array* array) {
|
|
115 | 115 |
unsigned int next = array->next; |
116 | 116 |
void* result; |
117 | 117 |
|
... | ... | |
124 | 124 |
return result; |
125 | 125 |
} |
126 | 126 |
|
127 |
static inline void* array_insert(array_t* array,unsigned int index,unsigned int count) {
|
|
127 |
static inline void* array_insert(an_array* array,unsigned int index,unsigned int count) {
|
|
128 | 128 |
if((array->next+count)*array->item_size>array->size) { |
129 | 129 |
int increment=count*array->item_size; |
130 | 130 |
array->pointer=qemu_realloc(array->pointer,array->size+increment); |
... | ... | |
141 | 141 |
|
142 | 142 |
/* this performs a "roll", so that the element which was at index_from becomes |
143 | 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)
|
|
144 |
static inline int array_roll(an_array* array,int index_to,int index_from,int count)
|
|
145 | 145 |
{ |
146 | 146 |
char* buf; |
147 | 147 |
char* from; |
... | ... | |
174 | 174 |
return 0; |
175 | 175 |
} |
176 | 176 |
|
177 |
static inline int array_remove_slice(array_t* array,int index, int count)
|
|
177 |
static inline int array_remove_slice(an_array* array,int index, int count)
|
|
178 | 178 |
{ |
179 | 179 |
assert(index >=0); |
180 | 180 |
assert(count > 0); |
... | ... | |
185 | 185 |
return 0; |
186 | 186 |
} |
187 | 187 |
|
188 |
static int array_remove(array_t* array,int index)
|
|
188 |
static int array_remove(an_array* array,int index)
|
|
189 | 189 |
{ |
190 | 190 |
return array_remove_slice(array, index, 1); |
191 | 191 |
} |
192 | 192 |
|
193 | 193 |
/* return the index for a given member */ |
194 |
static int array_index(array_t* array, void* pointer)
|
|
194 |
static int array_index(an_array* array, void* pointer)
|
|
195 | 195 |
{ |
196 | 196 |
size_t offset = (char*)pointer - array->pointer; |
197 | 197 |
assert((offset % array->item_size) == 0); |
... | ... | |
202 | 202 |
/* These structures are used to fake a disk and the VFAT filesystem. |
203 | 203 |
* For this reason we need to use __attribute__((packed)). */ |
204 | 204 |
|
205 |
typedef struct bootsector_t {
|
|
205 |
typedef struct bootsector { |
|
206 | 206 |
uint8_t jump[3]; |
207 | 207 |
uint8_t name[8]; |
208 | 208 |
uint16_t sector_size; |
... | ... | |
238 | 238 |
uint8_t fat_type[8]; |
239 | 239 |
uint8_t ignored[0x1c0]; |
240 | 240 |
uint8_t magic[2]; |
241 |
} __attribute__((packed)) bootsector_t;
|
|
241 |
} __attribute__((packed)) a_bootsector;
|
|
242 | 242 |
|
243 | 243 |
typedef struct { |
244 | 244 |
uint8_t head; |
245 | 245 |
uint8_t sector; |
246 | 246 |
uint8_t cylinder; |
247 |
} mbr_chs_t;
|
|
247 |
} a_mbr_chs;
|
|
248 | 248 |
|
249 |
typedef struct partition_t {
|
|
249 |
typedef struct partition { |
|
250 | 250 |
uint8_t attributes; /* 0x80 = bootable */ |
251 |
mbr_chs_t start_CHS;
|
|
251 |
a_mbr_chs start_CHS;
|
|
252 | 252 |
uint8_t fs_type; /* 0x1 = FAT12, 0x6 = FAT16, 0xe = FAT16_LBA, 0xb = FAT32, 0xc = FAT32_LBA */ |
253 |
mbr_chs_t end_CHS;
|
|
253 |
a_mbr_chs end_CHS;
|
|
254 | 254 |
uint32_t start_sector_long; |
255 | 255 |
uint32_t length_sector_long; |
256 |
} __attribute__((packed)) partition_t;
|
|
256 |
} __attribute__((packed)) a_partition;
|
|
257 | 257 |
|
258 |
typedef struct mbr_t {
|
|
258 |
typedef struct mbr { |
|
259 | 259 |
uint8_t ignored[0x1b8]; |
260 | 260 |
uint32_t nt_id; |
261 | 261 |
uint8_t ignored2[2]; |
262 |
partition_t partition[4];
|
|
262 |
a_partition partition[4];
|
|
263 | 263 |
uint8_t magic[2]; |
264 |
} __attribute__((packed)) mbr_t;
|
|
264 |
} __attribute__((packed)) a_mbr;
|
|
265 | 265 |
|
266 |
typedef struct direntry_t {
|
|
266 |
typedef struct direntry { |
|
267 | 267 |
uint8_t name[8]; |
268 | 268 |
uint8_t extension[3]; |
269 | 269 |
uint8_t attributes; |
... | ... | |
276 | 276 |
uint16_t mdate; |
277 | 277 |
uint16_t begin; |
278 | 278 |
uint32_t size; |
279 |
} __attribute__((packed)) direntry_t;
|
|
279 |
} __attribute__((packed)) a_direntry;
|
|
280 | 280 |
|
281 | 281 |
/* this structure are used to transparently access the files */ |
282 | 282 |
|
283 |
typedef struct mapping_t {
|
|
283 |
typedef struct mapping { |
|
284 | 284 |
/* begin is the first cluster, end is the last+1 */ |
285 | 285 |
uint32_t begin,end; |
286 | 286 |
/* as s->directory is growable, no pointer may be used here */ |
... | ... | |
308 | 308 |
MODE_DIRECTORY = 4, MODE_FAKED = 8, |
309 | 309 |
MODE_DELETED = 16, MODE_RENAMED = 32 } mode; |
310 | 310 |
int read_only; |
311 |
} mapping_t;
|
|
311 |
} a_mapping;
|
|
312 | 312 |
|
313 | 313 |
#ifdef DEBUG |
314 |
static void print_direntry(const struct direntry_t*);
|
|
315 |
static void print_mapping(const struct mapping_t* mapping);
|
|
314 |
static void print_direntry(const struct a_direntry*);
|
|
315 |
static void print_mapping(const struct a_mapping* mapping);
|
|
316 | 316 |
#endif |
317 | 317 |
|
318 | 318 |
/* here begins the real VVFAT driver */ |
... | ... | |
323 | 323 |
unsigned char first_sectors[0x40*0x200]; |
324 | 324 |
|
325 | 325 |
int fat_type; /* 16 or 32 */ |
326 |
array_t fat,directory,mapping;
|
|
326 |
an_array fat,directory,mapping;
|
|
327 | 327 |
|
328 | 328 |
unsigned int cluster_size; |
329 | 329 |
unsigned int sectors_per_cluster; |
... | ... | |
336 | 336 |
uint32_t max_fat_value; |
337 | 337 |
|
338 | 338 |
int current_fd; |
339 |
mapping_t* current_mapping;
|
|
339 |
a_mapping* current_mapping;
|
|
340 | 340 |
unsigned char* cluster; /* points to current cluster */ |
341 | 341 |
unsigned char* cluster_buffer; /* points to a buffer to hold temp data */ |
342 | 342 |
unsigned int current_cluster; |
... | ... | |
347 | 347 |
BlockDriverState* qcow; |
348 | 348 |
void* fat2; |
349 | 349 |
char* used_clusters; |
350 |
array_t commits;
|
|
350 |
an_array commits;
|
|
351 | 351 |
const char* path; |
352 | 352 |
int downcase_short_names; |
353 | 353 |
} BDRVVVFATState; |
... | ... | |
356 | 356 |
* if the position is outside the specified geometry, fill maximum value for CHS |
357 | 357 |
* and return 1 to signal overflow. |
358 | 358 |
*/ |
359 |
static int sector2CHS(BlockDriverState* bs, mbr_chs_t * chs, int spos){
|
|
359 |
static int sector2CHS(BlockDriverState* bs, a_mbr_chs * chs, int spos){
|
|
360 | 360 |
int head,sector; |
361 | 361 |
sector = spos % (bs->secs); spos/= bs->secs; |
362 | 362 |
head = spos % (bs->heads); spos/= bs->heads; |
... | ... | |
378 | 378 |
static void init_mbr(BDRVVVFATState* s) |
379 | 379 |
{ |
380 | 380 |
/* TODO: if the files mbr.img and bootsect.img exist, use them */ |
381 |
mbr_t* real_mbr=(mbr_t*)s->first_sectors;
|
|
382 |
partition_t* partition = &(real_mbr->partition[0]);
|
|
381 |
a_mbr* real_mbr=(a_mbr*)s->first_sectors;
|
|
382 |
a_partition* partition = &(real_mbr->partition[0]);
|
|
383 | 383 |
int lba; |
384 | 384 |
|
385 | 385 |
memset(s->first_sectors,0,512); |
... | ... | |
425 | 425 |
return len; |
426 | 426 |
} |
427 | 427 |
|
428 |
static inline direntry_t* create_long_filename(BDRVVVFATState* s,const char* filename)
|
|
428 |
static inline a_direntry* create_long_filename(BDRVVVFATState* s,const char* filename)
|
|
429 | 429 |
{ |
430 | 430 |
char buffer[258]; |
431 | 431 |
int length=short2long_name(buffer,filename), |
432 | 432 |
number_of_entries=(length+25)/26,i; |
433 |
direntry_t* entry;
|
|
433 |
a_direntry* entry;
|
|
434 | 434 |
|
435 | 435 |
for(i=0;i<number_of_entries;i++) { |
436 | 436 |
entry=array_get_next(&(s->directory)); |
... | ... | |
450 | 450 |
return array_get(&(s->directory),s->directory.next-number_of_entries); |
451 | 451 |
} |
452 | 452 |
|
453 |
static char is_free(const direntry_t* direntry)
|
|
453 |
static char is_free(const a_direntry* direntry)
|
|
454 | 454 |
{ |
455 | 455 |
return direntry->name[0]==0xe5 || direntry->name[0]==0x00; |
456 | 456 |
} |
457 | 457 |
|
458 |
static char is_volume_label(const direntry_t* direntry)
|
|
458 |
static char is_volume_label(const a_direntry* direntry)
|
|
459 | 459 |
{ |
460 | 460 |
return direntry->attributes == 0x28; |
461 | 461 |
} |
462 | 462 |
|
463 |
static char is_long_name(const direntry_t* direntry)
|
|
463 |
static char is_long_name(const a_direntry* direntry)
|
|
464 | 464 |
{ |
465 | 465 |
return direntry->attributes == 0xf; |
466 | 466 |
} |
467 | 467 |
|
468 |
static char is_short_name(const direntry_t* direntry)
|
|
468 |
static char is_short_name(const a_direntry* direntry)
|
|
469 | 469 |
{ |
470 | 470 |
return !is_volume_label(direntry) && !is_long_name(direntry) |
471 | 471 |
&& !is_free(direntry); |
472 | 472 |
} |
473 | 473 |
|
474 |
static char is_directory(const direntry_t* direntry)
|
|
474 |
static char is_directory(const a_direntry* direntry)
|
|
475 | 475 |
{ |
476 | 476 |
return direntry->attributes & 0x10 && direntry->name[0] != 0xe5; |
477 | 477 |
} |
478 | 478 |
|
479 |
static inline char is_dot(const direntry_t* direntry)
|
|
479 |
static inline char is_dot(const a_direntry* direntry)
|
|
480 | 480 |
{ |
481 | 481 |
return is_short_name(direntry) && direntry->name[0] == '.'; |
482 | 482 |
} |
483 | 483 |
|
484 |
static char is_file(const direntry_t* direntry)
|
|
484 |
static char is_file(const a_direntry* direntry)
|
|
485 | 485 |
{ |
486 | 486 |
return is_short_name(direntry) && !is_directory(direntry); |
487 | 487 |
} |
488 | 488 |
|
489 |
static inline uint32_t begin_of_direntry(const direntry_t* direntry)
|
|
489 |
static inline uint32_t begin_of_direntry(const a_direntry* direntry)
|
|
490 | 490 |
{ |
491 | 491 |
return le16_to_cpu(direntry->begin)|(le16_to_cpu(direntry->begin_hi)<<16); |
492 | 492 |
} |
493 | 493 |
|
494 |
static inline uint32_t filesize_of_direntry(const direntry_t* direntry)
|
|
494 |
static inline uint32_t filesize_of_direntry(const a_direntry* direntry)
|
|
495 | 495 |
{ |
496 | 496 |
return le32_to_cpu(direntry->size); |
497 | 497 |
} |
498 | 498 |
|
499 |
static void set_begin_of_direntry(direntry_t* direntry, uint32_t begin)
|
|
499 |
static void set_begin_of_direntry(a_direntry* direntry, uint32_t begin)
|
|
500 | 500 |
{ |
501 | 501 |
direntry->begin = cpu_to_le16(begin & 0xffff); |
502 | 502 |
direntry->begin_hi = cpu_to_le16((begin >> 16) & 0xffff); |
... | ... | |
504 | 504 |
|
505 | 505 |
/* fat functions */ |
506 | 506 |
|
507 |
static inline uint8_t fat_chksum(const direntry_t* entry)
|
|
507 |
static inline uint8_t fat_chksum(const a_direntry* entry)
|
|
508 | 508 |
{ |
509 | 509 |
uint8_t chksum=0; |
510 | 510 |
int i; |
... | ... | |
603 | 603 |
|
604 | 604 |
/* TODO: in create_short_filename, 0xe5->0x05 is not yet handled! */ |
605 | 605 |
/* TODO: in parse_short_filename, 0x05->0xe5 is not yet handled! */ |
606 |
static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,
|
|
606 |
static inline a_direntry* create_short_and_long_name(BDRVVVFATState* s,
|
|
607 | 607 |
unsigned int directory_start, const char* filename, int is_dot) |
608 | 608 |
{ |
609 | 609 |
int i,j,long_index=s->directory.next; |
610 |
direntry_t* entry = NULL;
|
|
611 |
direntry_t* entry_long = NULL;
|
|
610 |
a_direntry* entry = NULL;
|
|
611 |
a_direntry* entry_long = NULL;
|
|
612 | 612 |
|
613 | 613 |
if(is_dot) { |
614 | 614 |
entry=array_get_next(&(s->directory)); |
... | ... | |
646 | 646 |
|
647 | 647 |
/* mangle duplicates */ |
648 | 648 |
while(1) { |
649 |
direntry_t* entry1=array_get(&(s->directory),directory_start);
|
|
649 |
a_direntry* entry1=array_get(&(s->directory),directory_start);
|
|
650 | 650 |
int j; |
651 | 651 |
|
652 | 652 |
for(;entry1<entry;entry1++) |
... | ... | |
693 | 693 |
*/ |
694 | 694 |
static int read_directory(BDRVVVFATState* s, int mapping_index) |
695 | 695 |
{ |
696 |
mapping_t* mapping = array_get(&(s->mapping), mapping_index);
|
|
697 |
direntry_t* direntry;
|
|
696 |
a_mapping* mapping = array_get(&(s->mapping), mapping_index);
|
|
697 |
a_direntry* direntry;
|
|
698 | 698 |
const char* dirname = mapping->path; |
699 | 699 |
int first_cluster = mapping->begin; |
700 | 700 |
int parent_index = mapping->info.dir.parent_mapping_index; |
701 |
mapping_t* parent_mapping = (mapping_t*)
|
|
701 |
a_mapping* parent_mapping = (a_mapping*)
|
|
702 | 702 |
(parent_index >= 0 ? array_get(&(s->mapping), parent_index) : NULL); |
703 | 703 |
int first_cluster_of_parent = parent_mapping ? parent_mapping->begin : -1; |
704 | 704 |
|
... | ... | |
720 | 720 |
while((entry=readdir(dir))) { |
721 | 721 |
unsigned int length=strlen(dirname)+2+strlen(entry->d_name); |
722 | 722 |
char* buffer; |
723 |
direntry_t* direntry;
|
|
723 |
a_direntry* direntry;
|
|
724 | 724 |
struct stat st; |
725 | 725 |
int is_dot=!strcmp(entry->d_name,"."); |
726 | 726 |
int is_dotdot=!strcmp(entry->d_name,".."); |
... | ... | |
762 | 762 |
|
763 | 763 |
/* create mapping for this file */ |
764 | 764 |
if(!is_dot && !is_dotdot && (S_ISDIR(st.st_mode) || st.st_size)) { |
765 |
s->current_mapping=(mapping_t*)array_get_next(&(s->mapping));
|
|
765 |
s->current_mapping=(a_mapping*)array_get_next(&(s->mapping));
|
|
766 | 766 |
s->current_mapping->begin=0; |
767 | 767 |
s->current_mapping->end=st.st_size; |
768 | 768 |
/* |
... | ... | |
788 | 788 |
|
789 | 789 |
/* fill with zeroes up to the end of the cluster */ |
790 | 790 |
while(s->directory.next%(0x10*s->sectors_per_cluster)) { |
791 |
direntry_t* direntry=array_get_next(&(s->directory));
|
|
792 |
memset(direntry,0,sizeof(direntry_t));
|
|
791 |
a_direntry* direntry=array_get_next(&(s->directory));
|
|
792 |
memset(direntry,0,sizeof(a_direntry));
|
|
793 | 793 |
} |
794 | 794 |
|
795 | 795 |
/* TODO: if there are more entries, bootsector has to be adjusted! */ |
... | ... | |
799 | 799 |
int cur = s->directory.next; |
800 | 800 |
array_ensure_allocated(&(s->directory), ROOT_ENTRIES - 1); |
801 | 801 |
memset(array_get(&(s->directory), cur), 0, |
802 |
(ROOT_ENTRIES - cur) * sizeof(direntry_t));
|
|
802 |
(ROOT_ENTRIES - cur) * sizeof(a_direntry));
|
|
803 | 803 |
} |
804 | 804 |
|
805 | 805 |
/* reget the mapping, since s->mapping was possibly realloc()ed */ |
806 |
mapping = (mapping_t*)array_get(&(s->mapping), mapping_index);
|
|
806 |
mapping = (a_mapping*)array_get(&(s->mapping), mapping_index);
|
|
807 | 807 |
first_cluster += (s->directory.next - mapping->info.dir.first_dir_index) |
808 | 808 |
* 0x20 / s->cluster_size; |
809 | 809 |
mapping->end = first_cluster; |
810 | 810 |
|
811 |
direntry = (direntry_t*)array_get(&(s->directory), mapping->dir_index);
|
|
811 |
direntry = (a_direntry*)array_get(&(s->directory), mapping->dir_index);
|
|
812 | 812 |
set_begin_of_direntry(direntry, mapping->begin); |
813 | 813 |
|
814 | 814 |
return 0; |
... | ... | |
830 | 830 |
} |
831 | 831 |
|
832 | 832 |
#ifdef DBG |
833 |
static direntry_t* get_direntry_for_mapping(BDRVVVFATState* s,mapping_t* mapping)
|
|
833 |
static a_direntry* get_direntry_for_mapping(BDRVVVFATState* s,a_mapping* mapping)
|
|
834 | 834 |
{ |
835 | 835 |
if(mapping->mode==MODE_UNDEFINED) |
836 | 836 |
return 0; |
837 |
return (direntry_t*)(s->directory.pointer+sizeof(direntry_t)*mapping->dir_index);
|
|
837 |
return (a_direntry*)(s->directory.pointer+sizeof(a_direntry)*mapping->dir_index);
|
|
838 | 838 |
} |
839 | 839 |
#endif |
840 | 840 |
|
841 | 841 |
static int init_directories(BDRVVVFATState* s, |
842 | 842 |
const char* dirname) |
843 | 843 |
{ |
844 |
bootsector_t* bootsector;
|
|
845 |
mapping_t* mapping;
|
|
844 |
a_bootsector* bootsector;
|
|
845 |
a_mapping* mapping;
|
|
846 | 846 |
unsigned int i; |
847 | 847 |
unsigned int cluster; |
848 | 848 |
|
... | ... | |
861 | 861 |
i = 1+s->sectors_per_cluster*0x200*8/s->fat_type; |
862 | 862 |
s->sectors_per_fat=(s->sector_count+i)/i; /* round up */ |
863 | 863 |
|
864 |
array_init(&(s->mapping),sizeof(mapping_t));
|
|
865 |
array_init(&(s->directory),sizeof(direntry_t));
|
|
864 |
array_init(&(s->mapping),sizeof(a_mapping));
|
|
865 |
array_init(&(s->directory),sizeof(a_direntry));
|
|
866 | 866 |
|
867 | 867 |
/* add volume label */ |
868 | 868 |
{ |
869 |
direntry_t* entry=array_get_next(&(s->directory));
|
|
869 |
a_direntry* entry=array_get_next(&(s->directory));
|
|
870 | 870 |
entry->attributes=0x28; /* archive | volume label */ |
871 | 871 |
snprintf((char*)entry->name,11,"QEMU VVFAT"); |
872 | 872 |
} |
... | ... | |
910 | 910 |
mapping->mode=MODE_NORMAL; |
911 | 911 |
mapping->begin = cluster; |
912 | 912 |
if (mapping->end > 0) { |
913 |
direntry_t* direntry = array_get(&(s->directory),
|
|
913 |
a_direntry* direntry = array_get(&(s->directory),
|
|
914 | 914 |
mapping->dir_index); |
915 | 915 |
|
916 | 916 |
mapping->end = cluster + 1 + (mapping->end-1)/s->cluster_size; |
... | ... | |
954 | 954 |
|
955 | 955 |
s->current_mapping = NULL; |
956 | 956 |
|
957 |
bootsector=(bootsector_t*)(s->first_sectors+(s->first_sectors_number-1)*0x200);
|
|
957 |
bootsector=(a_bootsector*)(s->first_sectors+(s->first_sectors_number-1)*0x200);
|
|
958 | 958 |
bootsector->jump[0]=0xeb; |
959 | 959 |
bootsector->jump[1]=0x3e; |
960 | 960 |
bootsector->jump[2]=0x90; |
... | ... | |
1100 | 1100 |
{ |
1101 | 1101 |
int index3=index1+1; |
1102 | 1102 |
while(1) { |
1103 |
mapping_t* mapping;
|
|
1103 |
a_mapping* mapping;
|
|
1104 | 1104 |
index3=(index1+index2)/2; |
1105 | 1105 |
mapping=array_get(&(s->mapping),index3); |
1106 | 1106 |
assert(mapping->begin < mapping->end); |
... | ... | |
1123 | 1123 |
} |
1124 | 1124 |
} |
1125 | 1125 |
|
1126 |
static inline mapping_t* find_mapping_for_cluster(BDRVVVFATState* s,int cluster_num)
|
|
1126 |
static inline a_mapping* find_mapping_for_cluster(BDRVVVFATState* s,int cluster_num)
|
|
1127 | 1127 |
{ |
1128 | 1128 |
int index=find_mapping_for_cluster_aux(s,cluster_num,0,s->mapping.next); |
1129 |
mapping_t* mapping;
|
|
1129 |
a_mapping* mapping;
|
|
1130 | 1130 |
if(index>=s->mapping.next) |
1131 | 1131 |
return NULL; |
1132 | 1132 |
mapping=array_get(&(s->mapping),index); |
... | ... | |
1140 | 1140 |
* This function simply compares path == mapping->path. Since the mappings |
1141 | 1141 |
* are sorted by cluster, this is expensive: O(n). |
1142 | 1142 |
*/ |
1143 |
static inline mapping_t* find_mapping_for_path(BDRVVVFATState* s,
|
|
1143 |
static inline a_mapping* find_mapping_for_path(BDRVVVFATState* s,
|
|
1144 | 1144 |
const char* path) |
1145 | 1145 |
{ |
1146 | 1146 |
int i; |
1147 | 1147 |
|
1148 | 1148 |
for (i = 0; i < s->mapping.next; i++) { |
1149 |
mapping_t* mapping = array_get(&(s->mapping), i);
|
|
1149 |
a_mapping* mapping = array_get(&(s->mapping), i);
|
|
1150 | 1150 |
if (mapping->first_mapping_index < 0 && |
1151 | 1151 |
!strcmp(path, mapping->path)) |
1152 | 1152 |
return mapping; |
... | ... | |
1155 | 1155 |
return NULL; |
1156 | 1156 |
} |
1157 | 1157 |
|
1158 |
static int open_file(BDRVVVFATState* s,mapping_t* mapping)
|
|
1158 |
static int open_file(BDRVVVFATState* s,a_mapping* mapping)
|
|
1159 | 1159 |
{ |
1160 | 1160 |
if(!mapping) |
1161 | 1161 |
return -1; |
... | ... | |
1182 | 1182 |
|| s->current_mapping->begin>cluster_num |
1183 | 1183 |
|| s->current_mapping->end<=cluster_num) { |
1184 | 1184 |
/* binary search of mappings for file */ |
1185 |
mapping_t* mapping=find_mapping_for_cluster(s,cluster_num);
|
|
1185 |
a_mapping* mapping=find_mapping_for_cluster(s,cluster_num);
|
|
1186 | 1186 |
|
1187 | 1187 |
assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end)); |
1188 | 1188 |
|
... | ... | |
1238 | 1238 |
} |
1239 | 1239 |
} |
1240 | 1240 |
|
1241 |
static void print_direntry(const direntry_t* direntry)
|
|
1241 |
static void print_direntry(const a_direntry* direntry)
|
|
1242 | 1242 |
{ |
1243 | 1243 |
int j = 0; |
1244 | 1244 |
char buffer[1024]; |
... | ... | |
1270 | 1270 |
} |
1271 | 1271 |
} |
1272 | 1272 |
|
1273 |
static void print_mapping(const mapping_t* mapping)
|
|
1273 |
static void print_mapping(const a_mapping* mapping)
|
|
1274 | 1274 |
{ |
1275 | 1275 |
fprintf(stderr, "mapping (0x%x): begin, end = %d, %d, dir_index = %d, first_mapping_index = %d, name = %s, mode = 0x%x, " , (int)mapping, mapping->begin, mapping->end, mapping->dir_index, mapping->first_mapping_index, mapping->path, mapping->mode); |
1276 | 1276 |
if (mapping->mode & MODE_DIRECTORY) |
... | ... | |
1346 | 1346 |
* |
1347 | 1347 |
*/ |
1348 | 1348 |
|
1349 |
typedef struct commit_t {
|
|
1349 |
typedef struct commit { |
|
1350 | 1350 |
char* path; |
1351 | 1351 |
union { |
1352 | 1352 |
struct { uint32_t cluster; } rename; |
... | ... | |
1358 | 1358 |
enum { |
1359 | 1359 |
ACTION_RENAME, ACTION_WRITEOUT, ACTION_NEW_FILE, ACTION_MKDIR |
1360 | 1360 |
} action; |
1361 |
} commit_t;
|
|
1361 |
} a_commit;
|
|
1362 | 1362 |
|
1363 | 1363 |
static void clear_commits(BDRVVVFATState* s) |
1364 | 1364 |
{ |
1365 | 1365 |
int i; |
1366 | 1366 |
DLOG(fprintf(stderr, "clear_commits (%d commits)\n", s->commits.next)); |
1367 | 1367 |
for (i = 0; i < s->commits.next; i++) { |
1368 |
commit_t* commit = array_get(&(s->commits), i);
|
|
1368 |
a_commit* commit = array_get(&(s->commits), i);
|
|
1369 | 1369 |
assert(commit->path || commit->action == ACTION_WRITEOUT); |
1370 | 1370 |
if (commit->action != ACTION_WRITEOUT) { |
1371 | 1371 |
assert(commit->path); |
... | ... | |
1379 | 1379 |
static void schedule_rename(BDRVVVFATState* s, |
1380 | 1380 |
uint32_t cluster, char* new_path) |
1381 | 1381 |
{ |
1382 |
commit_t* commit = array_get_next(&(s->commits));
|
|
1382 |
a_commit* commit = array_get_next(&(s->commits));
|
|
1383 | 1383 |
commit->path = new_path; |
1384 | 1384 |
commit->param.rename.cluster = cluster; |
1385 | 1385 |
commit->action = ACTION_RENAME; |
... | ... | |
1388 | 1388 |
static void schedule_writeout(BDRVVVFATState* s, |
1389 | 1389 |
int dir_index, uint32_t modified_offset) |
1390 | 1390 |
{ |
1391 |
commit_t* commit = array_get_next(&(s->commits));
|
|
1391 |
a_commit* commit = array_get_next(&(s->commits));
|
|
1392 | 1392 |
commit->path = NULL; |
1393 | 1393 |
commit->param.writeout.dir_index = dir_index; |
1394 | 1394 |
commit->param.writeout.modified_offset = modified_offset; |
... | ... | |
1398 | 1398 |
static void schedule_new_file(BDRVVVFATState* s, |
1399 | 1399 |
char* path, uint32_t first_cluster) |
1400 | 1400 |
{ |
1401 |
commit_t* commit = array_get_next(&(s->commits));
|
|
1401 |
a_commit* commit = array_get_next(&(s->commits));
|
|
1402 | 1402 |
commit->path = path; |
1403 | 1403 |
commit->param.new_file.first_cluster = first_cluster; |
1404 | 1404 |
commit->action = ACTION_NEW_FILE; |
... | ... | |
1406 | 1406 |
|
1407 | 1407 |
static void schedule_mkdir(BDRVVVFATState* s, uint32_t cluster, char* path) |
1408 | 1408 |
{ |
1409 |
commit_t* commit = array_get_next(&(s->commits));
|
|
1409 |
a_commit* commit = array_get_next(&(s->commits));
|
|
1410 | 1410 |
commit->path = path; |
1411 | 1411 |
commit->param.mkdir.cluster = cluster; |
1412 | 1412 |
commit->action = ACTION_MKDIR; |
... | ... | |
1431 | 1431 |
|
1432 | 1432 |
/* return 0 if parsed successfully, > 0 if no long name, < 0 if error */ |
1433 | 1433 |
static int parse_long_name(long_file_name* lfn, |
1434 |
const direntry_t* direntry)
|
|
1434 |
const a_direntry* direntry)
|
|
1435 | 1435 |
{ |
1436 | 1436 |
int i, j, offset; |
1437 | 1437 |
const unsigned char* pointer = (const unsigned char*)direntry; |
... | ... | |
1474 | 1474 |
|
1475 | 1475 |
/* returns 0 if successful, >0 if no short_name, and <0 on error */ |
1476 | 1476 |
static int parse_short_name(BDRVVVFATState* s, |
1477 |
long_file_name* lfn, direntry_t* direntry)
|
|
1477 |
long_file_name* lfn, a_direntry* direntry)
|
|
1478 | 1478 |
{ |
1479 | 1479 |
int i, j; |
1480 | 1480 |
|
... | ... | |
1566 | 1566 |
*/ |
1567 | 1567 |
typedef enum { |
1568 | 1568 |
USED_DIRECTORY = 1, USED_FILE = 2, USED_ANY = 3, USED_ALLOCATED = 4 |
1569 |
} used_t;
|
|
1569 |
} e_used;
|
|
1570 | 1570 |
|
1571 | 1571 |
/* |
1572 | 1572 |
* get_cluster_count_for_direntry() not only determines how many clusters |
... | ... | |
1579 | 1579 |
* assumed to be *not* deleted (and *only* those). |
1580 | 1580 |
*/ |
1581 | 1581 |
static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s, |
1582 |
direntry_t* direntry, const char* path)
|
|
1582 |
a_direntry* direntry, const char* path)
|
|
1583 | 1583 |
{ |
1584 | 1584 |
/* |
1585 | 1585 |
* This is a little bit tricky: |
... | ... | |
1605 | 1605 |
uint32_t cluster_num = begin_of_direntry(direntry); |
1606 | 1606 |
uint32_t offset = 0; |
1607 | 1607 |
int first_mapping_index = -1; |
1608 |
mapping_t* mapping = NULL;
|
|
1608 |
a_mapping* mapping = NULL;
|
|
1609 | 1609 |
const char* basename2 = NULL; |
1610 | 1610 |
|
1611 | 1611 |
vvfat_close_current_file(s); |
... | ... | |
1730 | 1730 |
{ |
1731 | 1731 |
int ret = 0; |
1732 | 1732 |
unsigned char* cluster = qemu_malloc(s->cluster_size); |
1733 |
direntry_t* direntries = (direntry_t*)cluster;
|
|
1734 |
mapping_t* mapping = find_mapping_for_cluster(s, cluster_num);
|
|
1733 |
a_direntry* direntries = (a_direntry*)cluster;
|
|
1734 |
a_mapping* mapping = find_mapping_for_cluster(s, cluster_num);
|
|
1735 | 1735 |
|
1736 | 1736 |
long_file_name lfn; |
1737 | 1737 |
int path_len = strlen(path); |
... | ... | |
1889 | 1889 |
* (check_directory_consistency() will unmark those still present). */ |
1890 | 1890 |
if (s->qcow) |
1891 | 1891 |
for (i = 0; i < s->mapping.next; i++) { |
1892 |
mapping_t* mapping = array_get(&(s->mapping), i);
|
|
1892 |
a_mapping* mapping = array_get(&(s->mapping), i);
|
|
1893 | 1893 |
if (mapping->first_mapping_index < 0) |
1894 | 1894 |
mapping->mode |= MODE_DELETED; |
1895 | 1895 |
} |
... | ... | |
1929 | 1929 |
int i; |
1930 | 1930 |
|
1931 | 1931 |
for (i = 0; i < s->mapping.next; i++) { |
1932 |
mapping_t* mapping = array_get(&(s->mapping), i);
|
|
1932 |
a_mapping* mapping = array_get(&(s->mapping), i);
|
|
1933 | 1933 |
|
1934 | 1934 |
#define ADJUST_MAPPING_INDEX(name) \ |
1935 | 1935 |
if (mapping->name >= offset) \ |
... | ... | |
1942 | 1942 |
} |
1943 | 1943 |
|
1944 | 1944 |
/* insert or update mapping */ |
1945 |
static mapping_t* insert_mapping(BDRVVVFATState* s,
|
|
1945 |
static a_mapping* insert_mapping(BDRVVVFATState* s,
|
|
1946 | 1946 |
uint32_t begin, uint32_t end) |
1947 | 1947 |
{ |
1948 | 1948 |
/* |
... | ... | |
1953 | 1953 |
* - replace name |
1954 | 1954 |
*/ |
1955 | 1955 |
int index = find_mapping_for_cluster_aux(s, begin, 0, s->mapping.next); |
1956 |
mapping_t* mapping = NULL;
|
|
1957 |
mapping_t* first_mapping = array_get(&(s->mapping), 0);
|
|
1956 |
a_mapping* mapping = NULL;
|
|
1957 |
a_mapping* first_mapping = array_get(&(s->mapping), 0);
|
|
1958 | 1958 |
|
1959 | 1959 |
if (index < s->mapping.next && (mapping = array_get(&(s->mapping), index)) |
1960 | 1960 |
&& mapping->begin < begin) { |
... | ... | |
1971 | 1971 |
mapping->begin = begin; |
1972 | 1972 |
mapping->end = end; |
1973 | 1973 |
|
1974 |
DLOG(mapping_t* next_mapping;
|
|
1974 |
DLOG(a_mapping* next_mapping;
|
|
1975 | 1975 |
assert(index + 1 >= s->mapping.next || |
1976 | 1976 |
((next_mapping = array_get(&(s->mapping), index + 1)) && |
1977 | 1977 |
next_mapping->begin >= end))); |
1978 | 1978 |
|
1979 |
if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
|
|
1979 |
if (s->current_mapping && first_mapping != (a_mapping*)s->mapping.pointer)
|
|
1980 | 1980 |
s->current_mapping = array_get(&(s->mapping), |
1981 | 1981 |
s->current_mapping - first_mapping); |
1982 | 1982 |
|
... | ... | |
1985 | 1985 |
|
1986 | 1986 |
static int remove_mapping(BDRVVVFATState* s, int mapping_index) |
1987 | 1987 |
{ |
1988 |
mapping_t* mapping = array_get(&(s->mapping), mapping_index);
|
|
1989 |
mapping_t* first_mapping = array_get(&(s->mapping), 0);
|
|
1988 |
a_mapping* mapping = array_get(&(s->mapping), mapping_index);
|
|
1989 |
a_mapping* first_mapping = array_get(&(s->mapping), 0);
|
|
1990 | 1990 |
|
1991 | 1991 |
/* free mapping */ |
1992 | 1992 |
if (mapping->first_mapping_index < 0) |
... | ... | |
1998 | 1998 |
/* adjust all references to mappings */ |
1999 | 1999 |
adjust_mapping_indices(s, mapping_index, -1); |
2000 | 2000 |
|
2001 |
if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
|
|
2001 |
if (s->current_mapping && first_mapping != (a_mapping*)s->mapping.pointer)
|
|
2002 | 2002 |
s->current_mapping = array_get(&(s->mapping), |
2003 | 2003 |
s->current_mapping - first_mapping); |
2004 | 2004 |
|
... | ... | |
2009 | 2009 |
{ |
2010 | 2010 |
int i; |
2011 | 2011 |
for (i = 0; i < s->mapping.next; i++) { |
2012 |
mapping_t* mapping = array_get(&(s->mapping), i);
|
|
2012 |
a_mapping* mapping = array_get(&(s->mapping), i);
|
|
2013 | 2013 |
if (mapping->dir_index >= offset) |
2014 | 2014 |
mapping->dir_index += adjust; |
2015 | 2015 |
if ((mapping->mode & MODE_DIRECTORY) && |
... | ... | |
2018 | 2018 |
} |
2019 | 2019 |
} |
2020 | 2020 |
|
2021 |
static direntry_t* insert_direntries(BDRVVVFATState* s,
|
|
2021 |
static a_direntry* insert_direntries(BDRVVVFATState* s,
|
|
2022 | 2022 |
int dir_index, int count) |
2023 | 2023 |
{ |
2024 | 2024 |
/* |
2025 | 2025 |
* make room in s->directory, |
2026 | 2026 |
* adjust_dirindices |
2027 | 2027 |
*/ |
2028 |
direntry_t* result = array_insert(&(s->directory), dir_index, count);
|
|
2028 |
a_direntry* result = array_insert(&(s->directory), dir_index, count);
|
|
2029 | 2029 |
if (result == NULL) |
2030 | 2030 |
return NULL; |
2031 | 2031 |
adjust_dirindices(s, dir_index, count); |
... | ... | |
2050 | 2050 |
static int commit_mappings(BDRVVVFATState* s, |
2051 | 2051 |
uint32_t first_cluster, int dir_index) |
2052 | 2052 |
{ |
2053 |
mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
|
|
2054 |
direntry_t* direntry = array_get(&(s->directory), dir_index);
|
|
2053 |
a_mapping* mapping = find_mapping_for_cluster(s, first_cluster);
|
|
2054 |
a_direntry* direntry = array_get(&(s->directory), dir_index);
|
|
2055 | 2055 |
uint32_t cluster = first_cluster; |
2056 | 2056 |
|
2057 | 2057 |
vvfat_close_current_file(s); |
... | ... | |
2083 | 2083 |
|
2084 | 2084 |
if (!fat_eof(s, c1)) { |
2085 | 2085 |
int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next); |
2086 |
mapping_t* next_mapping = i >= s->mapping.next ? NULL :
|
|
2086 |
a_mapping* next_mapping = i >= s->mapping.next ? NULL :
|
|
2087 | 2087 |
array_get(&(s->mapping), i); |
2088 | 2088 |
|
2089 | 2089 |
if (next_mapping == NULL || next_mapping->begin > c1) { |
... | ... | |
2127 | 2127 |
static int commit_direntries(BDRVVVFATState* s, |
2128 | 2128 |
int dir_index, int parent_mapping_index) |
2129 | 2129 |
{ |
2130 |
direntry_t* direntry = array_get(&(s->directory), dir_index);
|
|
2130 |
a_direntry* direntry = array_get(&(s->directory), dir_index);
|
|
2131 | 2131 |
uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry); |
2132 |
mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
|
|
2132 |
a_mapping* mapping = find_mapping_for_cluster(s, first_cluster);
|
|
2133 | 2133 |
|
2134 | 2134 |
int factor = 0x10 * s->sectors_per_cluster; |
2135 | 2135 |
int old_cluster_count, new_cluster_count; |
... | ... | |
2207 | 2207 |
static int commit_one_file(BDRVVVFATState* s, |
2208 | 2208 |
int dir_index, uint32_t offset) |
2209 | 2209 |
{ |
2210 |
direntry_t* direntry = array_get(&(s->directory), dir_index);
|
|
2210 |
a_direntry* direntry = array_get(&(s->directory), dir_index);
|
|
2211 | 2211 |
uint32_t c = begin_of_direntry(direntry); |
2212 | 2212 |
uint32_t first_cluster = c; |
2213 |
mapping_t* mapping = find_mapping_for_cluster(s, c);
|
|
2213 |
a_mapping* mapping = find_mapping_for_cluster(s, c);
|
|
2214 | 2214 |
uint32_t size = filesize_of_direntry(direntry); |
2215 | 2215 |
char* cluster = qemu_malloc(s->cluster_size); |
2216 | 2216 |
uint32_t i; |
... | ... | |
2268 | 2268 |
{ |
2269 | 2269 |
int i; |
2270 | 2270 |
for (i = 0; i < s->mapping.next; i++) { |
2271 |
mapping_t* mapping = array_get(&(s->mapping), i);
|
|
2271 |
a_mapping* mapping = array_get(&(s->mapping), i);
|
|
2272 | 2272 |
if (mapping->mode & MODE_DELETED) { |
2273 | 2273 |
fprintf(stderr, "deleted\n"); |
2274 | 2274 |
continue; |
2275 | 2275 |
} |
2276 | 2276 |
assert(mapping->dir_index >= 0); |
2277 | 2277 |
assert(mapping->dir_index < s->directory.next); |
2278 |
direntry_t* direntry = array_get(&(s->directory), mapping->dir_index);
|
|
2278 |
a_direntry* direntry = array_get(&(s->directory), mapping->dir_index);
|
|
2279 | 2279 |
assert(mapping->begin == begin_of_direntry(direntry) || mapping->first_mapping_index >= 0); |
2280 | 2280 |
if (mapping->mode & MODE_DIRECTORY) { |
2281 | 2281 |
assert(mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster * (mapping->end - mapping->begin) <= s->directory.next); |
... | ... | |
2291 | 2291 |
int first_mapping = -1; |
2292 | 2292 |
|
2293 | 2293 |
for (i = 0; i < s->directory.next; i++) { |
2294 |
direntry_t* direntry = array_get(&(s->directory), i);
|
|
2294 |
a_direntry* direntry = array_get(&(s->directory), i);
|
|
2295 | 2295 |
|
2296 | 2296 |
if (is_short_name(direntry) && begin_of_direntry(direntry)) { |
2297 |
mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
|
|
2297 |
a_mapping* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
|
|
2298 | 2298 |
assert(mapping); |
2299 | 2299 |
assert(mapping->dir_index == i || is_dot(direntry)); |
2300 | 2300 |
assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry)); |
... | ... | |
2305 | 2305 |
int j, count = 0; |
2306 | 2306 |
|
2307 | 2307 |
for (j = 0; j < s->mapping.next; j++) { |
2308 |
mapping_t* mapping = array_get(&(s->mapping), j);
|
|
2308 |
a_mapping* mapping = array_get(&(s->mapping), j);
|
|
2309 | 2309 |
if (mapping->mode & MODE_DELETED) |
2310 | 2310 |
continue; |
2311 | 2311 |
if (mapping->mode & MODE_DIRECTORY) { |
... | ... | |
2318 | 2318 |
if (mapping->info.dir.parent_mapping_index < 0) |
2319 | 2319 |
assert(j == 0); |
2320 | 2320 |
else { |
2321 |
mapping_t* parent = array_get(&(s->mapping), mapping->info.dir.parent_mapping_index);
|
|
2321 |
a_mapping* parent = array_get(&(s->mapping), mapping->info.dir.parent_mapping_index);
|
|
2322 | 2322 |
assert(parent->mode & MODE_DIRECTORY); |
2323 | 2323 |
assert(parent->info.dir.first_dir_index < mapping->info.dir.first_dir_index); |
2324 | 2324 |
} |
... | ... | |
2339 | 2339 |
#ifdef DEBUG |
2340 | 2340 |
fprintf(stderr, "handle_renames\n"); |
2341 | 2341 |
for (i = 0; i < s->commits.next; i++) { |
2342 |
commit_t* commit = array_get(&(s->commits), i);
|
|
2342 |
a_commit* commit = array_get(&(s->commits), i);
|
|
2343 | 2343 |
fprintf(stderr, "%d, %s (%d, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action); |
2344 | 2344 |
} |
2345 | 2345 |
#endif |
2346 | 2346 |
|
2347 | 2347 |
for (i = 0; i < s->commits.next;) { |
2348 |
commit_t* commit = array_get(&(s->commits), i);
|
|
2348 |
a_commit* commit = array_get(&(s->commits), i);
|
|
2349 | 2349 |
if (commit->action == ACTION_RENAME) { |
2350 |
mapping_t* mapping = find_mapping_for_cluster(s,
|
|
2350 |
a_mapping* mapping = find_mapping_for_cluster(s,
|
|
2351 | 2351 |
commit->param.rename.cluster); |
2352 | 2352 |
char* old_path = mapping->path; |
2353 | 2353 |
|
... | ... | |
2360 | 2360 |
int l1 = strlen(mapping->path); |
2361 | 2361 |
int l2 = strlen(old_path); |
2362 | 2362 |
int diff = l1 - l2; |
2363 |
direntry_t* direntry = array_get(&(s->directory),
|
|
2363 |
a_direntry* direntry = array_get(&(s->directory),
|
|
2364 | 2364 |
mapping->info.dir.first_dir_index); |
2365 | 2365 |
uint32_t c = mapping->begin; |
2366 | 2366 |
int i = 0; |
... | ... | |
2368 | 2368 |
/* recurse */ |
2369 | 2369 |
while (!fat_eof(s, c)) { |
2370 | 2370 |
do { |
2371 |
direntry_t* d = direntry + i;
|
|
2371 |
a_direntry* d = direntry + i;
|
|
2372 | 2372 |
|
2373 | 2373 |
if (is_file(d) || (is_directory(d) && !is_dot(d))) { |
2374 |
mapping_t* m = find_mapping_for_cluster(s,
|
|
2374 |
a_mapping* m = find_mapping_for_cluster(s,
|
|
2375 | 2375 |
begin_of_direntry(d)); |
2376 | 2376 |
int l = strlen(m->path); |
2377 | 2377 |
char* new_path = qemu_malloc(l + diff + 1); |
... | ... | |
2394 | 2394 |
array_remove(&(s->commits), i); |
2395 | 2395 |
continue; |
2396 | 2396 |
} else if (commit->action == ACTION_MKDIR) { |
2397 |
mapping_t* mapping;
|
|
2397 |
a_mapping* mapping;
|
|
2398 | 2398 |
int j, parent_path_len; |
2399 | 2399 |
|
2400 | 2400 |
#ifdef __MINGW32__ |
... | ... | |
2422 | 2422 |
parent_path_len = strlen(commit->path) |
2423 | 2423 |
- strlen(get_basename(commit->path)) - 1; |
2424 | 2424 |
for (j = 0; j < s->mapping.next; j++) { |
2425 |
mapping_t* m = array_get(&(s->mapping), j);
|
|
2425 |
a_mapping* m = array_get(&(s->mapping), j);
|
|
2426 | 2426 |
if (m->first_mapping_index < 0 && m != mapping && |
2427 | 2427 |
!strncmp(m->path, mapping->path, parent_path_len) && |
2428 | 2428 |
strlen(m->path) == parent_path_len) |
... | ... | |
2450 | 2450 |
vvfat_close_current_file(s); |
2451 | 2451 |
|
2452 | 2452 |
for (i = 0; !fail && i < s->commits.next; i++) { |
2453 |
commit_t* commit = array_get(&(s->commits), i);
|
|
2453 |
a_commit* commit = array_get(&(s->commits), i);
|
|
2454 | 2454 |
switch(commit->action) { |
2455 | 2455 |
case ACTION_RENAME: case ACTION_MKDIR: |
2456 | 2456 |
assert(0); |
2457 | 2457 |
fail = -2; |
2458 | 2458 |
break; |
2459 | 2459 |
case ACTION_WRITEOUT: { |
2460 |
direntry_t* entry = array_get(&(s->directory),
|
|
2460 |
a_direntry* entry = array_get(&(s->directory),
|
|
2461 | 2461 |
commit->param.writeout.dir_index); |
2462 | 2462 |
uint32_t begin = begin_of_direntry(entry); |
2463 |
mapping_t* mapping = find_mapping_for_cluster(s, begin);
|
|
2463 |
a_mapping* mapping = find_mapping_for_cluster(s, begin);
|
|
2464 | 2464 |
|
2465 | 2465 |
assert(mapping); |
2466 | 2466 |
assert(mapping->begin == begin); |
... | ... | |
2474 | 2474 |
} |
2475 | 2475 |
case ACTION_NEW_FILE: { |
2476 | 2476 |
int begin = commit->param.new_file.first_cluster; |
2477 |
mapping_t* mapping = find_mapping_for_cluster(s, begin);
|
|
2478 |
direntry_t* entry;
|
|
2477 |
a_mapping* mapping = find_mapping_for_cluster(s, begin);
|
|
2478 |
a_direntry* entry;
|
|
2479 | 2479 |
int i; |
2480 | 2480 |
|
2481 | 2481 |
/* find direntry */ |
... | ... | |
2530 | 2530 |
deleted = 0; |
2531 | 2531 |
|
2532 | 2532 |
for (i = 1; i < s->mapping.next; i++) { |
2533 |
mapping_t* mapping = array_get(&(s->mapping), i);
|
|
2533 |
a_mapping* mapping = array_get(&(s->mapping), i);
|
|
2534 | 2534 |
if (mapping->mode & MODE_DELETED) { |
2535 |
direntry_t* entry = array_get(&(s->directory),
|
|
2535 |
a_direntry* entry = array_get(&(s->directory),
|
|
2536 | 2536 |
mapping->dir_index); |
2537 | 2537 |
|
2538 | 2538 |
if (is_free(entry)) { |
... | ... | |
2550 | 2550 |
} |
2551 | 2551 |
|
2552 | 2552 |
for (j = 1; j < s->mapping.next; j++) { |
2553 |
mapping_t* m = array_get(&(s->mapping), j);
|
|
2553 |
a_mapping* m = array_get(&(s->mapping), j);
|
|
2554 | 2554 |
if (m->mode & MODE_DIRECTORY && |
2555 | 2555 |
m->info.dir.first_dir_index > |
2556 | 2556 |
first_dir_index && |
... | ... | |
2666 | 2666 |
|
2667 | 2667 |
for (i = sector2cluster(s, sector_num); |
2668 | 2668 |
i <= sector2cluster(s, sector_num + nb_sectors - 1);) { |
2669 |
mapping_t* mapping = find_mapping_for_cluster(s, i);
|
|
2669 |
a_mapping* mapping = find_mapping_for_cluster(s, i);
|
|
2670 | 2670 |
if (mapping) { |
2671 | 2671 |
if (mapping->read_only) { |
2672 | 2672 |
fprintf(stderr, "Tried to write to write-protected file %s\n", |
... | ... | |
2678 | 2678 |
int begin = cluster2sector(s, i); |
2679 | 2679 |
int end = begin + s->sectors_per_cluster, k; |
2680 | 2680 |
int dir_index; |
2681 |
const direntry_t* direntries;
|
|
2681 |
const a_direntry* direntries;
|
|
2682 | 2682 |
long_file_name lfn; |
2683 | 2683 |
|
2684 | 2684 |
lfn_init(&lfn); |
... | ... | |
2689 | 2689 |
end = sector_num + nb_sectors; |
2690 | 2690 |
dir_index = mapping->dir_index + |
2691 | 2691 |
0x10 * (begin - mapping->begin * s->sectors_per_cluster); |
2692 |
direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
|
|
2692 |
direntries = (a_direntry*)(buf + 0x200 * (begin - sector_num));
|
|
2693 | 2693 |
|
2694 | 2694 |
for (k = 0; k < (end - begin) * 0x10; k++) { |
2695 | 2695 |
/* do not allow non-ASCII filenames */ |
... | ... | |
2702 | 2702 |
(direntries[k].attributes & 1)) { |
2703 | 2703 |
if (memcmp(direntries + k, |
2704 | 2704 |
array_get(&(s->directory), dir_index + k), |
2705 |
sizeof(direntry_t))) {
|
|
2705 |
sizeof(a_direntry))) {
|
|
2706 | 2706 |
fprintf(stderr, "Warning: tried to write to write-protected file\n"); |
2707 | 2707 |
return -1; |
2708 | 2708 |
} |
... | ... | |
2774 | 2774 |
int size = sector2cluster(s, s->sector_count); |
2775 | 2775 |
s->used_clusters = calloc(size, 1); |
2776 | 2776 |
|
2777 |
array_init(&(s->commits), sizeof(commit_t));
|
|
2777 |
array_init(&(s->commits), sizeof(a_commit));
|
|
2778 | 2778 |
|
2779 | 2779 |
s->qcow_filename = qemu_malloc(1024); |
2780 | 2780 |
get_tmp_filename(s->qcow_filename, 1024); |
... | ... | |
2833 | 2833 |
|
2834 | 2834 |
#ifdef DEBUG |
2835 | 2835 |
static void checkpoint(void) { |
2836 |
assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2);
|
|
2836 |
assert(((a_mapping*)array_get(&(vvv->mapping), 0))->end == 2);
|
|
2837 | 2837 |
check1(vvv); |
2838 | 2838 |
check2(vvv); |
2839 | 2839 |
assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY)); |
2840 | 2840 |
#if 0 |
2841 |
if (((direntry_t*)vvv->directory.pointer)[1].attributes != 0xf)
|
|
2841 |
if (((a_direntry*)vvv->directory.pointer)[1].attributes != 0xf)
|
|
2842 | 2842 |
fprintf(stderr, "Nonono!\n"); |
2843 |
mapping_t* mapping;
|
|
2844 |
direntry_t* direntry;
|
|
2843 |
a_mapping* mapping;
|
|
2844 |
a_direntry* direntry;
|
|
2845 | 2845 |
assert(vvv->mapping.size >= vvv->mapping.item_size * vvv->mapping.next); |
2846 | 2846 |
assert(vvv->directory.size >= vvv->directory.item_size * vvv->directory.next); |
2847 | 2847 |
if (vvv->mapping.next<47) |
Also available in: Unified diff