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