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