Statistics
| Branch: | Revision:

root / block-vvfat.c @ 5efa9d5a

History | View | Annotate | Download (79.7 kB)

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__
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

    
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

    
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 */
95
static inline void* array_get(array_t* array,unsigned int index) {
96
    assert(index < array->next);
97
    return array->pointer + index * array->item_size;
98
}
99

    
100
static inline int array_ensure_allocated(array_t* array, int index)
101
{
102
    if((index + 1) * array->item_size > array->size) {
103
        int new_size = (index + 32) * array->item_size;
104
        array->pointer = 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

    
114
static inline void* array_get_next(array_t* array) {
115
    unsigned int next = array->next;
116
    void* result;
117

    
118
    if (array_ensure_allocated(array, next) < 0)
119
        return NULL;
120

    
121
    array->next = next + 1;
122
    result = array_get(array, next);
123

    
124
    return result;
125
}
126

    
127
static inline void* array_insert(array_t* array,unsigned int index,unsigned int count) {
128
    if((array->next+count)*array->item_size>array->size) {
129
        int increment=count*array->item_size;
130
        array->pointer=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. */
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

    
177
static inline int array_remove_slice(array_t* array,int index, int count)
178
{
179
    assert(index >=0);
180
    assert(count > 0);
181
    assert(index + count <= array->next);
182
    if(array_roll(array,array->next-1,index,count))
183
        return -1;
184
    array->next -= count;
185
    return 0;
186
}
187

    
188
static int array_remove(array_t* array,int index)
189
{
190
    return array_remove_slice(array, index, 1);
191
}
192

    
193
/* return the index for a given member */
194
static int array_index(array_t* array, void* pointer)
195
{
196
    size_t offset = (char*)pointer - array->pointer;
197
    assert((offset % array->item_size) == 0);
198
    assert(offset/array->item_size < array->next);
199
    return offset/array->item_size;
200
}
201

    
202
/* These structures are used to fake a disk and the VFAT filesystem.
203
 * For this reason we need to use __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
 */
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

    
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 */
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

    
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

    
453
static char is_free(const direntry_t* direntry)
454
{
455
    return direntry->name[0]==0xe5 || direntry->name[0]==0x00;
456
}
457

    
458
static char is_volume_label(const direntry_t* direntry)
459
{
460
    return direntry->attributes == 0x28;
461
}
462

    
463
static char is_long_name(const direntry_t* direntry)
464
{
465
    return direntry->attributes == 0xf;
466
}
467

    
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

    
474
static char is_directory(const direntry_t* direntry)
475
{
476
    return direntry->attributes & 0x10 && direntry->name[0] != 0xe5;
477
}
478

    
479
static inline char is_dot(const direntry_t* direntry)
480
{
481
    return is_short_name(direntry) && direntry->name[0] == '.';
482
}
483

    
484
static char is_file(const direntry_t* direntry)
485
{
486
    return is_short_name(direntry) && !is_directory(direntry);
487
}
488

    
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

    
494
static inline uint32_t filesize_of_direntry(const direntry_t* direntry)
495
{
496
    return le32_to_cpu(direntry->size);
497
}
498

    
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

    
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 */
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

    
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

    
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

    
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

    
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! */
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
 */
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

    
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

    
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

    
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
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

    
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

    
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

    
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
 */
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

    
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
 */
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

    
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

    
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
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

    
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

    
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

    
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

    
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

    
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

    
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

    
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

    
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

    
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 */
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 */
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

    
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

    
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

    
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
 */
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
 */
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 */
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

    
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 */
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

    
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

    
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

    
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

    
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
 */
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

    
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 */
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 */
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 */
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

    
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
 */
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

    
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
 */
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

    
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

    
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

    
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

    
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

    
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
    "vvfat_write_target", 0, NULL, NULL, NULL,
2766
    write_target_commit,
2767
    write_target_close,
2768
    NULL, NULL, NULL
2769
};
2770

    
2771
static int enable_write_target(BDRVVVFATState *s)
2772
{
2773
    int size = sector2cluster(s, s->sector_count);
2774
    s->used_clusters = calloc(size, 1);
2775

    
2776
    array_init(&(s->commits), sizeof(commit_t));
2777

    
2778
    s->qcow_filename = qemu_malloc(1024);
2779
    get_tmp_filename(s->qcow_filename, 1024);
2780
    if (bdrv_create(bdrv_find_format("qcow"),
2781
                s->qcow_filename, s->sector_count, "fat:", 0) < 0)
2782
        return -1;
2783
    s->qcow = bdrv_new("");
2784
    if (s->qcow == NULL || bdrv_open(s->qcow, s->qcow_filename, 0) < 0)
2785
        return -1;
2786

    
2787
#ifndef _WIN32
2788
    unlink(s->qcow_filename);
2789
#endif
2790

    
2791
    s->bs->backing_hd = calloc(sizeof(BlockDriverState), 1);
2792
    s->bs->backing_hd->drv = &vvfat_write_target;
2793
    s->bs->backing_hd->opaque = s;
2794

    
2795
    return 0;
2796
}
2797

    
2798
static void vvfat_close(BlockDriverState *bs)
2799
{
2800
    BDRVVVFATState *s = bs->opaque;
2801

    
2802
    vvfat_close_current_file(s);
2803
    array_free(&(s->fat));
2804
    array_free(&(s->directory));
2805
    array_free(&(s->mapping));
2806
    if(s->cluster_buffer)
2807
        free(s->cluster_buffer);
2808
}
2809

    
2810
static BlockDriver bdrv_vvfat = {
2811
    .format_name        = "vvfat",
2812
    .instance_size        = sizeof(BDRVVVFATState),
2813
    .bdrv_open                = vvfat_open,
2814
    .bdrv_read                = vvfat_read,
2815
    .bdrv_write                = vvfat_write,
2816
    .bdrv_close                = vvfat_close,
2817
    .bdrv_is_allocated        = vvfat_is_allocated,
2818
    .protocol_name        = "fat",
2819
};
2820

    
2821
static void bdrv_vvfat_init(void)
2822
{
2823
    bdrv_register(&bdrv_vvfat);
2824
}
2825

    
2826
block_init(bdrv_vvfat_init);
2827

    
2828
#ifdef DEBUG
2829
static void checkpoint(void) {
2830
    assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2);
2831
    check1(vvv);
2832
    check2(vvv);
2833
    assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY));
2834
#if 0
2835
    if (((direntry_t*)vvv->directory.pointer)[1].attributes != 0xf)
2836
        fprintf(stderr, "Nonono!\n");
2837
    mapping_t* mapping;
2838
    direntry_t* direntry;
2839
    assert(vvv->mapping.size >= vvv->mapping.item_size * vvv->mapping.next);
2840
    assert(vvv->directory.size >= vvv->directory.item_size * vvv->directory.next);
2841
    if (vvv->mapping.next<47)
2842
        return;
2843
    assert((mapping = array_get(&(vvv->mapping), 47)));
2844
    assert(mapping->dir_index < vvv->directory.next);
2845
    direntry = array_get(&(vvv->directory), mapping->dir_index);
2846
    assert(!memcmp(direntry->name, "USB     H  ", 11) || direntry->name[0]==0);
2847
#endif
2848
    return;
2849
    /* avoid compiler warnings: */
2850
    hexdump(NULL, 100);
2851
    remove_mapping(vvv, NULL);
2852
    print_mapping(NULL);
2853
    print_direntry(NULL);
2854
}
2855
#endif