]> git.proxmox.com Git - qemu.git/blame - block-vvfat.c
find -type f | xargs sed -i 's/[\t ]*$//g' # Yes, again. Note the star in the regex.
[qemu.git] / block-vvfat.c
Content-type: text/html ]> git.proxmox.com Git - qemu.git/blame - block-vvfat.c


500 - Internal Server Error

Malformed UTF-8 character (fatal) at (eval 6) line 1, <$fd> line 2489.
CommitLineData
a046433a 1/* vim:set shiftwidth=4 ts=8: */
de167e41
FB
2/*
3 * QEMU Block driver for virtual VFAT (shadows a local directory)
5fafdf24 4 *
a046433a 5 * Copyright (c) 2004,2005 Johannes E. Schindelin
5fafdf24 6 *
de167e41
FB
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25#include <sys/stat.h>
26#include <dirent.h>
27#include <assert.h>
28#include "vl.h"
29#include "block_int.h"
30
a046433a
FB
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
5fafdf24 41 Note that DOS assumes the system files to be the first files in the
a046433a
FB
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
54FILE* stderr = NULL;
de167e41 55
a046433a 56static void checkpoint();
de167e41 57
a046433a
FB
58#ifdef __MINGW32__
59void 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
6bcb76c3 64#define assert(a) do {if (!(a)) nonono(__FILE__, __LINE__, #a);}while(0)
a046433a
FB
65#endif
66
67#else
68
69#define DLOG(a)
70
71#endif
de167e41
FB
72
73/* dynamic array functions */
74typedef struct array_t {
75 char* pointer;
76 unsigned int size,next,item_size;
77} array_t;
78
79static inline void array_init(array_t* array,unsigned int item_size)
80{
81 array->pointer=0;
82 array->size=0;
83 array->next=0;
84 array->item_size=item_size;
85}
86
87static inline void array_free(array_t* array)
88{
89 if(array->pointer)
90 free(array->pointer);
91 array->size=array->next=0;
92}
93
a046433a 94/* does not automatically grow */
de167e41 95static inline void* array_get(array_t* array,unsigned int index) {
a046433a
FB
96 assert(index >= 0);
97 assert(index < array->next);
98 return array->pointer + index * array->item_size;
99}
100
101static inline int array_ensure_allocated(array_t* array, int index)
102{
103 if((index + 1) * array->item_size > array->size) {
104 int new_size = (index + 32) * array->item_size;
105 array->pointer = realloc(array->pointer, new_size);
106 if (!array->pointer)
107 return -1;
108 array->size = new_size;
109 array->next = index + 1;
de167e41 110 }
a046433a
FB
111
112 return 0;
de167e41
FB
113}
114
115static inline void* array_get_next(array_t* array) {
a046433a
FB
116 unsigned int next = array->next;
117 void* result;
118
119 if (array_ensure_allocated(array, next) < 0)
120 return NULL;
121
122 array->next = next + 1;
123 result = array_get(array, next);
124
de167e41
FB
125 return result;
126}
127
128static inline void* array_insert(array_t* array,unsigned int index,unsigned int count) {
129 if((array->next+count)*array->item_size>array->size) {
130 int increment=count*array->item_size;
131 array->pointer=realloc(array->pointer,array->size+increment);
132 if(!array->pointer)
133 return 0;
134 array->size+=increment;
135 }
136 memmove(array->pointer+(index+count)*array->item_size,
137 array->pointer+index*array->item_size,
138 (array->next-index)*array->item_size);
139 array->next+=count;
140 return array->pointer+index*array->item_size;
141}
142
143/* this performs a "roll", so that the element which was at index_from becomes
144 * index_to, but the order of all other elements is preserved. */
145static inline int array_roll(array_t* array,int index_to,int index_from,int count)
146{
147 char* buf;
148 char* from;
149 char* to;
150 int is;
151
152 if(!array ||
153 index_to<0 || index_to>=array->next ||
154 index_from<0 || index_from>=array->next)
155 return -1;
3b46e624 156
de167e41
FB
157 if(index_to==index_from)
158 return 0;
159
160 is=array->item_size;
161 from=array->pointer+index_from*is;
162 to=array->pointer+index_to*is;
163 buf=malloc(is*count);
164 memcpy(buf,from,is*count);
165
166 if(index_to<index_from)
167 memmove(to+is*count,to,from-to);
168 else
169 memmove(from,from+is*count,to-from);
3b46e624 170
de167e41
FB
171 memcpy(to,buf,is*count);
172
173 free(buf);
174
175 return 0;
176}
177
a046433a 178inline int array_remove_slice(array_t* array,int index, int count)
de167e41 179{
a046433a
FB
180 assert(index >=0);
181 assert(count > 0);
182 assert(index + count <= array->next);
183 if(array_roll(array,array->next-1,index,count))
de167e41 184 return -1;
a046433a 185 array->next -= count;
de167e41
FB
186 return 0;
187}
188
a046433a
FB
189int array_remove(array_t* array,int index)
190{
191 return array_remove_slice(array, index, 1);
192}
193
194/* return the index for a given member */
195int array_index(array_t* array, void* pointer)
196{
197 size_t offset = (char*)pointer - array->pointer;
198 assert(offset >= 0);
199 assert((offset % array->item_size) == 0);
200 assert(offset/array->item_size < array->next);
201 return offset/array->item_size;
202}
203
de167e41
FB
204/* These structures are used to fake a disk and the VFAT filesystem.
205 * For this reason we need to use __attribute__((packed)). */
206
207typedef struct bootsector_t {
208 uint8_t jump[3];
209 uint8_t name[8];
210 uint16_t sector_size;
211 uint8_t sectors_per_cluster;
212 uint16_t reserved_sectors;
213 uint8_t number_of_fats;
214 uint16_t root_entries;
a046433a 215 uint16_t total_sectors16;
de167e41
FB
216 uint8_t media_type;
217 uint16_t sectors_per_fat;
218 uint16_t sectors_per_track;
219 uint16_t number_of_heads;
220 uint32_t hidden_sectors;
221 uint32_t total_sectors;
222 union {
223 struct {
224 uint8_t drive_number;
225 uint8_t current_head;
226 uint8_t signature;
227 uint32_t id;
228 uint8_t volume_label[11];
229 } __attribute__((packed)) fat16;
230 struct {
231 uint32_t sectors_per_fat;
232 uint16_t flags;
233 uint8_t major,minor;
234 uint32_t first_cluster_of_root_directory;
235 uint16_t info_sector;
236 uint16_t backup_boot_sector;
237 uint16_t ignored;
238 } __attribute__((packed)) fat32;
239 } u;
240 uint8_t fat_type[8];
241 uint8_t ignored[0x1c0];
242 uint8_t magic[2];
243} __attribute__((packed)) bootsector_t;
244
245typedef struct partition_t {
246 uint8_t attributes; /* 0x80 = bootable */
247 uint8_t start_head;
248 uint8_t start_sector;
249 uint8_t start_cylinder;
a046433a 250 uint8_t fs_type; /* 0x1 = FAT12, 0x6 = FAT16, 0xb = FAT32 */
de167e41
FB
251 uint8_t end_head;
252 uint8_t end_sector;
253 uint8_t end_cylinder;
254 uint32_t start_sector_long;
255 uint32_t end_sector_long;
256} __attribute__((packed)) partition_t;
257
258typedef struct mbr_t {
259 uint8_t ignored[0x1be];
260 partition_t partition[4];
261 uint8_t magic[2];
262} __attribute__((packed)) mbr_t;
263
264typedef struct direntry_t {
265 uint8_t name[8];
266 uint8_t extension[3];
267 uint8_t attributes;
268 uint8_t reserved[2];
269 uint16_t ctime;
270 uint16_t cdate;
271 uint16_t adate;
272 uint16_t begin_hi;
273 uint16_t mtime;
274 uint16_t mdate;
275 uint16_t begin;
276 uint32_t size;
277} __attribute__((packed)) direntry_t;
278
279/* this structure are used to transparently access the files */
280
281typedef struct mapping_t {
a046433a
FB
282 /* begin is the first cluster, end is the last+1 */
283 uint32_t begin,end;
de167e41
FB
284 /* as s->directory is growable, no pointer may be used here */
285 unsigned int dir_index;
a046433a
FB
286 /* the clusters of a file may be in any order; this points to the first */
287 int first_mapping_index;
288 union {
289 /* offset is
290 * - the offset in the file (in clusters) for a file, or
291 * - the next cluster of the directory for a directory, and
292 * - the address of the buffer for a faked entry
293 */
294 struct {
295 uint32_t offset;
296 } file;
297 struct {
298 int parent_mapping_index;
299 int first_dir_index;
300 } dir;
301 } info;
302 /* path contains the full path, i.e. it always starts with s->path */
303 char* path;
304
305 enum { MODE_UNDEFINED = 0, MODE_NORMAL = 1, MODE_MODIFIED = 2,
306 MODE_DIRECTORY = 4, MODE_FAKED = 8,
307 MODE_DELETED = 16, MODE_RENAMED = 32 } mode;
308 int read_only;
de167e41
FB
309} mapping_t;
310
a046433a
FB
311#ifdef DEBUG
312static void print_direntry(const struct direntry_t*);
313static void print_mapping(const struct mapping_t* mapping);
314#endif
de167e41
FB
315
316/* here begins the real VVFAT driver */
317
318typedef struct BDRVVVFATState {
a046433a 319 BlockDriverState* bs; /* pointer to parent */
de167e41
FB
320 unsigned int first_sectors_number; /* 1 for a single partition, 0x40 for a disk with partition table */
321 unsigned char first_sectors[0x40*0x200];
3b46e624 322
de167e41
FB
323 int fat_type; /* 16 or 32 */
324 array_t fat,directory,mapping;
3b46e624 325
de167e41
FB
326 unsigned int cluster_size;
327 unsigned int sectors_per_cluster;
328 unsigned int sectors_per_fat;
329 unsigned int sectors_of_root_directory;
a046433a 330 uint32_t last_cluster_of_root_directory;
de167e41
FB
331 unsigned int faked_sectors; /* how many sectors are faked before file data */
332 uint32_t sector_count; /* total number of sectors of the partition */
333 uint32_t cluster_count; /* total number of clusters of this partition */
de167e41 334 uint32_t max_fat_value;
3b46e624 335
de167e41 336 int current_fd;
de167e41 337 mapping_t* current_mapping;
a046433a
FB
338 unsigned char* cluster; /* points to current cluster */
339 unsigned char* cluster_buffer; /* points to a buffer to hold temp data */
de167e41
FB
340 unsigned int current_cluster;
341
342 /* write support */
a046433a
FB
343 BlockDriverState* write_target;
344 char* qcow_filename;
345 BlockDriverState* qcow;
346 void* fat2;
347 char* used_clusters;
348 array_t commits;
349 const char* path;
350 int downcase_short_names;
de167e41
FB
351} BDRVVVFATState;
352
353
de167e41
FB
354static void init_mbr(BDRVVVFATState* s)
355{
356 /* TODO: if the files mbr.img and bootsect.img exist, use them */
357 mbr_t* real_mbr=(mbr_t*)s->first_sectors;
358 partition_t* partition=&(real_mbr->partition[0]);
359
360 memset(s->first_sectors,0,512);
3b46e624 361
de167e41
FB
362 partition->attributes=0x80; /* bootable */
363 partition->start_head=1;
364 partition->start_sector=1;
365 partition->start_cylinder=0;
a046433a
FB
366 /* FAT12/FAT16/FAT32 */
367 partition->fs_type=(s->fat_type==12?0x1:s->fat_type==16?0x6:0xb);
368 partition->end_head=s->bs->heads-1;
de167e41
FB
369 partition->end_sector=0xff; /* end sector & upper 2 bits of cylinder */;
370 partition->end_cylinder=0xff; /* lower 8 bits of end cylinder */;
a046433a 371 partition->start_sector_long=cpu_to_le32(s->bs->secs);
de167e41
FB
372 partition->end_sector_long=cpu_to_le32(s->sector_count);
373
374 real_mbr->magic[0]=0x55; real_mbr->magic[1]=0xaa;
375}
376
a046433a
FB
377/* direntry functions */
378
de167e41
FB
379/* dest is assumed to hold 258 bytes, and pads with 0xffff up to next multiple of 26 */
380static inline int short2long_name(unsigned char* dest,const char* src)
381{
382 int i;
383 for(i=0;i<129 && src[i];i++) {
384 dest[2*i]=src[i];
385 dest[2*i+1]=0;
386 }
387 dest[2*i]=dest[2*i+1]=0;
388 for(i=2*i+2;(i%26);i++)
389 dest[i]=0xff;
390 return i;
391}
392
393static inline direntry_t* create_long_filename(BDRVVVFATState* s,const char* filename)
394{
395 char buffer[258];
396 int length=short2long_name(buffer,filename),
397 number_of_entries=(length+25)/26,i;
398 direntry_t* entry;
399
400 for(i=0;i<number_of_entries;i++) {
401 entry=array_get_next(&(s->directory));
402 entry->attributes=0xf;
403 entry->reserved[0]=0;
404 entry->begin=0;
405 entry->name[0]=(number_of_entries-i)|(i==0?0x40:0);
406 }
407 for(i=0;i<length;i++) {
408 int offset=(i%26);
409 if(offset<10) offset=1+offset;
410 else if(offset<22) offset=14+offset-10;
411 else offset=28+offset-22;
412 entry=array_get(&(s->directory),s->directory.next-1-(i/26));
413 entry->name[offset]=buffer[i];
414 }
415 return array_get(&(s->directory),s->directory.next-number_of_entries);
416}
417
a046433a
FB
418static char is_free(const direntry_t* direntry)
419{
420 /* return direntry->name[0]==0 ; */
421 return direntry->attributes == 0 || direntry->name[0]==0xe5;
422}
423
424static char is_volume_label(const direntry_t* direntry)
425{
426 return direntry->attributes == 0x28;
427}
428
429static char is_long_name(const direntry_t* direntry)
430{
431 return direntry->attributes == 0xf;
432}
433
434static char is_short_name(const direntry_t* direntry)
435{
436 return !is_volume_label(direntry) && !is_long_name(direntry)
437 && !is_free(direntry);
438}
439
440static char is_directory(const direntry_t* direntry)
441{
442 return direntry->attributes & 0x10 && direntry->name[0] != 0xe5;
443}
444
445static inline char is_dot(const direntry_t* direntry)
446{
447 return is_short_name(direntry) && direntry->name[0] == '.';
448}
449
450static char is_file(const direntry_t* direntry)
451{
452 return is_short_name(direntry) && !is_directory(direntry);
453}
454
455static inline uint32_t begin_of_direntry(const direntry_t* direntry)
456{
457 return le16_to_cpu(direntry->begin)|(le16_to_cpu(direntry->begin_hi)<<16);
458}
459
460static inline uint32_t filesize_of_direntry(const direntry_t* direntry)
461{
462 return le32_to_cpu(direntry->size);
463}
464
465static void set_begin_of_direntry(direntry_t* direntry, uint32_t begin)
466{
467 direntry->begin = cpu_to_le16(begin & 0xffff);
468 direntry->begin_hi = cpu_to_le16((begin >> 16) & 0xffff);
469}
470
de167e41
FB
471/* fat functions */
472
a046433a 473static inline uint8_t fat_chksum(const direntry_t* entry)
de167e41
FB
474{
475 uint8_t chksum=0;
476 int i;
477
478 for(i=0;i<11;i++)
479 chksum=(((chksum&0xfe)>>1)|((chksum&0x01)?0x80:0))
480 +(unsigned char)entry->name[i];
3b46e624 481
de167e41
FB
482 return chksum;
483}
484
485/* if return_time==0, this returns the fat_date, else the fat_time */
486static uint16_t fat_datetime(time_t time,int return_time) {
487 struct tm* t;
488#ifdef _WIN32
489 t=localtime(&time); /* this is not thread safe */
490#else
491 struct tm t1;
492 t=&t1;
493 localtime_r(&time,t);
494#endif
495 if(return_time)
496 return cpu_to_le16((t->tm_sec/2)|(t->tm_min<<5)|(t->tm_hour<<11));
497 return cpu_to_le16((t->tm_mday)|((t->tm_mon+1)<<5)|((t->tm_year-80)<<9));
498}
499
500static inline void fat_set(BDRVVVFATState* s,unsigned int cluster,uint32_t value)
501{
a046433a
FB
502 if(s->fat_type==32) {
503 uint32_t* entry=array_get(&(s->fat),cluster);
504 *entry=cpu_to_le32(value);
de167e41
FB
505 } else if(s->fat_type==16) {
506 uint16_t* entry=array_get(&(s->fat),cluster);
507 *entry=cpu_to_le16(value&0xffff);
508 } else {
a046433a
FB
509 int offset = (cluster*3/2);
510 unsigned char* p = array_get(&(s->fat), offset);
511 switch (cluster&1) {
512 case 0:
513 p[0] = value&0xff;
514 p[1] = (p[1]&0xf0) | ((value>>8)&0xf);
515 break;
516 case 1:
517 p[0] = (p[0]&0xf) | ((value&0xf)<<4);
518 p[1] = (value>>4);
519 break;
520 }
de167e41
FB
521 }
522}
523
524static inline uint32_t fat_get(BDRVVVFATState* s,unsigned int cluster)
525{
a046433a
FB
526 if(s->fat_type==32) {
527 uint32_t* entry=array_get(&(s->fat),cluster);
528 return le32_to_cpu(*entry);
de167e41
FB
529 } else if(s->fat_type==16) {
530 uint16_t* entry=array_get(&(s->fat),cluster);
531 return le16_to_cpu(*entry);
532 } else {
a046433a
FB
533 const uint8_t* x=s->fat.pointer+cluster*3/2;
534 return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
de167e41
FB
535 }
536}
537
538static inline int fat_eof(BDRVVVFATState* s,uint32_t fat_entry)
539{
540 if(fat_entry>s->max_fat_value-8)
541 return -1;
542 return 0;
543}
544
545static inline void init_fat(BDRVVVFATState* s)
546{
a046433a
FB
547 if (s->fat_type == 12) {
548 array_init(&(s->fat),1);
549 array_ensure_allocated(&(s->fat),
550 s->sectors_per_fat * 0x200 * 3 / 2 - 1);
551 } else {
552 array_init(&(s->fat),(s->fat_type==32?4:2));
553 array_ensure_allocated(&(s->fat),
554 s->sectors_per_fat * 0x200 / s->fat.item_size - 1);
555 }
de167e41 556 memset(s->fat.pointer,0,s->fat.size);
3b46e624 557
de167e41
FB
558 switch(s->fat_type) {
559 case 12: s->max_fat_value=0xfff; break;
560 case 16: s->max_fat_value=0xffff; break;
a046433a 561 case 32: s->max_fat_value=0x0fffffff; break;
de167e41
FB
562 default: s->max_fat_value=0; /* error... */
563 }
564
565}
566
a046433a
FB
567/* TODO: in create_short_filename, 0xe5->0x05 is not yet handled! */
568/* TODO: in parse_short_filename, 0x05->0xe5 is not yet handled! */
569static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,
570 unsigned int directory_start, const char* filename, int is_dot)
de167e41 571{
a046433a 572 int i,j,long_index=s->directory.next;
de167e41
FB
573 direntry_t* entry=0;
574 direntry_t* entry_long=0;
575
576 if(is_dot) {
577 entry=array_get_next(&(s->directory));
578 memset(entry->name,0x20,11);
579 memcpy(entry->name,filename,strlen(filename));
580 return entry;
581 }
3b46e624 582
de167e41 583 entry_long=create_long_filename(s,filename);
3b46e624 584
5fafdf24 585 i = strlen(filename);
a046433a
FB
586 for(j = i - 1; j>0 && filename[j]!='.';j--);
587 if (j > 0)
588 i = (j > 8 ? 8 : j);
589 else if (i > 8)
590 i = 8;
591
de167e41
FB
592 entry=array_get_next(&(s->directory));
593 memset(entry->name,0x20,11);
594 strncpy(entry->name,filename,i);
3b46e624 595
a046433a
FB
596 if(j > 0)
597 for (i = 0; i < 3 && filename[j+1+i]; i++)
598 entry->extension[i] = filename[j+1+i];
de167e41
FB
599
600 /* upcase & remove unwanted characters */
601 for(i=10;i>=0;i--) {
a046433a 602 if(i==10 || i==7) for(;i>0 && entry->name[i]==' ';i--);
de167e41 603 if(entry->name[i]<=' ' || entry->name[i]>0x7f
a046433a 604 || strchr(".*?<>|\":/\\[];,+='",entry->name[i]))
de167e41
FB
605 entry->name[i]='_';
606 else if(entry->name[i]>='a' && entry->name[i]<='z')
607 entry->name[i]+='A'-'a';
608 }
609
610 /* mangle duplicates */
611 while(1) {
612 direntry_t* entry1=array_get(&(s->directory),directory_start);
613 int j;
614
615 for(;entry1<entry;entry1++)
a046433a 616 if(!is_long_name(entry1) && !memcmp(entry1->name,entry->name,11))
de167e41
FB
617 break; /* found dupe */
618 if(entry1==entry) /* no dupe found */
619 break;
620
5fafdf24 621 /* use all 8 characters of name */
de167e41
FB
622 if(entry->name[7]==' ') {
623 int j;
624 for(j=6;j>0 && entry->name[j]==' ';j--)
625 entry->name[j]='~';
626 }
627
628 /* increment number */
629 for(j=7;j>0 && entry->name[j]=='9';j--)
630 entry->name[j]='0';
631 if(j>0) {
632 if(entry->name[j]<'0' || entry->name[j]>'9')
633 entry->name[j]='0';
634 else
635 entry->name[j]++;
636 }
637 }
638
639 /* calculate checksum; propagate to long name */
640 if(entry_long) {
641 uint8_t chksum=fat_chksum(entry);
642
643 /* calculate anew, because realloc could have taken place */
644 entry_long=array_get(&(s->directory),long_index);
a046433a 645 while(entry_long<entry && is_long_name(entry_long)) {
de167e41
FB
646 entry_long->reserved[1]=chksum;
647 entry_long++;
648 }
649 }
650
651 return entry;
652}
653
a046433a
FB
654/*
655 * Read a directory. (the index of the corresponding mapping must be passed).
656 */
657static int read_directory(BDRVVVFATState* s, int mapping_index)
de167e41 658{
a046433a
FB
659 mapping_t* mapping = array_get(&(s->mapping), mapping_index);
660 direntry_t* direntry;
661 const char* dirname = mapping->path;
662 int first_cluster = mapping->begin;
663 int parent_index = mapping->info.dir.parent_mapping_index;
664 mapping_t* parent_mapping = (mapping_t*)
665 (parent_index >= 0 ? array_get(&(s->mapping), parent_index) : 0);
666 int first_cluster_of_parent = parent_mapping ? parent_mapping->begin : -1;
de167e41
FB
667
668 DIR* dir=opendir(dirname);
669 struct dirent* entry;
de167e41
FB
670 int i;
671
a046433a
FB
672 assert(mapping->mode & MODE_DIRECTORY);
673
674 if(!dir) {
675 mapping->end = mapping->begin;
de167e41 676 return -1;
a046433a 677 }
3b46e624 678
a046433a
FB
679 i = mapping->info.dir.first_dir_index =
680 first_cluster == 0 ? 0 : s->directory.next;
681
5fafdf24 682 /* actually read the directory, and allocate the mappings */
de167e41
FB
683 while((entry=readdir(dir))) {
684 unsigned int length=strlen(dirname)+2+strlen(entry->d_name);
685 char* buffer;
686 direntry_t* direntry;
a046433a 687 struct stat st;
de167e41
FB
688 int is_dot=!strcmp(entry->d_name,".");
689 int is_dotdot=!strcmp(entry->d_name,"..");
690
a046433a 691 if(first_cluster == 0 && (is_dotdot || is_dot))
de167e41 692 continue;
5fafdf24 693
de167e41 694 buffer=(char*)malloc(length);
a046433a 695 assert(buffer);
de167e41
FB
696 snprintf(buffer,length,"%s/%s",dirname,entry->d_name);
697
698 if(stat(buffer,&st)<0) {
699 free(buffer);
700 continue;
701 }
702
703 /* create directory entry for this file */
a046433a
FB
704 direntry=create_short_and_long_name(s, i, entry->d_name,
705 is_dot || is_dotdot);
de167e41
FB
706 direntry->attributes=(S_ISDIR(st.st_mode)?0x10:0x20);
707 direntry->reserved[0]=direntry->reserved[1]=0;
708 direntry->ctime=fat_datetime(st.st_ctime,1);
709 direntry->cdate=fat_datetime(st.st_ctime,0);
710 direntry->adate=fat_datetime(st.st_atime,0);
711 direntry->begin_hi=0;
712 direntry->mtime=fat_datetime(st.st_mtime,1);
713 direntry->mdate=fat_datetime(st.st_mtime,0);
714 if(is_dotdot)
a046433a 715 set_begin_of_direntry(direntry, first_cluster_of_parent);
de167e41 716 else if(is_dot)
a046433a 717 set_begin_of_direntry(direntry, first_cluster);
de167e41 718 else
a046433a
FB
719 direntry->begin=0; /* do that later */
720 if (st.st_size > 0x7fffffff) {
721 fprintf(stderr, "File %s is larger than 2GB\n", buffer);
722 free(buffer);
723 return -2;
724 }
725 direntry->size=cpu_to_le32(S_ISDIR(st.st_mode)?0:st.st_size);
de167e41
FB
726
727 /* create mapping for this file */
a046433a
FB
728 if(!is_dot && !is_dotdot && (S_ISDIR(st.st_mode) || st.st_size)) {
729 s->current_mapping=(mapping_t*)array_get_next(&(s->mapping));
de167e41
FB
730 s->current_mapping->begin=0;
731 s->current_mapping->end=st.st_size;
a046433a
FB
732 /*
733 * we get the direntry of the most recent direntry, which
734 * contains the short name and all the relevant information.
735 */
de167e41 736 s->current_mapping->dir_index=s->directory.next-1;
a046433a
FB
737 s->current_mapping->first_mapping_index = -1;
738 if (S_ISDIR(st.st_mode)) {
739 s->current_mapping->mode = MODE_DIRECTORY;
740 s->current_mapping->info.dir.parent_mapping_index =
741 mapping_index;
742 } else {
743 s->current_mapping->mode = MODE_UNDEFINED;
744 s->current_mapping->info.file.offset = 0;
745 }
746 s->current_mapping->path=buffer;
747 s->current_mapping->read_only =
748 (st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0;
de167e41
FB
749 }
750 }
751 closedir(dir);
752
753 /* fill with zeroes up to the end of the cluster */
754 while(s->directory.next%(0x10*s->sectors_per_cluster)) {
755 direntry_t* direntry=array_get_next(&(s->directory));
756 memset(direntry,0,sizeof(direntry_t));
757 }
758
a046433a
FB
759/* TODO: if there are more entries, bootsector has to be adjusted! */
760#define ROOT_ENTRIES (0x02 * 0x10 * s->sectors_per_cluster)
761 if (mapping_index == 0 && s->directory.next < ROOT_ENTRIES) {
762 /* root directory */
763 int cur = s->directory.next;
764 array_ensure_allocated(&(s->directory), ROOT_ENTRIES - 1);
765 memset(array_get(&(s->directory), cur), 0,
766 (ROOT_ENTRIES - cur) * sizeof(direntry_t));
de167e41 767 }
5fafdf24 768
a046433a
FB
769 /* reget the mapping, since s->mapping was possibly realloc()ed */
770 mapping = (mapping_t*)array_get(&(s->mapping), mapping_index);
771 first_cluster += (s->directory.next - mapping->info.dir.first_dir_index)
772 * 0x20 / s->cluster_size;
773 mapping->end = first_cluster;
774
775 direntry = (direntry_t*)array_get(&(s->directory), mapping->dir_index);
776 set_begin_of_direntry(direntry, mapping->begin);
3b46e624 777
a046433a
FB
778 return 0;
779}
de167e41 780
a046433a
FB
781static inline uint32_t sector2cluster(BDRVVVFATState* s,off_t sector_num)
782{
783 return (sector_num-s->faked_sectors)/s->sectors_per_cluster;
784}
de167e41 785
a046433a
FB
786static inline off_t cluster2sector(BDRVVVFATState* s, uint32_t cluster_num)
787{
788 return s->faked_sectors + s->sectors_per_cluster * cluster_num;
789}
de167e41 790
a046433a
FB
791static inline uint32_t sector_offset_in_cluster(BDRVVVFATState* s,off_t sector_num)
792{
793 return (sector_num-s->first_sectors_number-2*s->sectors_per_fat)%s->sectors_per_cluster;
794}
de167e41 795
a046433a
FB
796#ifdef DBG
797static direntry_t* get_direntry_for_mapping(BDRVVVFATState* s,mapping_t* mapping)
798{
799 if(mapping->mode==MODE_UNDEFINED)
800 return 0;
801 return (direntry_t*)(s->directory.pointer+sizeof(direntry_t)*mapping->dir_index);
de167e41 802}
a046433a 803#endif
de167e41 804
a046433a
FB
805static int init_directories(BDRVVVFATState* s,
806 const char* dirname)
de167e41 807{
a046433a
FB
808 bootsector_t* bootsector;
809 mapping_t* mapping;
de167e41
FB
810 unsigned int i;
811 unsigned int cluster;
812
813 memset(&(s->first_sectors[0]),0,0x40*0x200);
814
de167e41 815 s->cluster_size=s->sectors_per_cluster*0x200;
a046433a
FB
816 s->cluster_buffer=malloc(s->cluster_size);
817 assert(s->cluster_buffer);
818
819 /*
820 * The formula: sc = spf+1+spf*spc*(512*8/fat_type),
821 * where sc is sector_count,
822 * spf is sectors_per_fat,
823 * spc is sectors_per_clusters, and
824 * fat_type = 12, 16 or 32.
825 */
826 i = 1+s->sectors_per_cluster*0x200*8/s->fat_type;
827 s->sectors_per_fat=(s->sector_count+i)/i; /* round up */
3b46e624 828
de167e41
FB
829 array_init(&(s->mapping),sizeof(mapping_t));
830 array_init(&(s->directory),sizeof(direntry_t));
de167e41
FB
831
832 /* add volume label */
833 {
834 direntry_t* entry=array_get_next(&(s->directory));
835 entry->attributes=0x28; /* archive | volume label */
836 snprintf(entry->name,11,"QEMU VVFAT");
837 }
838
de167e41
FB
839 /* Now build FAT, and write back information into directory */
840 init_fat(s);
841
a046433a
FB
842 s->faked_sectors=s->first_sectors_number+s->sectors_per_fat*2;
843 s->cluster_count=sector2cluster(s, s->sector_count);
844
845 mapping = array_get_next(&(s->mapping));
846 mapping->begin = 0;
847 mapping->dir_index = 0;
848 mapping->info.dir.parent_mapping_index = -1;
849 mapping->first_mapping_index = -1;
850 mapping->path = strdup(dirname);
851 i = strlen(mapping->path);
852 if (i > 0 && mapping->path[i - 1] == '/')
853 mapping->path[i - 1] = '\0';
854 mapping->mode = MODE_DIRECTORY;
855 mapping->read_only = 0;
856 s->path = mapping->path;
857
858 for (i = 0, cluster = 0; i < s->mapping.next; i++) {
859 int j;
5fafdf24 860 /* MS-DOS expects the FAT to be 0 for the root directory
a046433a
FB
861 * (except for the media byte). */
862 /* LATER TODO: still true for FAT32? */
863 int fix_fat = (i != 0);
864 mapping = array_get(&(s->mapping), i);
865
866 if (mapping->mode & MODE_DIRECTORY) {
867 mapping->begin = cluster;
868 if(read_directory(s, i)) {
869 fprintf(stderr, "Could not read directory %s\n",
870 mapping->path);
de167e41
FB
871 return -1;
872 }
a046433a
FB
873 mapping = array_get(&(s->mapping), i);
874 } else {
875 assert(mapping->mode == MODE_UNDEFINED);
de167e41 876 mapping->mode=MODE_NORMAL;
a046433a
FB
877 mapping->begin = cluster;
878 if (mapping->end > 0) {
879 direntry_t* direntry = array_get(&(s->directory),
880 mapping->dir_index);
881
882 mapping->end = cluster + 1 + (mapping->end-1)/s->cluster_size;
883 set_begin_of_direntry(direntry, mapping->begin);
884 } else {
885 mapping->end = cluster + 1;
886 fix_fat = 0;
de167e41 887 }
a046433a
FB
888 }
889
890 assert(mapping->begin < mapping->end);
891
892 /* fix fat for entry */
893 if (fix_fat) {
894 for(j = mapping->begin; j < mapping->end - 1; j++)
895 fat_set(s, j, j+1);
896 fat_set(s, mapping->end - 1, s->max_fat_value);
897 }
898
899 /* next free cluster */
900 cluster = mapping->end;
de167e41 901
a046433a
FB
902 if(cluster > s->cluster_count) {
903 fprintf(stderr,"Directory does not fit in FAT%d\n",s->fat_type);
904 return -1;
de167e41
FB
905 }
906 }
907
a046433a
FB
908 mapping = array_get(&(s->mapping), 0);
909 s->sectors_of_root_directory = mapping->end * s->sectors_per_cluster;
910 s->last_cluster_of_root_directory = mapping->end;
911
912 /* the FAT signature */
913 fat_set(s,0,s->max_fat_value);
914 fat_set(s,1,s->max_fat_value);
de167e41 915
a046433a
FB
916 s->current_mapping = NULL;
917
918 bootsector=(bootsector_t*)(s->first_sectors+(s->first_sectors_number-1)*0x200);
de167e41
FB
919 bootsector->jump[0]=0xeb;
920 bootsector->jump[1]=0x3e;
921 bootsector->jump[2]=0x90;
922 memcpy(bootsector->name,"QEMU ",8);
923 bootsector->sector_size=cpu_to_le16(0x200);
924 bootsector->sectors_per_cluster=s->sectors_per_cluster;
925 bootsector->reserved_sectors=cpu_to_le16(1);
926 bootsector->number_of_fats=0x2; /* number of FATs */
927 bootsector->root_entries=cpu_to_le16(s->sectors_of_root_directory*0x10);
a046433a
FB
928 bootsector->total_sectors16=s->sector_count>0xffff?0:cpu_to_le16(s->sector_count);
929 bootsector->media_type=(s->fat_type!=12?0xf8:s->sector_count==5760?0xf9:0xf8); /* media descriptor */
930 s->fat.pointer[0] = bootsector->media_type;
de167e41 931 bootsector->sectors_per_fat=cpu_to_le16(s->sectors_per_fat);
a046433a
FB
932 bootsector->sectors_per_track=cpu_to_le16(s->bs->secs);
933 bootsector->number_of_heads=cpu_to_le16(s->bs->heads);
de167e41 934 bootsector->hidden_sectors=cpu_to_le32(s->first_sectors_number==1?0:0x3f);
a046433a 935 bootsector->total_sectors=cpu_to_le32(s->sector_count>0xffff?s->sector_count:0);
de167e41 936
a046433a
FB
937 /* LATER TODO: if FAT32, this is wrong */
938 bootsector->u.fat16.drive_number=s->fat_type==12?0:0x80; /* assume this is hda (TODO) */
de167e41
FB
939 bootsector->u.fat16.current_head=0;
940 bootsector->u.fat16.signature=0x29;
941 bootsector->u.fat16.id=cpu_to_le32(0xfabe1afd);
942
943 memcpy(bootsector->u.fat16.volume_label,"QEMU VVFAT ",11);
944 memcpy(bootsector->fat_type,(s->fat_type==12?"FAT12 ":s->fat_type==16?"FAT16 ":"FAT32 "),8);
945 bootsector->magic[0]=0x55; bootsector->magic[1]=0xaa;
946
947 return 0;
948}
949
83f64091 950#ifdef DEBUG
a046433a 951static BDRVVVFATState *vvv = NULL;
83f64091 952#endif
a046433a
FB
953
954static int enable_write_target(BDRVVVFATState *s);
955static int is_consistent(BDRVVVFATState *s);
956
83f64091 957static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
de167e41
FB
958{
959 BDRVVVFATState *s = bs->opaque;
a046433a 960 int floppy = 0;
de167e41
FB
961 int i;
962
83f64091 963#ifdef DEBUG
a046433a 964 vvv = s;
83f64091 965#endif
a046433a
FB
966
967DLOG(if (stderr == NULL) {
968 stderr = fopen("vvfat.log", "a");
969 setbuf(stderr, NULL);
970})
971
972 s->bs = bs;
973
de167e41 974 s->fat_type=16;
a046433a 975 /* LATER TODO: if FAT32, adjust */
de167e41 976 s->sector_count=0xec04f;
a046433a
FB
977 s->sectors_per_cluster=0x10;
978 /* LATER TODO: this could be wrong for FAT32 */
979 bs->cyls=1023; bs->heads=15; bs->secs=63;
de167e41
FB
980
981 s->current_cluster=0xffffffff;
de167e41 982
de167e41 983 s->first_sectors_number=0x40;
a046433a
FB
984 /* read only is the default for safety */
985 bs->read_only = 1;
986 s->qcow = s->write_target = NULL;
987 s->qcow_filename = NULL;
988 s->fat2 = NULL;
989 s->downcase_short_names = 1;
3b46e624 990
a046433a
FB
991 if (!strstart(dirname, "fat:", NULL))
992 return -1;
993
994 if (strstr(dirname, ":rw:")) {
995 if (enable_write_target(s))
996 return -1;
997 bs->read_only = 0;
998 }
999
1000 if (strstr(dirname, ":floppy:")) {
1001 floppy = 1;
1002 s->fat_type = 12;
1003 s->first_sectors_number = 1;
1004 s->sectors_per_cluster=2;
1005 bs->cyls = 80; bs->heads = 2; bs->secs = 36;
1006 }
1007
1008 if (strstr(dirname, ":32:")) {
1009 fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. You are welcome to do so!\n");
1010 s->fat_type = 32;
1011 } else if (strstr(dirname, ":16:")) {
1012 s->fat_type = 16;
1013 } else if (strstr(dirname, ":12:")) {
1014 s->fat_type = 12;
1015 s->sector_count=2880;
de167e41 1016 }
a046433a
FB
1017
1018 i = strrchr(dirname, ':') - dirname;
1019 assert(i >= 3);
1020 if (dirname[i-2] == ':' && isalpha(dirname[i-1]))
1021 /* workaround for DOS drive names */
1022 dirname += i-1;
1023 else
1024 dirname += i+1;
1025
1026 bs->total_sectors=bs->cyls*bs->heads*bs->secs;
1027 if (s->sector_count > bs->total_sectors)
1028 s->sector_count = bs->total_sectors;
1029 if(init_directories(s, dirname))
de167e41
FB
1030 return -1;
1031
1032 if(s->first_sectors_number==0x40)
1033 init_mbr(s);
1034
a046433a
FB
1035 /* for some reason or other, MS-DOS does not like to know about CHS... */
1036 if (floppy)
1037 bs->heads = bs->cyls = bs->secs = 0;
1038
1039 // assert(is_consistent(s));
de167e41
FB
1040 return 0;
1041}
1042
1043static inline void vvfat_close_current_file(BDRVVVFATState *s)
1044{
1045 if(s->current_mapping) {
a046433a
FB
1046 s->current_mapping = NULL;
1047 if (s->current_fd) {
1048 close(s->current_fd);
1049 s->current_fd = 0;
1050 }
de167e41 1051 }
a046433a 1052 s->current_cluster = -1;
de167e41
FB
1053}
1054
1055/* mappings between index1 and index2-1 are supposed to be ordered
1056 * return value is the index of the last mapping for which end>cluster_num
1057 */
1058static inline int find_mapping_for_cluster_aux(BDRVVVFATState* s,int cluster_num,int index1,int index2)
1059{
1060 int index3=index1+1;
de167e41
FB
1061 while(1) {
1062 mapping_t* mapping;
1063 index3=(index1+index2)/2;
1064 mapping=array_get(&(s->mapping),index3);
a046433a
FB
1065 assert(mapping->begin < mapping->end);
1066 if(mapping->begin>=cluster_num) {
de167e41
FB
1067 assert(index2!=index3 || index2==0);
1068 if(index2==index3)
a046433a 1069 return index1;
de167e41
FB
1070 index2=index3;
1071 } else {
1072 if(index1==index3)
a046433a 1073 return mapping->end<=cluster_num ? index2 : index1;
de167e41
FB
1074 index1=index3;
1075 }
1076 assert(index1<=index2);
a046433a
FB
1077 DLOG(mapping=array_get(&(s->mapping),index1);
1078 assert(mapping->begin<=cluster_num);
5fafdf24 1079 assert(index2 >= s->mapping.next ||
a046433a
FB
1080 ((mapping = array_get(&(s->mapping),index2)) &&
1081 mapping->end>cluster_num)));
de167e41
FB
1082 }
1083}
1084
1085static inline mapping_t* find_mapping_for_cluster(BDRVVVFATState* s,int cluster_num)
1086{
1087 int index=find_mapping_for_cluster_aux(s,cluster_num,0,s->mapping.next);
1088 mapping_t* mapping;
1089 if(index>=s->mapping.next)
1090 return 0;
1091 mapping=array_get(&(s->mapping),index);
1092 if(mapping->begin>cluster_num)
1093 return 0;
a046433a 1094 assert(mapping->begin<=cluster_num && mapping->end>cluster_num);
de167e41
FB
1095 return mapping;
1096}
1097
a046433a
FB
1098/*
1099 * This function simply compares path == mapping->path. Since the mappings
1100 * are sorted by cluster, this is expensive: O(n).
1101 */
1102static inline mapping_t* find_mapping_for_path(BDRVVVFATState* s,
1103 const char* path)
1104{
1105 int i;
1106
1107 for (i = 0; i < s->mapping.next; i++) {
1108 mapping_t* mapping = array_get(&(s->mapping), i);
1109 if (mapping->first_mapping_index < 0 &&
1110 !strcmp(path, mapping->path))
1111 return mapping;
1112 }
1113
1114 return NULL;
1115}
1116
1117static int open_file(BDRVVVFATState* s,mapping_t* mapping)
de167e41
FB
1118{
1119 if(!mapping)
1120 return -1;
de167e41 1121 if(!s->current_mapping ||
a046433a 1122 strcmp(s->current_mapping->path,mapping->path)) {
de167e41 1123 /* open file */
a046433a 1124 int fd = open(mapping->path, O_RDONLY | O_BINARY | O_LARGEFILE);
de167e41
FB
1125 if(fd<0)
1126 return -1;
1127 vvfat_close_current_file(s);
1128 s->current_fd = fd;
de167e41
FB
1129 s->current_mapping = mapping;
1130 }
1131 return 0;
1132}
1133
1134static inline int read_cluster(BDRVVVFATState *s,int cluster_num)
1135{
1136 if(s->current_cluster != cluster_num) {
1137 int result=0;
1138 off_t offset;
a046433a 1139 assert(!s->current_mapping || s->current_fd || (s->current_mapping->mode & MODE_DIRECTORY));
de167e41
FB
1140 if(!s->current_mapping
1141 || s->current_mapping->begin>cluster_num
1142 || s->current_mapping->end<=cluster_num) {
1143 /* binary search of mappings for file */
1144 mapping_t* mapping=find_mapping_for_cluster(s,cluster_num);
a046433a
FB
1145
1146 assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
1147
1148 if (mapping && mapping->mode & MODE_DIRECTORY) {
1149 vvfat_close_current_file(s);
1150 s->current_mapping = mapping;
1151read_cluster_directory:
1152 offset = s->cluster_size*(cluster_num-s->current_mapping->begin);
1153 s->cluster = s->directory.pointer+offset
1154 + 0x20*s->current_mapping->info.dir.first_dir_index;
1155 assert(((s->cluster-(unsigned char*)s->directory.pointer)%s->cluster_size)==0);
1156 assert((char*)s->cluster+s->cluster_size <= s->directory.pointer+s->directory.next*s->directory.item_size);
1157 s->current_cluster = cluster_num;
1158 return 0;
1159 }
1160
1161 if(open_file(s,mapping))
de167e41 1162 return -2;
a046433a
FB
1163 } else if (s->current_mapping->mode & MODE_DIRECTORY)
1164 goto read_cluster_directory;
de167e41 1165
a046433a
FB
1166 assert(s->current_fd);
1167
1168 offset=s->cluster_size*(cluster_num-s->current_mapping->begin)+s->current_mapping->info.file.offset;
de167e41
FB
1169 if(lseek(s->current_fd, offset, SEEK_SET)!=offset)
1170 return -3;
a046433a 1171 s->cluster=s->cluster_buffer;
de167e41
FB
1172 result=read(s->current_fd,s->cluster,s->cluster_size);
1173 if(result<0) {
1174 s->current_cluster = -1;
1175 return -1;
1176 }
1177 s->current_cluster = cluster_num;
1178 }
1179 return 0;
1180}
1181
a046433a
FB
1182#ifdef DEBUG
1183static void hexdump(const void* address, uint32_t len)
de167e41 1184{
a046433a
FB
1185 const unsigned char* p = address;
1186 int i, j;
1187
1188 for (i = 0; i < len; i += 16) {
1189 for (j = 0; j < 16 && i + j < len; j++)
1190 fprintf(stderr, "%02x ", p[i + j]);
1191 for (; j < 16; j++)
1192 fprintf(stderr, " ");
1193 fprintf(stderr, " ");
1194 for (j = 0; j < 16 && i + j < len; j++)
1195 fprintf(stderr, "%c", (p[i + j] < ' ' || p[i + j] > 0x7f) ? '.' : p[i + j]);
1196 fprintf(stderr, "\n");
de167e41 1197 }
de167e41
FB
1198}
1199
a046433a 1200static void print_direntry(const direntry_t* direntry)
de167e41 1201{
a046433a
FB
1202 int j = 0;
1203 char buffer[1024];
1204
1205 fprintf(stderr, "direntry 0x%x: ", (int)direntry);
de167e41
FB
1206 if(!direntry)
1207 return;
a046433a 1208 if(is_long_name(direntry)) {
de167e41
FB
1209 unsigned char* c=(unsigned char*)direntry;
1210 int i;
1211 for(i=1;i<11 && c[i] && c[i]!=0xff;i+=2)
a046433a
FB
1212