Statistics
| Branch: | Revision:

root / block-vvfat.c @ 64eaabda

History | View | Annotate | Download (79.1 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 <assert.h>
28
#include "qemu-common.h"
29
#include "block_int.h"
30

    
31
#ifndef S_IWGRP
32
#define S_IWGRP 0
33
#endif
34
#ifndef S_IWOTH
35
#define S_IWOTH 0
36
#endif
37

    
38
/* TODO: add ":bootsector=blabla.img:" */
39
/* LATER TODO: add automatic boot sector generation from
40
    BOOTEASY.ASM and Ranish Partition Manager
41
    Note that DOS assumes the system files to be the first files in the
42
    file system (test if the boot sector still relies on that fact)! */
43
/* MAYBE TODO: write block-visofs.c */
44
/* TODO: call try_commit() only after a timeout */
45

    
46
/* #define DEBUG */
47

    
48
#ifdef DEBUG
49

    
50
#define DLOG(a) a
51

    
52
#undef stderr
53
#define stderr STDERR
54
FILE* stderr = NULL;
55

    
56
static void checkpoint(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=0;
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 >= 0);
97
    assert(index < array->next);
98
    return array->pointer + index * array->item_size;
99
}
100

    
101
static inline int array_ensure_allocated(array_t* array, int index)
102
{
103
    if((index + 1) * array->item_size > array->size) {
104
        int new_size = (index + 32) * array->item_size;
105
        array->pointer = realloc(array->pointer, new_size);
106
        if (!array->pointer)
107
            return -1;
108
        array->size = new_size;
109
        array->next = index + 1;
110
    }
111

    
112
    return 0;
113
}
114

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

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

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

    
125
    return result;
126
}
127

    
128
static inline void* array_insert(array_t* array,unsigned int index,unsigned int count) {
129
    if((array->next+count)*array->item_size>array->size) {
130
        int increment=count*array->item_size;
131
        array->pointer=realloc(array->pointer,array->size+increment);
132
        if(!array->pointer)
133
            return 0;
134
        array->size+=increment;
135
    }
136
    memmove(array->pointer+(index+count)*array->item_size,
137
                array->pointer+index*array->item_size,
138
                (array->next-index)*array->item_size);
139
    array->next+=count;
140
    return array->pointer+index*array->item_size;
141
}
142

    
143
/* this performs a "roll", so that the element which was at index_from becomes
144
 * index_to, but the order of all other elements is preserved. */
145
static inline int array_roll(array_t* array,int index_to,int index_from,int count)
146
{
147
    char* buf;
148
    char* from;
149
    char* to;
150
    int is;
151

    
152
    if(!array ||
153
            index_to<0 || index_to>=array->next ||
154
            index_from<0 || index_from>=array->next)
155
        return -1;
156

    
157
    if(index_to==index_from)
158
        return 0;
159

    
160
    is=array->item_size;
161
    from=array->pointer+index_from*is;
162
    to=array->pointer+index_to*is;
163
    buf=malloc(is*count);
164
    memcpy(buf,from,is*count);
165

    
166
    if(index_to<index_from)
167
        memmove(to+is*count,to,from-to);
168
    else
169
        memmove(from,from+is*count,to-from);
170

    
171
    memcpy(to,buf,is*count);
172

    
173
    free(buf);
174

    
175
    return 0;
176
}
177

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

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

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

    
204
/* These structures are used to fake a disk and the VFAT filesystem.
205
 * For this reason we need to use __attribute__((packed)). */
206

    
207
typedef struct bootsector_t {
208
    uint8_t jump[3];
209
    uint8_t name[8];
210
    uint16_t sector_size;
211
    uint8_t sectors_per_cluster;
212
    uint16_t reserved_sectors;
213
    uint8_t number_of_fats;
214
    uint16_t root_entries;
215
    uint16_t total_sectors16;
216
    uint8_t media_type;
217
    uint16_t sectors_per_fat;
218
    uint16_t sectors_per_track;
219
    uint16_t number_of_heads;
220
    uint32_t hidden_sectors;
221
    uint32_t total_sectors;
222
    union {
223
        struct {
224
            uint8_t drive_number;
225
            uint8_t current_head;
226
            uint8_t signature;
227
            uint32_t id;
228
            uint8_t volume_label[11];
229
        } __attribute__((packed)) fat16;
230
        struct {
231
            uint32_t sectors_per_fat;
232
            uint16_t flags;
233
            uint8_t major,minor;
234
            uint32_t first_cluster_of_root_directory;
235
            uint16_t info_sector;
236
            uint16_t backup_boot_sector;
237
            uint16_t ignored;
238
        } __attribute__((packed)) fat32;
239
    } u;
240
    uint8_t fat_type[8];
241
    uint8_t ignored[0x1c0];
242
    uint8_t magic[2];
243
} __attribute__((packed)) bootsector_t;
244

    
245
typedef struct {
246
    uint8_t head;
247
    uint8_t sector;
248
    uint8_t cylinder;
249
} mbr_chs_t;
250

    
251
typedef struct partition_t {
252
    uint8_t attributes; /* 0x80 = bootable */
253
    mbr_chs_t start_CHS;
254
    uint8_t   fs_type; /* 0x1 = FAT12, 0x6 = FAT16, 0xe = FAT16_LBA, 0xb = FAT32, 0xc = FAT32_LBA */
255
    mbr_chs_t end_CHS;
256
    uint32_t start_sector_long;
257
    uint32_t length_sector_long;
258
} __attribute__((packed)) partition_t;
259

    
260
typedef struct mbr_t {
261
    uint8_t ignored[0x1b8];
262
    uint32_t nt_id;
263
    uint8_t ignored2[2];
264
    partition_t partition[4];
265
    uint8_t magic[2];
266
} __attribute__((packed)) mbr_t;
267

    
268
typedef struct direntry_t {
269
    uint8_t name[8];
270
    uint8_t extension[3];
271
    uint8_t attributes;
272
    uint8_t reserved[2];
273
    uint16_t ctime;
274
    uint16_t cdate;
275
    uint16_t adate;
276
    uint16_t begin_hi;
277
    uint16_t mtime;
278
    uint16_t mdate;
279
    uint16_t begin;
280
    uint32_t size;
281
} __attribute__((packed)) direntry_t;
282

    
283
/* this structure are used to transparently access the files */
284

    
285
typedef struct mapping_t {
286
    /* begin is the first cluster, end is the last+1 */
287
    uint32_t begin,end;
288
    /* as s->directory is growable, no pointer may be used here */
289
    unsigned int dir_index;
290
    /* the clusters of a file may be in any order; this points to the first */
291
    int first_mapping_index;
292
    union {
293
        /* offset is
294
         * - the offset in the file (in clusters) for a file, or
295
         * - the next cluster of the directory for a directory, and
296
         * - the address of the buffer for a faked entry
297
         */
298
        struct {
299
            uint32_t offset;
300
        } file;
301
        struct {
302
            int parent_mapping_index;
303
            int first_dir_index;
304
        } dir;
305
    } info;
306
    /* path contains the full path, i.e. it always starts with s->path */
307
    char* path;
308

    
309
    enum { MODE_UNDEFINED = 0, MODE_NORMAL = 1, MODE_MODIFIED = 2,
310
        MODE_DIRECTORY = 4, MODE_FAKED = 8,
311
        MODE_DELETED = 16, MODE_RENAMED = 32 } mode;
312
    int read_only;
313
} mapping_t;
314

    
315
#ifdef DEBUG
316
static void print_direntry(const struct direntry_t*);
317
static void print_mapping(const struct mapping_t* mapping);
318
#endif
319

    
320
/* here begins the real VVFAT driver */
321

    
322
typedef struct BDRVVVFATState {
323
    BlockDriverState* bs; /* pointer to parent */
324
    unsigned int first_sectors_number; /* 1 for a single partition, 0x40 for a disk with partition table */
325
    unsigned char first_sectors[0x40*0x200];
326

    
327
    int fat_type; /* 16 or 32 */
328
    array_t fat,directory,mapping;
329

    
330
    unsigned int cluster_size;
331
    unsigned int sectors_per_cluster;
332
    unsigned int sectors_per_fat;
333
    unsigned int sectors_of_root_directory;
334
    uint32_t last_cluster_of_root_directory;
335
    unsigned int faked_sectors; /* how many sectors are faked before file data */
336
    uint32_t sector_count; /* total number of sectors of the partition */
337
    uint32_t cluster_count; /* total number of clusters of this partition */
338
    uint32_t max_fat_value;
339

    
340
    int current_fd;
341
    mapping_t* current_mapping;
342
    unsigned char* cluster; /* points to current cluster */
343
    unsigned char* cluster_buffer; /* points to a buffer to hold temp data */
344
    unsigned int current_cluster;
345

    
346
    /* write support */
347
    BlockDriverState* write_target;
348
    char* qcow_filename;
349
    BlockDriverState* qcow;
350
    void* fat2;
351
    char* used_clusters;
352
    array_t commits;
353
    const char* path;
354
    int downcase_short_names;
355
} BDRVVVFATState;
356

    
357
/* take the sector position spos and convert it to Cylinder/Head/Sector position
358
 * if the position is outside the specified geometry, fill maximum value for CHS
359
 * and return 1 to signal overflow.
360
 */
361
static int sector2CHS(BlockDriverState* bs, mbr_chs_t * chs, int spos){
362
    int head,sector;
363
    sector   = spos % (bs->secs);  spos/= bs->secs;
364
    head     = spos % (bs->heads); spos/= bs->heads;
365
    if(spos >= bs->cyls){
366
        /* Overflow,
367
        it happens if 32bit sector positions are used, while CHS is only 24bit.
368
        Windows/Dos is said to take 1023/255/63 as nonrepresentable CHS */
369
        chs->head     = 0xFF;
370
        chs->sector   = 0xFF;
371
        chs->cylinder = 0xFF;
372
        return 1;
373
    }
374
    chs->head     = (uint8_t)head;
375
    chs->sector   = (uint8_t)( (sector+1) | ((spos>>8)<<6) );
376
    chs->cylinder = (uint8_t)spos;
377
    return 0;
378
}
379

    
380
static void init_mbr(BDRVVVFATState* s)
381
{
382
    /* TODO: if the files mbr.img and bootsect.img exist, use them */
383
    mbr_t* real_mbr=(mbr_t*)s->first_sectors;
384
    partition_t* partition=&(real_mbr->partition[0]);
385
    int lba;
386

    
387
    memset(s->first_sectors,0,512);
388

    
389
    /* Win NT Disk Signature */
390
    real_mbr->nt_id= cpu_to_le32(0xbe1afdfa);
391

    
392
    partition->attributes=0x80; /* bootable */
393

    
394
    /* LBA is used when partition is outside the CHS geometry */
395
    lba = sector2CHS(s->bs, &partition->start_CHS, s->first_sectors_number-1);
396
    lba|= sector2CHS(s->bs, &partition->end_CHS,   s->sector_count);
397

    
398
    /*LBA partitions are identified only by start/length_sector_long not by CHS*/
399
    partition->start_sector_long =cpu_to_le32(s->first_sectors_number-1);
400
    partition->length_sector_long=cpu_to_le32(s->sector_count - s->first_sectors_number+1);
401

    
402
    /* FAT12/FAT16/FAT32 */
403
    /* DOS uses different types when partition is LBA,
404
       probably to prevent older versions from using CHS on them */
405
    partition->fs_type= s->fat_type==12 ? 0x1:
406
                        s->fat_type==16 ? (lba?0xe:0x06):
407
                         /*fat_tyoe==32*/ (lba?0xc:0x0b);
408

    
409
    real_mbr->magic[0]=0x55; real_mbr->magic[1]=0xaa;
410
}
411

    
412
/* direntry functions */
413

    
414
/* dest is assumed to hold 258 bytes, and pads with 0xffff up to next multiple of 26 */
415
static inline int short2long_name(char* dest,const char* src)
416
{
417
    int i;
418
    int len;
419
    for(i=0;i<129 && src[i];i++) {
420
        dest[2*i]=src[i];
421
        dest[2*i+1]=0;
422
    }
423
    len=2*i;
424
    dest[2*i]=dest[2*i+1]=0;
425
    for(i=2*i+2;(i%26);i++)
426
        dest[i]=0xff;
427
    return len;
428
}
429

    
430
static inline direntry_t* create_long_filename(BDRVVVFATState* s,const char* filename)
431
{
432
    char buffer[258];
433
    int length=short2long_name(buffer,filename),
434
        number_of_entries=(length+25)/26,i;
435
    direntry_t* entry;
436

    
437
    for(i=0;i<number_of_entries;i++) {
438
        entry=array_get_next(&(s->directory));
439
        entry->attributes=0xf;
440
        entry->reserved[0]=0;
441
        entry->begin=0;
442
        entry->name[0]=(number_of_entries-i)|(i==0?0x40:0);
443
    }
444
    for(i=0;i<26*number_of_entries;i++) {
445
        int offset=(i%26);
446
        if(offset<10) offset=1+offset;
447
        else if(offset<22) offset=14+offset-10;
448
        else offset=28+offset-22;
449
        entry=array_get(&(s->directory),s->directory.next-1-(i/26));
450
        entry->name[offset]=buffer[i];
451
    }
452
    return array_get(&(s->directory),s->directory.next-number_of_entries);
453
}
454

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

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

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

    
470
static char is_short_name(const direntry_t* direntry)
471
{
472
    return !is_volume_label(direntry) && !is_long_name(direntry)
473
        && !is_free(direntry);
474
}
475

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

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

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

    
491
static inline uint32_t begin_of_direntry(const direntry_t* direntry)
492
{
493
    return le16_to_cpu(direntry->begin)|(le16_to_cpu(direntry->begin_hi)<<16);
494
}
495

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

    
501
static void set_begin_of_direntry(direntry_t* direntry, uint32_t begin)
502
{
503
    direntry->begin = cpu_to_le16(begin & 0xffff);
504
    direntry->begin_hi = cpu_to_le16((begin >> 16) & 0xffff);
505
}
506

    
507
/* fat functions */
508

    
509
static inline uint8_t fat_chksum(const direntry_t* entry)
510
{
511
    uint8_t chksum=0;
512
    int i;
513

    
514
    for(i=0;i<11;i++)
515
        chksum=(((chksum&0xfe)>>1)|((chksum&0x01)?0x80:0))
516
            +(unsigned char)entry->name[i];
517

    
518
    return chksum;
519
}
520

    
521
/* if return_time==0, this returns the fat_date, else the fat_time */
522
static uint16_t fat_datetime(time_t time,int return_time) {
523
    struct tm* t;
524
#ifdef _WIN32
525
    t=localtime(&time); /* this is not thread safe */
526
#else
527
    struct tm t1;
528
    t=&t1;
529
    localtime_r(&time,t);
530
#endif
531
    if(return_time)
532
        return cpu_to_le16((t->tm_sec/2)|(t->tm_min<<5)|(t->tm_hour<<11));
533
    return cpu_to_le16((t->tm_mday)|((t->tm_mon+1)<<5)|((t->tm_year-80)<<9));
534
}
535

    
536
static inline void fat_set(BDRVVVFATState* s,unsigned int cluster,uint32_t value)
537
{
538
    if(s->fat_type==32) {
539
        uint32_t* entry=array_get(&(s->fat),cluster);
540
        *entry=cpu_to_le32(value);
541
    } else if(s->fat_type==16) {
542
        uint16_t* entry=array_get(&(s->fat),cluster);
543
        *entry=cpu_to_le16(value&0xffff);
544
    } else {
545
        int offset = (cluster*3/2);
546
        unsigned char* p = array_get(&(s->fat), offset);
547
        switch (cluster&1) {
548
        case 0:
549
                p[0] = value&0xff;
550
                p[1] = (p[1]&0xf0) | ((value>>8)&0xf);
551
                break;
552
        case 1:
553
                p[0] = (p[0]&0xf) | ((value&0xf)<<4);
554
                p[1] = (value>>4);
555
                break;
556
        }
557
    }
558
}
559

    
560
static inline uint32_t fat_get(BDRVVVFATState* s,unsigned int cluster)
561
{
562
    if(s->fat_type==32) {
563
        uint32_t* entry=array_get(&(s->fat),cluster);
564
        return le32_to_cpu(*entry);
565
    } else if(s->fat_type==16) {
566
        uint16_t* entry=array_get(&(s->fat),cluster);
567
        return le16_to_cpu(*entry);
568
    } else {
569
        const uint8_t* x=(uint8_t*)(s->fat.pointer)+cluster*3/2;
570
        return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
571
    }
572
}
573

    
574
static inline int fat_eof(BDRVVVFATState* s,uint32_t fat_entry)
575
{
576
    if(fat_entry>s->max_fat_value-8)
577
        return -1;
578
    return 0;
579
}
580

    
581
static inline void init_fat(BDRVVVFATState* s)
582
{
583
    if (s->fat_type == 12) {
584
        array_init(&(s->fat),1);
585
        array_ensure_allocated(&(s->fat),
586
                s->sectors_per_fat * 0x200 * 3 / 2 - 1);
587
    } else {
588
        array_init(&(s->fat),(s->fat_type==32?4:2));
589
        array_ensure_allocated(&(s->fat),
590
                s->sectors_per_fat * 0x200 / s->fat.item_size - 1);
591
    }
592
    memset(s->fat.pointer,0,s->fat.size);
593

    
594
    switch(s->fat_type) {
595
        case 12: s->max_fat_value=0xfff; break;
596
        case 16: s->max_fat_value=0xffff; break;
597
        case 32: s->max_fat_value=0x0fffffff; break;
598
        default: s->max_fat_value=0; /* error... */
599
    }
600

    
601
}
602

    
603
/* TODO: in create_short_filename, 0xe5->0x05 is not yet handled! */
604
/* TODO: in parse_short_filename, 0x05->0xe5 is not yet handled! */
605
static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,
606
        unsigned int directory_start, const char* filename, int is_dot)
607
{
608
    int i,j,long_index=s->directory.next;
609
    direntry_t* entry=0;
610
    direntry_t* entry_long=0;
611

    
612
    if(is_dot) {
613
        entry=array_get_next(&(s->directory));
614
        memset(entry->name,0x20,11);
615
        memcpy(entry->name,filename,strlen(filename));
616
        return entry;
617
    }
618

    
619
    entry_long=create_long_filename(s,filename);
620

    
621
    i = strlen(filename);
622
    for(j = i - 1; j>0  && filename[j]!='.';j--);
623
    if (j > 0)
624
        i = (j > 8 ? 8 : j);
625
    else if (i > 8)
626
        i = 8;
627

    
628
    entry=array_get_next(&(s->directory));
629
    memset(entry->name,0x20,11);
630
    strncpy((char*)entry->name,filename,i);
631

    
632
    if(j > 0)
633
        for (i = 0; i < 3 && filename[j+1+i]; i++)
634
            entry->extension[i] = filename[j+1+i];
635

    
636
    /* upcase & remove unwanted characters */
637
    for(i=10;i>=0;i--) {
638
        if(i==10 || i==7) for(;i>0 && entry->name[i]==' ';i--);
639
        if(entry->name[i]<=' ' || entry->name[i]>0x7f
640
                || strchr(".*?<>|\":/\\[];,+='",entry->name[i]))
641
            entry->name[i]='_';
642
        else if(entry->name[i]>='a' && entry->name[i]<='z')
643
            entry->name[i]+='A'-'a';
644
    }
645

    
646
    /* mangle duplicates */
647
    while(1) {
648
        direntry_t* entry1=array_get(&(s->directory),directory_start);
649
        int j;
650

    
651
        for(;entry1<entry;entry1++)
652
            if(!is_long_name(entry1) && !memcmp(entry1->name,entry->name,11))
653
                break; /* found dupe */
654
        if(entry1==entry) /* no dupe found */
655
            break;
656

    
657
        /* use all 8 characters of name */
658
        if(entry->name[7]==' ') {
659
            int j;
660
            for(j=6;j>0 && entry->name[j]==' ';j--)
661
                entry->name[j]='~';
662
        }
663

    
664
        /* increment number */
665
        for(j=7;j>0 && entry->name[j]=='9';j--)
666
            entry->name[j]='0';
667
        if(j>0) {
668
            if(entry->name[j]<'0' || entry->name[j]>'9')
669
                entry->name[j]='0';
670
            else
671
                entry->name[j]++;
672
        }
673
    }
674

    
675
    /* calculate checksum; propagate to long name */
676
    if(entry_long) {
677
        uint8_t chksum=fat_chksum(entry);
678

    
679
        /* calculate anew, because realloc could have taken place */
680
        entry_long=array_get(&(s->directory),long_index);
681
        while(entry_long<entry && is_long_name(entry_long)) {
682
            entry_long->reserved[1]=chksum;
683
            entry_long++;
684
        }
685
    }
686

    
687
    return entry;
688
}
689

    
690
/*
691
 * Read a directory. (the index of the corresponding mapping must be passed).
692
 */
693
static int read_directory(BDRVVVFATState* s, int mapping_index)
694
{
695
    mapping_t* mapping = array_get(&(s->mapping), mapping_index);
696
    direntry_t* direntry;
697
    const char* dirname = mapping->path;
698
    int first_cluster = mapping->begin;
699
    int parent_index = mapping->info.dir.parent_mapping_index;
700
    mapping_t* parent_mapping = (mapping_t*)
701
        (parent_index >= 0 ? array_get(&(s->mapping), parent_index) : 0);
702
    int first_cluster_of_parent = parent_mapping ? parent_mapping->begin : -1;
703

    
704
    DIR* dir=opendir(dirname);
705
    struct dirent* entry;
706
    int i;
707

    
708
    assert(mapping->mode & MODE_DIRECTORY);
709

    
710
    if(!dir) {
711
        mapping->end = mapping->begin;
712
        return -1;
713
    }
714

    
715
    i = mapping->info.dir.first_dir_index =
716
            first_cluster == 0 ? 0 : s->directory.next;
717

    
718
    /* actually read the directory, and allocate the mappings */
719
    while((entry=readdir(dir))) {
720
        unsigned int length=strlen(dirname)+2+strlen(entry->d_name);
721
        char* buffer;
722
        direntry_t* direntry;
723
        struct stat st;
724
        int is_dot=!strcmp(entry->d_name,".");
725
        int is_dotdot=!strcmp(entry->d_name,"..");
726

    
727
        if(first_cluster == 0 && (is_dotdot || is_dot))
728
            continue;
729

    
730
        buffer=(char*)malloc(length);
731
        assert(buffer);
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=malloc(s->cluster_size);
853
    assert(s->cluster_buffer);
854

    
855
    /*
856
     * The formula: sc = spf+1+spf*spc*(512*8/fat_type),
857
     * where sc is sector_count,
858
     * spf is sectors_per_fat,
859
     * spc is sectors_per_clusters, and
860
     * fat_type = 12, 16 or 32.
861
     */
862
    i = 1+s->sectors_per_cluster*0x200*8/s->fat_type;
863
    s->sectors_per_fat=(s->sector_count+i)/i; /* round up */
864

    
865
    array_init(&(s->mapping),sizeof(mapping_t));
866
    array_init(&(s->directory),sizeof(direntry_t));
867

    
868
    /* add volume label */
869
    {
870
        direntry_t* entry=array_get_next(&(s->directory));
871
        entry->attributes=0x28; /* archive | volume label */
872
        snprintf((char*)entry->name,11,"QEMU VVFAT");
873
    }
874

    
875
    /* Now build FAT, and write back information into directory */
876
    init_fat(s);
877

    
878
    s->faked_sectors=s->first_sectors_number+s->sectors_per_fat*2;
879
    s->cluster_count=sector2cluster(s, s->sector_count);
880

    
881
    mapping = array_get_next(&(s->mapping));
882
    mapping->begin = 0;
883
    mapping->dir_index = 0;
884
    mapping->info.dir.parent_mapping_index = -1;
885
    mapping->first_mapping_index = -1;
886
    mapping->path = strdup(dirname);
887
    i = strlen(mapping->path);
888
    if (i > 0 && mapping->path[i - 1] == '/')
889
        mapping->path[i - 1] = '\0';
890
    mapping->mode = MODE_DIRECTORY;
891
    mapping->read_only = 0;
892
    s->path = mapping->path;
893

    
894
    for (i = 0, cluster = 0; i < s->mapping.next; i++) {
895
        int j;
896
        /* MS-DOS expects the FAT to be 0 for the root directory
897
         * (except for the media byte). */
898
        /* LATER TODO: still true for FAT32? */
899
        int fix_fat = (i != 0);
900
        mapping = array_get(&(s->mapping), i);
901

    
902
        if (mapping->mode & MODE_DIRECTORY) {
903
            mapping->begin = cluster;
904
            if(read_directory(s, i)) {
905
                fprintf(stderr, "Could not read directory %s\n",
906
                        mapping->path);
907
                return -1;
908
            }
909
            mapping = array_get(&(s->mapping), i);
910
        } else {
911
            assert(mapping->mode == MODE_UNDEFINED);
912
            mapping->mode=MODE_NORMAL;
913
            mapping->begin = cluster;
914
            if (mapping->end > 0) {
915
                direntry_t* direntry = array_get(&(s->directory),
916
                        mapping->dir_index);
917

    
918
                mapping->end = cluster + 1 + (mapping->end-1)/s->cluster_size;
919
                set_begin_of_direntry(direntry, mapping->begin);
920
            } else {
921
                mapping->end = cluster + 1;
922
                fix_fat = 0;
923
            }
924
        }
925

    
926
        assert(mapping->begin < mapping->end);
927

    
928
        /* fix fat for entry */
929
        if (fix_fat) {
930
            for(j = mapping->begin; j < mapping->end - 1; j++)
931
                fat_set(s, j, j+1);
932
            fat_set(s, mapping->end - 1, s->max_fat_value);
933
        }
934

    
935
        /* next free cluster */
936
        cluster = mapping->end;
937

    
938
        if(cluster > s->cluster_count) {
939
            fprintf(stderr,"Directory does not fit in FAT%d\n",s->fat_type);
940
            return -1;
941
        }
942
    }
943

    
944
    mapping = array_get(&(s->mapping), 0);
945
    s->sectors_of_root_directory = mapping->end * s->sectors_per_cluster;
946
    s->last_cluster_of_root_directory = mapping->end;
947

    
948
    /* the FAT signature */
949
    fat_set(s,0,s->max_fat_value);
950
    fat_set(s,1,s->max_fat_value);
951

    
952
    s->current_mapping = NULL;
953

    
954
    bootsector=(bootsector_t*)(s->first_sectors+(s->first_sectors_number-1)*0x200);
955
    bootsector->jump[0]=0xeb;
956
    bootsector->jump[1]=0x3e;
957
    bootsector->jump[2]=0x90;
958
    memcpy(bootsector->name,"QEMU    ",8);
959
    bootsector->sector_size=cpu_to_le16(0x200);
960
    bootsector->sectors_per_cluster=s->sectors_per_cluster;
961
    bootsector->reserved_sectors=cpu_to_le16(1);
962
    bootsector->number_of_fats=0x2; /* number of FATs */
963
    bootsector->root_entries=cpu_to_le16(s->sectors_of_root_directory*0x10);
964
    bootsector->total_sectors16=s->sector_count>0xffff?0:cpu_to_le16(s->sector_count);
965
    bootsector->media_type=(s->fat_type!=12?0xf8:s->sector_count==5760?0xf9:0xf8); /* media descriptor */
966
    s->fat.pointer[0] = bootsector->media_type;
967
    bootsector->sectors_per_fat=cpu_to_le16(s->sectors_per_fat);
968
    bootsector->sectors_per_track=cpu_to_le16(s->bs->secs);
969
    bootsector->number_of_heads=cpu_to_le16(s->bs->heads);
970
    bootsector->hidden_sectors=cpu_to_le32(s->first_sectors_number==1?0:0x3f);
971
    bootsector->total_sectors=cpu_to_le32(s->sector_count>0xffff?s->sector_count:0);
972

    
973
    /* LATER TODO: if FAT32, this is wrong */
974
    bootsector->u.fat16.drive_number=s->fat_type==12?0:0x80; /* assume this is hda (TODO) */
975
    bootsector->u.fat16.current_head=0;
976
    bootsector->u.fat16.signature=0x29;
977
    bootsector->u.fat16.id=cpu_to_le32(0xfabe1afd);
978

    
979
    memcpy(bootsector->u.fat16.volume_label,"QEMU VVFAT ",11);
980
    memcpy(bootsector->fat_type,(s->fat_type==12?"FAT12   ":s->fat_type==16?"FAT16   ":"FAT32   "),8);
981
    bootsector->magic[0]=0x55; bootsector->magic[1]=0xaa;
982

    
983
    return 0;
984
}
985

    
986
#ifdef DEBUG
987
static BDRVVVFATState *vvv = NULL;
988
#endif
989

    
990
static int enable_write_target(BDRVVVFATState *s);
991
static int is_consistent(BDRVVVFATState *s);
992

    
993
static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
994
{
995
    BDRVVVFATState *s = bs->opaque;
996
    int floppy = 0;
997
    int i;
998

    
999
#ifdef DEBUG
1000
    vvv = s;
1001
#endif
1002

    
1003
DLOG(if (stderr == NULL) {
1004
    stderr = fopen("vvfat.log", "a");
1005
    setbuf(stderr, NULL);
1006
})
1007

    
1008
    s->bs = bs;
1009

    
1010
    s->fat_type=16;
1011
    /* LATER TODO: if FAT32, adjust */
1012
    s->sectors_per_cluster=0x10;
1013
    /* 504MB disk*/
1014
    bs->cyls=1024; bs->heads=16; bs->secs=63;
1015

    
1016
    s->current_cluster=0xffffffff;
1017

    
1018
    s->first_sectors_number=0x40;
1019
    /* read only is the default for safety */
1020
    bs->read_only = 1;
1021
    s->qcow = s->write_target = NULL;
1022
    s->qcow_filename = NULL;
1023
    s->fat2 = NULL;
1024
    s->downcase_short_names = 1;
1025

    
1026
    if (!strstart(dirname, "fat:", NULL))
1027
        return -1;
1028

    
1029
    if (strstr(dirname, ":floppy:")) {
1030
        floppy = 1;
1031
        s->fat_type = 12;
1032
        s->first_sectors_number = 1;
1033
        s->sectors_per_cluster=2;
1034
        bs->cyls = 80; bs->heads = 2; bs->secs = 36;
1035
    }
1036

    
1037
    s->sector_count=bs->cyls*bs->heads*bs->secs;
1038

    
1039
    if (strstr(dirname, ":32:")) {
1040
        fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. You are welcome to do so!\n");
1041
        s->fat_type = 32;
1042
    } else if (strstr(dirname, ":16:")) {
1043
        s->fat_type = 16;
1044
    } else if (strstr(dirname, ":12:")) {
1045
        s->fat_type = 12;
1046
        s->sector_count=2880;
1047
    }
1048

    
1049
    if (strstr(dirname, ":rw:")) {
1050
        if (enable_write_target(s))
1051
            return -1;
1052
        bs->read_only = 0;
1053
    }
1054

    
1055
    i = strrchr(dirname, ':') - dirname;
1056
    assert(i >= 3);
1057
    if (dirname[i-2] == ':' && isalpha(dirname[i-1]))
1058
        /* workaround for DOS drive names */
1059
        dirname += i-1;
1060
    else
1061
        dirname += i+1;
1062

    
1063
    bs->total_sectors=bs->cyls*bs->heads*bs->secs;
1064

    
1065
    if(init_directories(s, dirname))
1066
        return -1;
1067

    
1068
    s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
1069

    
1070
    if(s->first_sectors_number==0x40)
1071
        init_mbr(s);
1072

    
1073
    /* for some reason or other, MS-DOS does not like to know about CHS... */
1074
    if (floppy)
1075
        bs->heads = bs->cyls = bs->secs = 0;
1076

    
1077
    //    assert(is_consistent(s));
1078
    return 0;
1079
}
1080

    
1081
static inline void vvfat_close_current_file(BDRVVVFATState *s)
1082
{
1083
    if(s->current_mapping) {
1084
        s->current_mapping = NULL;
1085
        if (s->current_fd) {
1086
                close(s->current_fd);
1087
                s->current_fd = 0;
1088
        }
1089
    }
1090
    s->current_cluster = -1;
1091
}
1092

    
1093
/* mappings between index1 and index2-1 are supposed to be ordered
1094
 * return value is the index of the last mapping for which end>cluster_num
1095
 */
1096
static inline int find_mapping_for_cluster_aux(BDRVVVFATState* s,int cluster_num,int index1,int index2)
1097
{
1098
    int index3=index1+1;
1099
    while(1) {
1100
        mapping_t* mapping;
1101
        index3=(index1+index2)/2;
1102
        mapping=array_get(&(s->mapping),index3);
1103
        assert(mapping->begin < mapping->end);
1104
        if(mapping->begin>=cluster_num) {
1105
            assert(index2!=index3 || index2==0);
1106
            if(index2==index3)
1107
                return index1;
1108
            index2=index3;
1109
        } else {
1110
            if(index1==index3)
1111
                return mapping->end<=cluster_num ? index2 : index1;
1112
            index1=index3;
1113
        }
1114
        assert(index1<=index2);
1115
        DLOG(mapping=array_get(&(s->mapping),index1);
1116
        assert(mapping->begin<=cluster_num);
1117
        assert(index2 >= s->mapping.next ||
1118
                ((mapping = array_get(&(s->mapping),index2)) &&
1119
                mapping->end>cluster_num)));
1120
    }
1121
}
1122

    
1123
static inline mapping_t* find_mapping_for_cluster(BDRVVVFATState* s,int cluster_num)
1124
{
1125
    int index=find_mapping_for_cluster_aux(s,cluster_num,0,s->mapping.next);
1126
    mapping_t* mapping;
1127
    if(index>=s->mapping.next)
1128
        return 0;
1129
    mapping=array_get(&(s->mapping),index);
1130
    if(mapping->begin>cluster_num)
1131
        return 0;
1132
    assert(mapping->begin<=cluster_num && mapping->end>cluster_num);
1133
    return mapping;
1134
}
1135

    
1136
/*
1137
 * This function simply compares path == mapping->path. Since the mappings
1138
 * are sorted by cluster, this is expensive: O(n).
1139
 */
1140
static inline mapping_t* find_mapping_for_path(BDRVVVFATState* s,
1141
        const char* path)
1142
{
1143
    int i;
1144

    
1145
    for (i = 0; i < s->mapping.next; i++) {
1146
        mapping_t* mapping = array_get(&(s->mapping), i);
1147
        if (mapping->first_mapping_index < 0 &&
1148
                !strcmp(path, mapping->path))
1149
            return mapping;
1150
    }
1151

    
1152
    return NULL;
1153
}
1154

    
1155
static int open_file(BDRVVVFATState* s,mapping_t* mapping)
1156
{
1157
    if(!mapping)
1158
        return -1;
1159
    if(!s->current_mapping ||
1160
            strcmp(s->current_mapping->path,mapping->path)) {
1161
        /* open file */
1162
        int fd = open(mapping->path, O_RDONLY | O_BINARY | O_LARGEFILE);
1163
        if(fd<0)
1164
            return -1;
1165
        vvfat_close_current_file(s);
1166
        s->current_fd = fd;
1167
        s->current_mapping = mapping;
1168
    }
1169
    return 0;
1170
}
1171

    
1172
static inline int read_cluster(BDRVVVFATState *s,int cluster_num)
1173
{
1174
    if(s->current_cluster != cluster_num) {
1175
        int result=0;
1176
        off_t offset;
1177
        assert(!s->current_mapping || s->current_fd || (s->current_mapping->mode & MODE_DIRECTORY));
1178
        if(!s->current_mapping
1179
                || s->current_mapping->begin>cluster_num
1180
                || s->current_mapping->end<=cluster_num) {
1181
            /* binary search of mappings for file */
1182
            mapping_t* mapping=find_mapping_for_cluster(s,cluster_num);
1183

    
1184
            assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
1185

    
1186
            if (mapping && mapping->mode & MODE_DIRECTORY) {
1187
                vvfat_close_current_file(s);
1188
                s->current_mapping = mapping;
1189
read_cluster_directory:
1190
                offset = s->cluster_size*(cluster_num-s->current_mapping->begin);
1191
                s->cluster = (unsigned char*)s->directory.pointer+offset
1192
                        + 0x20*s->current_mapping->info.dir.first_dir_index;
1193
                assert(((s->cluster-(unsigned char*)s->directory.pointer)%s->cluster_size)==0);
1194
                assert((char*)s->cluster+s->cluster_size <= s->directory.pointer+s->directory.next*s->directory.item_size);
1195
                s->current_cluster = cluster_num;
1196
                return 0;
1197
            }
1198

    
1199
            if(open_file(s,mapping))
1200
                return -2;
1201
        } else if (s->current_mapping->mode & MODE_DIRECTORY)
1202
            goto read_cluster_directory;
1203

    
1204
        assert(s->current_fd);
1205

    
1206
        offset=s->cluster_size*(cluster_num-s->current_mapping->begin)+s->current_mapping->info.file.offset;
1207
        if(lseek(s->current_fd, offset, SEEK_SET)!=offset)
1208
            return -3;
1209
        s->cluster=s->cluster_buffer;
1210
        result=read(s->current_fd,s->cluster,s->cluster_size);
1211
        if(result<0) {
1212
            s->current_cluster = -1;
1213
            return -1;
1214
        }
1215
        s->current_cluster = cluster_num;
1216
    }
1217
    return 0;
1218
}
1219

    
1220
#ifdef DEBUG
1221
static void hexdump(const void* address, uint32_t len)
1222
{
1223
    const unsigned char* p = address;
1224
    int i, j;
1225

    
1226
    for (i = 0; i < len; i += 16) {
1227
        for (j = 0; j < 16 && i + j < len; j++)
1228
            fprintf(stderr, "%02x ", p[i + j]);
1229
        for (; j < 16; j++)
1230
            fprintf(stderr, "   ");
1231
        fprintf(stderr, " ");
1232
        for (j = 0; j < 16 && i + j < len; j++)
1233
            fprintf(stderr, "%c", (p[i + j] < ' ' || p[i + j] > 0x7f) ? '.' : p[i + j]);
1234
        fprintf(stderr, "\n");
1235
    }
1236
}
1237

    
1238
static void print_direntry(const direntry_t* direntry)
1239
{
1240
    int j = 0;
1241
    char buffer[1024];
1242

    
1243
    fprintf(stderr, "direntry 0x%x: ", (int)direntry);
1244
    if(!direntry)
1245
        return;
1246
    if(is_long_name(direntry)) {
1247
        unsigned char* c=(unsigned char*)direntry;
1248
        int i;
1249
        for(i=1;i<11 && c[i] && c[i]!=0xff;i+=2)
1250
#define ADD_CHAR(c) {buffer[j] = (c); if (buffer[j] < ' ') buffer[j] = '?'; j++;}
1251
            ADD_CHAR(c[i]);
1252
        for(i=14;i<26 && c[i] && c[i]!=0xff;i+=2)
1253
            ADD_CHAR(c[i]);
1254
        for(i=28;i<32 && c[i] && c[i]!=0xff;i+=2)
1255
            ADD_CHAR(c[i]);
1256
        buffer[j] = 0;
1257
        fprintf(stderr, "%s\n", buffer);
1258
    } else {
1259
        int i;
1260
        for(i=0;i<11;i++)
1261
            ADD_CHAR(direntry->name[i]);
1262
        buffer[j] = 0;
1263
        fprintf(stderr,"%s attributes=0x%02x begin=%d size=%d\n",
1264
                buffer,
1265
                direntry->attributes,
1266
                begin_of_direntry(direntry),le32_to_cpu(direntry->size));
1267
    }
1268
}
1269

    
1270
static void print_mapping(const mapping_t* mapping)
1271
{
1272
    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);
1273
    if (mapping->mode & MODE_DIRECTORY)
1274
        fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
1275
    else
1276
        fprintf(stderr, "offset = %d\n", mapping->info.file.offset);
1277
}
1278
#endif
1279

    
1280
static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
1281
                    uint8_t *buf, int nb_sectors)
1282
{
1283
    BDRVVVFATState *s = bs->opaque;
1284
    int i;
1285

    
1286
    for(i=0;i<nb_sectors;i++,sector_num++) {
1287
        if (sector_num >= s->sector_count)
1288
           return -1;
1289
        if (s->qcow) {
1290
            int n;
1291
            if (s->qcow->drv->bdrv_is_allocated(s->qcow,
1292
                        sector_num, nb_sectors-i, &n)) {
1293
DLOG(fprintf(stderr, "sectors %d+%d allocated\n", (int)sector_num, n));
1294
                if (s->qcow->drv->bdrv_read(s->qcow, sector_num, buf+i*0x200, n))
1295
                    return -1;
1296
                i += n - 1;
1297
                sector_num += n - 1;
1298
                continue;
1299
            }
1300
DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num));
1301
        }
1302
        if(sector_num<s->faked_sectors) {
1303
            if(sector_num<s->first_sectors_number)
1304
                memcpy(buf+i*0x200,&(s->first_sectors[sector_num*0x200]),0x200);
1305
            else if(sector_num-s->first_sectors_number<s->sectors_per_fat)
1306
                memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number)*0x200]),0x200);
1307
            else if(sector_num-s->first_sectors_number-s->sectors_per_fat<s->sectors_per_fat)
1308
                memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number-s->sectors_per_fat)*0x200]),0x200);
1309
        } else {
1310
            uint32_t sector=sector_num-s->faked_sectors,
1311
            sector_offset_in_cluster=(sector%s->sectors_per_cluster),
1312
            cluster_num=sector/s->sectors_per_cluster;
1313
            if(read_cluster(s, cluster_num) != 0) {
1314
                /* LATER TODO: strict: return -1; */
1315
                memset(buf+i*0x200,0,0x200);
1316
                continue;
1317
            }
1318
            memcpy(buf+i*0x200,s->cluster+sector_offset_in_cluster*0x200,0x200);
1319
        }
1320
    }
1321
    return 0;
1322
}
1323

    
1324
/* LATER TODO: statify all functions */
1325

    
1326
/*
1327
 * Idea of the write support (use snapshot):
1328
 *
1329
 * 1. check if all data is consistent, recording renames, modifications,
1330
 *    new files and directories (in s->commits).
1331
 *
1332
 * 2. if the data is not consistent, stop committing
1333
 *
1334
 * 3. handle renames, and create new files and directories (do not yet
1335
 *    write their contents)
1336
 *
1337
 * 4. walk the directories, fixing the mapping and direntries, and marking
1338
 *    the handled mappings as not deleted
1339
 *
1340
 * 5. commit the contents of the files
1341
 *
1342
 * 6. handle deleted files and directories
1343
 *
1344
 */
1345

    
1346
typedef struct commit_t {
1347
    char* path;
1348
    union {
1349
        struct { uint32_t cluster; } rename;
1350
        struct { int dir_index; uint32_t modified_offset; } writeout;
1351
        struct { uint32_t first_cluster; } new_file;
1352
        struct { uint32_t cluster; } mkdir;
1353
    } param;
1354
    /* DELETEs and RMDIRs are handled differently: see handle_deletes() */
1355
    enum {
1356
        ACTION_RENAME, ACTION_WRITEOUT, ACTION_NEW_FILE, ACTION_MKDIR
1357
    } action;
1358
} commit_t;
1359

    
1360
static void clear_commits(BDRVVVFATState* s)
1361
{
1362
    int i;
1363
DLOG(fprintf(stderr, "clear_commits (%d commits)\n", s->commits.next));
1364
    for (i = 0; i < s->commits.next; i++) {
1365
        commit_t* commit = array_get(&(s->commits), i);
1366
        assert(commit->path || commit->action == ACTION_WRITEOUT);
1367
        if (commit->action != ACTION_WRITEOUT) {
1368
            assert(commit->path);
1369
            free(commit->path);
1370
        } else
1371
            assert(commit->path == NULL);
1372
    }
1373
    s->commits.next = 0;
1374
}
1375

    
1376
static void schedule_rename(BDRVVVFATState* s,
1377
        uint32_t cluster, char* new_path)
1378
{
1379
    commit_t* commit = array_get_next(&(s->commits));
1380
    commit->path = new_path;
1381
    commit->param.rename.cluster = cluster;
1382
    commit->action = ACTION_RENAME;
1383
}
1384

    
1385
static void schedule_writeout(BDRVVVFATState* s,
1386
        int dir_index, uint32_t modified_offset)
1387
{
1388
    commit_t* commit = array_get_next(&(s->commits));
1389
    commit->path = NULL;
1390
    commit->param.writeout.dir_index = dir_index;
1391
    commit->param.writeout.modified_offset = modified_offset;
1392
    commit->action = ACTION_WRITEOUT;
1393
}
1394

    
1395
static void schedule_new_file(BDRVVVFATState* s,
1396
        char* path, uint32_t first_cluster)
1397
{
1398
    commit_t* commit = array_get_next(&(s->commits));
1399
    commit->path = path;
1400
    commit->param.new_file.first_cluster = first_cluster;
1401
    commit->action = ACTION_NEW_FILE;
1402
}
1403

    
1404
static void schedule_mkdir(BDRVVVFATState* s, uint32_t cluster, char* path)
1405
{
1406
    commit_t* commit = array_get_next(&(s->commits));
1407
    commit->path = path;
1408
    commit->param.mkdir.cluster = cluster;
1409
    commit->action = ACTION_MKDIR;
1410
}
1411

    
1412
typedef struct {
1413
    /*
1414
     * Since the sequence number is at most 0x3f, and the filename
1415
     * length is at most 13 times the sequence number, the maximal
1416
     * filename length is 0x3f * 13 bytes.
1417
     */
1418
    unsigned char name[0x3f * 13 + 1];
1419
    int checksum, len;
1420
    int sequence_number;
1421
} long_file_name;
1422

    
1423
static void lfn_init(long_file_name* lfn)
1424
{
1425
   lfn->sequence_number = lfn->len = 0;
1426
   lfn->checksum = 0x100;
1427
}
1428

    
1429
/* return 0 if parsed successfully, > 0 if no long name, < 0 if error */
1430
static int parse_long_name(long_file_name* lfn,
1431
        const direntry_t* direntry)
1432
{
1433
    int i, j, offset;
1434
    const unsigned char* pointer = (const unsigned char*)direntry;
1435

    
1436
    if (!is_long_name(direntry))
1437
        return 1;
1438

    
1439
    if (pointer[0] & 0x40) {
1440
        lfn->sequence_number = pointer[0] & 0x3f;
1441
        lfn->checksum = pointer[13];
1442
        lfn->name[0] = 0;
1443
    } else if ((pointer[0] & 0x3f) != --lfn->sequence_number)
1444
        return -1;
1445
    else if (pointer[13] != lfn->checksum)
1446
        return -2;
1447
    else if (pointer[12] || pointer[26] || pointer[27])
1448
        return -3;
1449

    
1450
    offset = 13 * (lfn->sequence_number - 1);
1451
    for (i = 0, j = 1; i < 13; i++, j+=2) {
1452
        if (j == 11)
1453
            j = 14;
1454
        else if (j == 26)
1455
            j = 28;
1456

    
1457
        if (pointer[j+1] == 0)
1458
            lfn->name[offset + i] = pointer[j];
1459
        else if (pointer[j+1] != 0xff || (pointer[0] & 0x40) == 0)
1460
            return -4;
1461
        else
1462
            lfn->name[offset + i] = 0;
1463
    }
1464

    
1465
    if (pointer[0] & 0x40)
1466
        lfn->len = offset + strlen((char*)lfn->name + offset);
1467

    
1468
    return 0;
1469
}
1470

    
1471
/* returns 0 if successful, >0 if no short_name, and <0 on error */
1472
static int parse_short_name(BDRVVVFATState* s,
1473
        long_file_name* lfn, direntry_t* direntry)
1474
{
1475
    int i, j;
1476

    
1477
    if (!is_short_name(direntry))
1478
        return 1;
1479

    
1480
    for (j = 7; j >= 0 && direntry->name[j] == ' '; j--);
1481
    for (i = 0; i <= j; i++) {
1482
        if (direntry->name[i] <= ' ' || direntry->name[i] > 0x7f)
1483
            return -1;
1484
        else if (s->downcase_short_names)
1485
            lfn->name[i] = tolower(direntry->name[i]);
1486
        else
1487
            lfn->name[i] = direntry->name[i];
1488
    }
1489

    
1490
    for (j = 2; j >= 0 && direntry->extension[j] == ' '; j--);
1491
    if (j >= 0) {
1492
        lfn->name[i++] = '.';
1493
        lfn->name[i + j + 1] = '\0';
1494
        for (;j >= 0; j--) {
1495
            if (direntry->extension[j] <= ' ' || direntry->extension[j] > 0x7f)
1496
                return -2;
1497
            else if (s->downcase_short_names)
1498
                lfn->name[i + j] = tolower(direntry->extension[j]);
1499
            else
1500
                lfn->name[i + j] = direntry->extension[j];
1501
        }
1502
    } else
1503
        lfn->name[i + j + 1] = '\0';
1504

    
1505
    lfn->len = strlen((char*)lfn->name);
1506

    
1507
    return 0;
1508
}
1509

    
1510
static inline uint32_t modified_fat_get(BDRVVVFATState* s,
1511
        unsigned int cluster)
1512
{
1513
    if (cluster < s->last_cluster_of_root_directory) {
1514
        if (cluster + 1 == s->last_cluster_of_root_directory)
1515
            return s->max_fat_value;
1516
        else
1517
            return cluster + 1;
1518
    }
1519

    
1520
    if (s->fat_type==32) {
1521
        uint32_t* entry=((uint32_t*)s->fat2)+cluster;
1522
        return le32_to_cpu(*entry);
1523
    } else if (s->fat_type==16) {
1524
        uint16_t* entry=((uint16_t*)s->fat2)+cluster;
1525
        return le16_to_cpu(*entry);
1526
    } else {
1527
        const uint8_t* x=s->fat2+cluster*3/2;
1528
        return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
1529
    }
1530
}
1531

    
1532
static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num)
1533
{
1534
    int was_modified = 0;
1535
    int i, dummy;
1536

    
1537
    if (s->qcow == NULL)
1538
        return 0;
1539

    
1540
    for (i = 0; !was_modified && i < s->sectors_per_cluster; i++)
1541
        was_modified = s->qcow->drv->bdrv_is_allocated(s->qcow,
1542
                cluster2sector(s, cluster_num) + i, 1, &dummy);
1543

    
1544
    return was_modified;
1545
}
1546

    
1547
static const char* get_basename(const char* path)
1548
{
1549
    char* basename = strrchr(path, '/');
1550
    if (basename == NULL)
1551
        return path;
1552
    else
1553
        return basename + 1; /* strip '/' */
1554
}
1555

    
1556
/*
1557
 * The array s->used_clusters holds the states of the clusters. If it is
1558
 * part of a file, it has bit 2 set, in case of a directory, bit 1. If it
1559
 * was modified, bit 3 is set.
1560
 * If any cluster is allocated, but not part of a file or directory, this
1561
 * driver refuses to commit.
1562
 */
1563
typedef enum {
1564
     USED_DIRECTORY = 1, USED_FILE = 2, USED_ANY = 3, USED_ALLOCATED = 4
1565
} used_t;
1566

    
1567
/*
1568
 * get_cluster_count_for_direntry() not only determines how many clusters
1569
 * are occupied by direntry, but also if it was renamed or modified.
1570
 *
1571
 * A file is thought to be renamed *only* if there already was a file with
1572
 * exactly the same first cluster, but a different name.
1573
 *
1574
 * Further, the files/directories handled by this function are
1575
 * assumed to be *not* deleted (and *only* those).
1576
 */
1577
static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
1578
        direntry_t* direntry, const char* path)
1579
{
1580
    /*
1581
     * This is a little bit tricky:
1582
     * IF the guest OS just inserts a cluster into the file chain,
1583
     * and leaves the rest alone, (i.e. the original file had clusters
1584
     * 15 -> 16, but now has 15 -> 32 -> 16), then the following happens:
1585
     *
1586
     * - do_commit will write the cluster into the file at the given
1587
     *   offset, but
1588
     *
1589
     * - the cluster which is overwritten should be moved to a later
1590
     *   position in the file.
1591
     *
1592
     * I am not aware that any OS does something as braindead, but this
1593
     * situation could happen anyway when not committing for a long time.
1594
     * Just to be sure that this does not bite us, detect it, and copy the
1595
     * contents of the clusters to-be-overwritten into the qcow.
1596
     */
1597
    int copy_it = 0;
1598
    int was_modified = 0;
1599
    int32_t ret = 0;
1600

    
1601
    uint32_t cluster_num = begin_of_direntry(direntry);
1602
    uint32_t offset = 0;
1603
    int first_mapping_index = -1;
1604
    mapping_t* mapping = NULL;
1605
    const char* basename2 = NULL;
1606

    
1607
    vvfat_close_current_file(s);
1608

    
1609
    /* the root directory */
1610
    if (cluster_num == 0)
1611
        return 0;
1612

    
1613
    /* write support */
1614
    if (s->qcow) {
1615
        basename2 = get_basename(path);
1616

    
1617
        mapping = find_mapping_for_cluster(s, cluster_num);
1618

    
1619
        if (mapping) {
1620
            const char* basename;
1621

    
1622
            assert(mapping->mode & MODE_DELETED);
1623
            mapping->mode &= ~MODE_DELETED;
1624

    
1625
            basename = get_basename(mapping->path);
1626

    
1627
            assert(mapping->mode & MODE_NORMAL);
1628

    
1629
            /* rename */
1630
            if (strcmp(basename, basename2))
1631
                schedule_rename(s, cluster_num, strdup(path));
1632
        } else if (is_file(direntry))
1633
            /* new file */
1634
            schedule_new_file(s, strdup(path), cluster_num);
1635
        else {
1636
            assert(0);
1637
            return 0;
1638
        }
1639
    }
1640

    
1641
    while(1) {
1642
        if (s->qcow) {
1643
            if (!copy_it && cluster_was_modified(s, cluster_num)) {
1644
                if (mapping == NULL ||
1645
                        mapping->begin > cluster_num ||
1646
                        mapping->end <= cluster_num)
1647
                mapping = find_mapping_for_cluster(s, cluster_num);
1648

    
1649

    
1650
                if (mapping &&
1651
                        (mapping->mode & MODE_DIRECTORY) == 0) {
1652

    
1653
                    /* was modified in qcow */
1654
                    if (offset != mapping->info.file.offset + s->cluster_size
1655
                            * (cluster_num - mapping->begin)) {
1656
                        /* offset of this cluster in file chain has changed */
1657
                        assert(0);
1658
                        copy_it = 1;
1659
                    } else if (offset == 0) {
1660
                        const char* basename = get_basename(mapping->path);
1661

    
1662
                        if (strcmp(basename, basename2))
1663
                            copy_it = 1;
1664
                        first_mapping_index = array_index(&(s->mapping), mapping);
1665
                    }
1666

    
1667
                    if (mapping->first_mapping_index != first_mapping_index
1668
                            && mapping->info.file.offset > 0) {
1669
                        assert(0);
1670
                        copy_it = 1;
1671
                    }
1672

    
1673
                    /* need to write out? */
1674
                    if (!was_modified && is_file(direntry)) {
1675
                        was_modified = 1;
1676
                        schedule_writeout(s, mapping->dir_index, offset);
1677
                    }
1678
                }
1679
            }
1680

    
1681
            if (copy_it) {
1682
                int i, dummy;
1683
                /*
1684
                 * This is horribly inefficient, but that is okay, since
1685
                 * it is rarely executed, if at all.
1686
                 */
1687
                int64_t offset = cluster2sector(s, cluster_num);
1688

    
1689
                vvfat_close_current_file(s);
1690
                for (i = 0; i < s->sectors_per_cluster; i++)
1691
                    if (!s->qcow->drv->bdrv_is_allocated(s->qcow,
1692
                                offset + i, 1, &dummy)) {
1693
                        if (vvfat_read(s->bs,
1694
                                    offset, s->cluster_buffer, 1))
1695
                            return -1;
1696
                        if (s->qcow->drv->bdrv_write(s->qcow,
1697
                                    offset, s->cluster_buffer, 1))
1698
                            return -2;
1699
                    }
1700
            }
1701
        }
1702

    
1703
        ret++;
1704
        if (s->used_clusters[cluster_num] & USED_ANY)
1705
            return 0;
1706
        s->used_clusters[cluster_num] = USED_FILE;
1707

    
1708
        cluster_num = modified_fat_get(s, cluster_num);
1709

    
1710
        if (fat_eof(s, cluster_num))
1711
            return ret;
1712
        else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
1713
            return -1;
1714

    
1715
        offset += s->cluster_size;
1716
    }
1717
}
1718

    
1719
/*
1720
 * This function looks at the modified data (qcow).
1721
 * It returns 0 upon inconsistency or error, and the number of clusters
1722
 * used by the directory, its subdirectories and their files.
1723
 */
1724
static int check_directory_consistency(BDRVVVFATState *s,
1725
        int cluster_num, const char* path)
1726
{
1727
    int ret = 0;
1728
    unsigned char* cluster = malloc(s->cluster_size);
1729
    direntry_t* direntries = (direntry_t*)cluster;
1730
    mapping_t* mapping = find_mapping_for_cluster(s, cluster_num);
1731

    
1732
    long_file_name lfn;
1733
    int path_len = strlen(path);
1734
    char path2[PATH_MAX];
1735

    
1736
    assert(path_len < PATH_MAX); /* len was tested before! */
1737
    strcpy(path2, path);
1738
    path2[path_len] = '/';
1739
    path2[path_len + 1] = '\0';
1740

    
1741
    if (mapping) {
1742
        const char* basename = get_basename(mapping->path);
1743
        const char* basename2 = get_basename(path);
1744

    
1745
        assert(mapping->mode & MODE_DIRECTORY);
1746

    
1747
        assert(mapping->mode & MODE_DELETED);
1748
        mapping->mode &= ~MODE_DELETED;
1749

    
1750
        if (strcmp(basename, basename2))
1751
            schedule_rename(s, cluster_num, strdup(path));
1752
    } else
1753
        /* new directory */
1754
        schedule_mkdir(s, cluster_num, strdup(path));
1755

    
1756
    lfn_init(&lfn);
1757
    do {
1758
        int i;
1759
        int subret = 0;
1760

    
1761
        ret++;
1762

    
1763
        if (s->used_clusters[cluster_num] & USED_ANY) {
1764
            fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
1765
            return 0;
1766
        }
1767
        s->used_clusters[cluster_num] = USED_DIRECTORY;
1768

    
1769
DLOG(fprintf(stderr, "read cluster %d (sector %d)\n", (int)cluster_num, (int)cluster2sector(s, cluster_num)));
1770
        subret = vvfat_read(s->bs, cluster2sector(s, cluster_num), cluster,
1771
                s->sectors_per_cluster);
1772
        if (subret) {
1773
            fprintf(stderr, "Error fetching direntries\n");
1774
        fail:
1775
            free(cluster);
1776
            return 0;
1777
        }
1778

    
1779
        for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
1780
            int cluster_count;
1781

    
1782
DLOG(fprintf(stderr, "check direntry %d: \n", i); print_direntry(direntries + i));
1783
            if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
1784
                    is_free(direntries + i))
1785
                continue;
1786

    
1787
            subret = parse_long_name(&lfn, direntries + i);
1788
            if (subret < 0) {
1789
                fprintf(stderr, "Error in long name\n");
1790
                goto fail;
1791
            }
1792
            if (subret == 0 || is_free(direntries + i))
1793
                continue;
1794

    
1795
            if (fat_chksum(direntries+i) != lfn.checksum) {
1796
                subret = parse_short_name(s, &lfn, direntries + i);
1797
                if (subret < 0) {
1798
                    fprintf(stderr, "Error in short name (%d)\n", subret);
1799
                    goto fail;
1800
                }
1801
                if (subret > 0 || !strcmp((char*)lfn.name, ".")
1802
                        || !strcmp((char*)lfn.name, ".."))
1803
                    continue;
1804
            }
1805
            lfn.checksum = 0x100; /* cannot use long name twice */
1806

    
1807
            if (path_len + 1 + lfn.len >= PATH_MAX) {
1808
                fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
1809
                goto fail;
1810
            }
1811
            strcpy(path2 + path_len + 1, (char*)lfn.name);
1812

    
1813
            if (is_directory(direntries + i)) {
1814
                if (begin_of_direntry(direntries + i) == 0) {
1815
                    DLOG(fprintf(stderr, "invalid begin for directory: %s\n", path2); print_direntry(direntries + i));
1816
                    goto fail;
1817
                }
1818
                cluster_count = check_directory_consistency(s,
1819
                        begin_of_direntry(direntries + i), path2);
1820
                if (cluster_count == 0) {
1821
                    DLOG(fprintf(stderr, "problem in directory %s:\n", path2); print_direntry(direntries + i));
1822
                    goto fail;
1823
                }
1824
            } else if (is_file(direntries + i)) {
1825
                /* check file size with FAT */
1826
                cluster_count = get_cluster_count_for_direntry(s, direntries + i, path2);
1827
                if (cluster_count !=
1828
                        (le32_to_cpu(direntries[i].size) + s->cluster_size
1829
                         - 1) / s->cluster_size) {
1830
                    DLOG(fprintf(stderr, "Cluster count mismatch\n"));
1831
                    goto fail;
1832
                }
1833
            } else
1834
                assert(0); /* cluster_count = 0; */
1835

    
1836
            ret += cluster_count;
1837
        }
1838

    
1839
        cluster_num = modified_fat_get(s, cluster_num);
1840
    } while(!fat_eof(s, cluster_num));
1841

    
1842
    free(cluster);
1843
    return ret;
1844
}
1845

    
1846
/* returns 1 on success */
1847
static int is_consistent(BDRVVVFATState* s)
1848
{
1849
    int i, check;
1850
    int used_clusters_count = 0;
1851

    
1852
DLOG(checkpoint());
1853
    /*
1854
     * - get modified FAT
1855
     * - compare the two FATs (TODO)
1856
     * - get buffer for marking used clusters
1857
     * - recurse direntries from root (using bs->bdrv_read to make
1858
     *    sure to get the new data)
1859
     *   - check that the FAT agrees with the size
1860
     *   - count the number of clusters occupied by this directory and
1861
     *     its files
1862
     * - check that the cumulative used cluster count agrees with the
1863
     *   FAT
1864
     * - if all is fine, return number of used clusters
1865
     */
1866
    if (s->fat2 == NULL) {
1867
        int size = 0x200 * s->sectors_per_fat;
1868
        s->fat2 = malloc(size);
1869
        memcpy(s->fat2, s->fat.pointer, size);
1870
    }
1871
    check = vvfat_read(s->bs,
1872
            s->first_sectors_number, s->fat2, s->sectors_per_fat);
1873
    if (check) {
1874
        fprintf(stderr, "Could not copy fat\n");
1875
        return 0;
1876
    }
1877
    assert (s->used_clusters);
1878
    for (i = 0; i < sector2cluster(s, s->sector_count); i++)
1879
        s->used_clusters[i] &= ~USED_ANY;
1880

    
1881
    clear_commits(s);
1882

    
1883
    /* mark every mapped file/directory as deleted.
1884
     * (check_directory_consistency() will unmark those still present). */
1885
    if (s->qcow)
1886
        for (i = 0; i < s->mapping.next; i++) {
1887
            mapping_t* mapping = array_get(&(s->mapping), i);
1888
            if (mapping->first_mapping_index < 0)
1889
                mapping->mode |= MODE_DELETED;
1890
        }
1891

    
1892
    used_clusters_count = check_directory_consistency(s, 0, s->path);
1893
    if (used_clusters_count <= 0) {
1894
        DLOG(fprintf(stderr, "problem in directory\n"));
1895
        return 0;
1896
    }
1897

    
1898
    check = s->last_cluster_of_root_directory;
1899
    for (i = check; i < sector2cluster(s, s->sector_count); i++) {
1900
        if (modified_fat_get(s, i)) {
1901
            if(!s->used_clusters[i]) {
1902
                DLOG(fprintf(stderr, "FAT was modified (%d), but cluster is not used?\n", i));
1903
                return 0;
1904
            }
1905
            check++;
1906
        }
1907

    
1908
        if (s->used_clusters[i] == USED_ALLOCATED) {
1909
            /* allocated, but not used... */
1910
            DLOG(fprintf(stderr, "unused, modified cluster: %d\n", i));
1911
            return 0;
1912
        }
1913
    }
1914

    
1915
    if (check != used_clusters_count)
1916
        return 0;
1917

    
1918
    return used_clusters_count;
1919
}
1920

    
1921
static inline void adjust_mapping_indices(BDRVVVFATState* s,
1922
        int offset, int adjust)
1923
{
1924
    int i;
1925

    
1926
    for (i = 0; i < s->mapping.next; i++) {
1927
        mapping_t* mapping = array_get(&(s->mapping), i);
1928

    
1929
#define ADJUST_MAPPING_INDEX(name) \
1930
        if (mapping->name >= offset) \
1931
            mapping->name += adjust
1932

    
1933
        ADJUST_MAPPING_INDEX(first_mapping_index);
1934
        if (mapping->mode & MODE_DIRECTORY)
1935
            ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
1936
    }
1937
}
1938

    
1939
/* insert or update mapping */
1940
static mapping_t* insert_mapping(BDRVVVFATState* s,
1941
        uint32_t begin, uint32_t end)
1942
{
1943
    /*
1944
     * - find mapping where mapping->begin >= begin,
1945
     * - if mapping->begin > begin: insert
1946
     *   - adjust all references to mappings!
1947
     * - else: adjust
1948
     * - replace name
1949
     */
1950
    int index = find_mapping_for_cluster_aux(s, begin, 0, s->mapping.next);
1951
    mapping_t* mapping = NULL;
1952
    mapping_t* first_mapping = array_get(&(s->mapping), 0);
1953

    
1954
    if (index < s->mapping.next && (mapping = array_get(&(s->mapping), index))
1955
            && mapping->begin < begin) {
1956
        mapping->end = begin;
1957
        index++;
1958
        mapping = array_get(&(s->mapping), index);
1959
    }
1960
    if (index >= s->mapping.next || mapping->begin > begin) {
1961
        mapping = array_insert(&(s->mapping), index, 1);
1962
        mapping->path = NULL;
1963
        adjust_mapping_indices(s, index, +1);
1964
    }
1965

    
1966
    mapping->begin = begin;
1967
    mapping->end = end;
1968

    
1969
DLOG(mapping_t* next_mapping;
1970
assert(index + 1 >= s->mapping.next ||
1971
((next_mapping = array_get(&(s->mapping), index + 1)) &&
1972
 next_mapping->begin >= end)));
1973

    
1974
    if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1975
        s->current_mapping = array_get(&(s->mapping),
1976
                s->current_mapping - first_mapping);
1977

    
1978
    return mapping;
1979
}
1980

    
1981
static int remove_mapping(BDRVVVFATState* s, int mapping_index)
1982
{
1983
    mapping_t* mapping = array_get(&(s->mapping), mapping_index);
1984
    mapping_t* first_mapping = array_get(&(s->mapping), 0);
1985

    
1986
    /* free mapping */
1987
    if (mapping->first_mapping_index < 0)
1988
        free(mapping->path);
1989

    
1990
    /* remove from s->mapping */
1991
    array_remove(&(s->mapping), mapping_index);
1992

    
1993
    /* adjust all references to mappings */
1994
    adjust_mapping_indices(s, mapping_index, -1);
1995

    
1996
    if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1997
        s->current_mapping = array_get(&(s->mapping),
1998
                s->current_mapping - first_mapping);
1999

    
2000
    return 0;
2001
}
2002

    
2003
static void adjust_dirindices(BDRVVVFATState* s, int offset, int adjust)
2004
{
2005
    int i;
2006
    for (i = 0; i < s->mapping.next; i++) {
2007
        mapping_t* mapping = array_get(&(s->mapping), i);
2008
        if (mapping->dir_index >= offset)
2009
            mapping->dir_index += adjust;
2010
        if ((mapping->mode & MODE_DIRECTORY) &&
2011
                mapping->info.dir.first_dir_index >= offset)
2012
            mapping->info.dir.first_dir_index += adjust;
2013
    }
2014
}
2015

    
2016
static direntry_t* insert_direntries(BDRVVVFATState* s,
2017
        int dir_index, int count)
2018
{
2019
    /*
2020
     * make room in s->directory,
2021
     * adjust_dirindices
2022
     */
2023
    direntry_t* result = array_insert(&(s->directory), dir_index, count);
2024
    if (result == NULL)
2025
        return NULL;
2026
    adjust_dirindices(s, dir_index, count);
2027
    return result;
2028
}
2029

    
2030
static int remove_direntries(BDRVVVFATState* s, int dir_index, int count)
2031
{
2032
    int ret = array_remove_slice(&(s->directory), dir_index, count);
2033
    if (ret)
2034
        return ret;
2035
    adjust_dirindices(s, dir_index, -count);
2036
    return 0;
2037
}
2038

    
2039
/*
2040
 * Adapt the mappings of the cluster chain starting at first cluster
2041
 * (i.e. if a file starts at first_cluster, the chain is followed according
2042
 * to the modified fat, and the corresponding entries in s->mapping are
2043
 * adjusted)
2044
 */
2045
static int commit_mappings(BDRVVVFATState* s,
2046
        uint32_t first_cluster, int dir_index)
2047
{
2048
    mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2049
    direntry_t* direntry = array_get(&(s->directory), dir_index);
2050
    uint32_t cluster = first_cluster;
2051

    
2052
    vvfat_close_current_file(s);
2053

    
2054
    assert(mapping);
2055
    assert(mapping->begin == first_cluster);
2056
    mapping->first_mapping_index = -1;
2057
    mapping->dir_index = dir_index;
2058
    mapping->mode = (dir_index <= 0 || is_directory(direntry)) ?
2059
        MODE_DIRECTORY : MODE_NORMAL;
2060

    
2061
    while (!fat_eof(s, cluster)) {
2062
        uint32_t c, c1;
2063

    
2064
        for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
2065
                c = c1, c1 = modified_fat_get(s, c1));
2066

    
2067
        c++;
2068
        if (c > mapping->end) {
2069
            int index = array_index(&(s->mapping), mapping);
2070
            int i, max_i = s->mapping.next - index;
2071
            for (i = 1; i < max_i && mapping[i].begin < c; i++);
2072
            while (--i > 0)
2073
                remove_mapping(s, index + 1);
2074
        }
2075
        assert(mapping == array_get(&(s->mapping), s->mapping.next - 1)
2076
                || mapping[1].begin >= c);
2077
        mapping->end = c;
2078

    
2079
        if (!fat_eof(s, c1)) {
2080
            int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next);
2081
            mapping_t* next_mapping = i >= s->mapping.next ? NULL :
2082
                array_get(&(s->mapping), i);
2083

    
2084
            if (next_mapping == NULL || next_mapping->begin > c1) {
2085
                int i1 = array_index(&(s->mapping), mapping);
2086

    
2087
                next_mapping = insert_mapping(s, c1, c1+1);
2088

    
2089
                if (c1 < c)
2090
                    i1++;
2091
                mapping = array_get(&(s->mapping), i1);
2092
            }
2093

    
2094
            next_mapping->dir_index = mapping->dir_index;
2095
            next_mapping->first_mapping_index =
2096
                mapping->first_mapping_index < 0 ?
2097
                array_index(&(s->mapping), mapping) :
2098
                mapping->first_mapping_index;
2099
            next_mapping->path = mapping->path;
2100
            next_mapping->mode = mapping->mode;
2101
            next_mapping->read_only = mapping->read_only;
2102
            if (mapping->mode & MODE_DIRECTORY) {
2103
                next_mapping->info.dir.parent_mapping_index =
2104
                        mapping->info.dir.parent_mapping_index;
2105
                next_mapping->info.dir.first_dir_index =
2106
                        mapping->info.dir.first_dir_index +
2107
                        0x10 * s->sectors_per_cluster *
2108
                        (mapping->end - mapping->begin);
2109
            } else
2110
                next_mapping->info.file.offset = mapping->info.file.offset +
2111
                        mapping->end - mapping->begin;
2112

    
2113
            mapping = next_mapping;
2114
        }
2115

    
2116
        cluster = c1;
2117
    }
2118

    
2119
    return 0;
2120
}
2121

    
2122
static int commit_direntries(BDRVVVFATState* s,
2123
        int dir_index, int parent_mapping_index)
2124
{
2125
    direntry_t* direntry = array_get(&(s->directory), dir_index);
2126
    uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
2127
    mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2128

    
2129
    int factor = 0x10 * s->sectors_per_cluster;
2130
    int old_cluster_count, new_cluster_count;
2131
    int current_dir_index = mapping->info.dir.first_dir_index;
2132
    int first_dir_index = current_dir_index;
2133
    int ret, i;
2134
    uint32_t c;
2135

    
2136
DLOG(fprintf(stderr, "commit_direntries for %s, parent_mapping_index %d\n", mapping->path, parent_mapping_index));
2137

    
2138
    assert(direntry);
2139
    assert(mapping);
2140
    assert(mapping->begin == first_cluster);
2141
    assert(mapping->info.dir.first_dir_index < s->directory.next);
2142
    assert(mapping->mode & MODE_DIRECTORY);
2143
    assert(dir_index == 0 || is_directory(direntry));
2144

    
2145
    mapping->info.dir.parent_mapping_index = parent_mapping_index;
2146

    
2147
    if (first_cluster == 0) {
2148
        old_cluster_count = new_cluster_count =
2149
            s->last_cluster_of_root_directory;
2150
    } else {
2151
        for (old_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2152
                c = fat_get(s, c))
2153
            old_cluster_count++;
2154

    
2155
        for (new_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2156
                c = modified_fat_get(s, c))
2157
            new_cluster_count++;
2158
    }
2159

    
2160
    if (new_cluster_count > old_cluster_count) {
2161
        if (insert_direntries(s,
2162
                current_dir_index + factor * old_cluster_count,
2163
                factor * (new_cluster_count - old_cluster_count)) == NULL)
2164
            return -1;
2165
    } else if (new_cluster_count < old_cluster_count)
2166
        remove_direntries(s,
2167
                current_dir_index + factor * new_cluster_count,
2168
                factor * (old_cluster_count - new_cluster_count));
2169

    
2170
    for (c = first_cluster; !fat_eof(s, c); c = modified_fat_get(s, c)) {
2171
        void* direntry = array_get(&(s->directory), current_dir_index);
2172
        int ret = vvfat_read(s->bs, cluster2sector(s, c), direntry,
2173
                s->sectors_per_cluster);
2174
        if (ret)
2175
            return ret;
2176
        assert(!strncmp(s->directory.pointer, "QEMU", 4));
2177
        current_dir_index += factor;
2178
    }
2179

    
2180
    ret = commit_mappings(s, first_cluster, dir_index);
2181
    if (ret)
2182
        return ret;
2183

    
2184
    /* recurse */
2185
    for (i = 0; i < factor * new_cluster_count; i++) {
2186
        direntry = array_get(&(s->directory), first_dir_index + i);
2187
        if (is_directory(direntry) && !is_dot(direntry)) {
2188
            mapping = find_mapping_for_cluster(s, first_cluster);
2189
            assert(mapping->mode & MODE_DIRECTORY);
2190
            ret = commit_direntries(s, first_dir_index + i,
2191
                array_index(&(s->mapping), mapping));
2192
            if (ret)
2193
                return ret;
2194
        }
2195
    }
2196

    
2197
    return 0;
2198
}
2199

    
2200
/* commit one file (adjust contents, adjust mapping),
2201
   return first_mapping_index */
2202
static int commit_one_file(BDRVVVFATState* s,
2203
        int dir_index, uint32_t offset)
2204
{
2205
    direntry_t* direntry = array_get(&(s->directory), dir_index);
2206
    uint32_t c = begin_of_direntry(direntry);
2207
    uint32_t first_cluster = c;
2208
    mapping_t* mapping = find_mapping_for_cluster(s, c);
2209
    uint32_t size = filesize_of_direntry(direntry);
2210
    char* cluster = malloc(s->cluster_size);
2211
    uint32_t i;
2212
    int fd = 0;
2213

    
2214
    assert(offset < size);
2215
    assert((offset % s->cluster_size) == 0);
2216

    
2217
    for (i = s->cluster_size; i < offset; i += s->cluster_size)
2218
        c = modified_fat_get(s, c);
2219

    
2220
    fd = open(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666);
2221
    if (fd < 0) {
2222
        fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path,
2223
                strerror(errno), errno);
2224
        return fd;
2225
    }
2226
    if (offset > 0)
2227
        if (lseek(fd, offset, SEEK_SET) != offset)
2228
            return -3;
2229

    
2230
    while (offset < size) {
2231
        uint32_t c1;
2232
        int rest_size = (size - offset > s->cluster_size ?
2233
                s->cluster_size : size - offset);
2234
        int ret;
2235

    
2236
        c1 = modified_fat_get(s, c);
2237

    
2238
        assert((size - offset == 0 && fat_eof(s, c)) ||
2239
                (size > offset && c >=2 && !fat_eof(s, c)));
2240
        assert(size >= 0);
2241

    
2242
        ret = vvfat_read(s->bs, cluster2sector(s, c),
2243
            (uint8_t*)cluster, (rest_size + 0x1ff) / 0x200);
2244

    
2245
        if (ret < 0)
2246
            return ret;
2247

    
2248
        if (write(fd, cluster, rest_size) < 0)
2249
            return -2;
2250

    
2251
        offset += rest_size;
2252
        c = c1;
2253
    }
2254

    
2255
    ftruncate(fd, size);
2256
    close(fd);
2257

    
2258
    return commit_mappings(s, first_cluster, dir_index);
2259
}
2260

    
2261
#ifdef DEBUG
2262
/* test, if all mappings point to valid direntries */
2263
static void check1(BDRVVVFATState* s)
2264
{
2265
    int i;
2266
    for (i = 0; i < s->mapping.next; i++) {
2267
        mapping_t* mapping = array_get(&(s->mapping), i);
2268
        if (mapping->mode & MODE_DELETED) {
2269
            fprintf(stderr, "deleted\n");
2270
            continue;
2271
        }
2272
        assert(mapping->dir_index >= 0);
2273
        assert(mapping->dir_index < s->directory.next);
2274
        direntry_t* direntry = array_get(&(s->directory), mapping->dir_index);
2275
        assert(mapping->begin == begin_of_direntry(direntry) || mapping->first_mapping_index >= 0);
2276
        if (mapping->mode & MODE_DIRECTORY) {
2277
            assert(mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster * (mapping->end - mapping->begin) <= s->directory.next);
2278
            assert((mapping->info.dir.first_dir_index % (0x10 * s->sectors_per_cluster)) == 0);
2279
        }
2280
    }
2281
}
2282

    
2283
/* test, if all direntries have mappings */
2284
static void check2(BDRVVVFATState* s)
2285
{
2286
    int i;
2287
    int first_mapping = -1;
2288

    
2289
    for (i = 0; i < s->directory.next; i++) {
2290
        direntry_t* direntry = array_get(&(s->directory), i);
2291

    
2292
        if (is_short_name(direntry) && begin_of_direntry(direntry)) {
2293
            mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
2294
            assert(mapping);
2295
            assert(mapping->dir_index == i || is_dot(direntry));
2296
            assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry));
2297
        }
2298

    
2299
        if ((i % (0x10 * s->sectors_per_cluster)) == 0) {
2300
            /* cluster start */
2301
            int j, count = 0;
2302

    
2303
            for (j = 0; j < s->mapping.next; j++) {
2304
                mapping_t* mapping = array_get(&(s->mapping), j);
2305
                if (mapping->mode & MODE_DELETED)
2306
                    continue;
2307
                if (mapping->mode & MODE_DIRECTORY) {
2308
                    if (mapping->info.dir.first_dir_index <= i && mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster > i) {
2309
                        assert(++count == 1);
2310
                        if (mapping->first_mapping_index == -1)
2311
                            first_mapping = array_index(&(s->mapping), mapping);
2312
                        else
2313
                            assert(first_mapping == mapping->first_mapping_index);
2314
                        if (mapping->info.dir.parent_mapping_index < 0)
2315
                            assert(j == 0);
2316
                        else {
2317
                            mapping_t* parent = array_get(&(s->mapping), mapping->info.dir.parent_mapping_index);
2318
                            assert(parent->mode & MODE_DIRECTORY);
2319
                            assert(parent->info.dir.first_dir_index < mapping->info.dir.first_dir_index);
2320
                        }
2321
                    }
2322
                }
2323
            }
2324
            if (count == 0)
2325
                first_mapping = -1;
2326
        }
2327
    }
2328
}
2329
#endif
2330

    
2331
static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2332
{
2333
    int i;
2334

    
2335
#ifdef DEBUG
2336
    fprintf(stderr, "handle_renames\n");
2337
    for (i = 0; i < s->commits.next; i++) {
2338
        commit_t* commit = array_get(&(s->commits), i);
2339
        fprintf(stderr, "%d, %s (%d, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action);
2340
    }
2341
#endif
2342

    
2343
    for (i = 0; i < s->commits.next;) {
2344
        commit_t* commit = array_get(&(s->commits), i);
2345
        if (commit->action == ACTION_RENAME) {
2346
            mapping_t* mapping = find_mapping_for_cluster(s,
2347
                    commit->param.rename.cluster);
2348
            char* old_path = mapping->path;
2349

    
2350
            assert(commit->path);
2351
            mapping->path = commit->path;
2352
            if (rename(old_path, mapping->path))
2353
                return -2;
2354

    
2355
            if (mapping->mode & MODE_DIRECTORY) {
2356
                int l1 = strlen(mapping->path);
2357
                int l2 = strlen(old_path);
2358
                int diff = l1 - l2;
2359
                direntry_t* direntry = array_get(&(s->directory),
2360
                        mapping->info.dir.first_dir_index);
2361
                uint32_t c = mapping->begin;
2362
                int i = 0;
2363

    
2364
                /* recurse */
2365
                while (!fat_eof(s, c)) {
2366
                    do {
2367
                        direntry_t* d = direntry + i;
2368

    
2369
                        if (is_file(d) || (is_directory(d) && !is_dot(d))) {
2370
                            mapping_t* m = find_mapping_for_cluster(s,
2371
                                    begin_of_direntry(d));
2372
                            int l = strlen(m->path);
2373
                            char* new_path = malloc(l + diff + 1);
2374

    
2375
                            assert(!strncmp(m->path, mapping->path, l2));
2376

    
2377
                            strcpy(new_path, mapping->path);
2378
                            strcpy(new_path + l1, m->path + l2);
2379

    
2380
                            schedule_rename(s, m->begin, new_path);
2381
                        }
2382
                        i++;
2383
                    } while((i % (0x10 * s->sectors_per_cluster)) != 0);
2384
                    c = fat_get(s, c);
2385
                }
2386
            }
2387

    
2388
            free(old_path);
2389
            array_remove(&(s->commits), i);
2390
            continue;
2391
        } else if (commit->action == ACTION_MKDIR) {
2392
            mapping_t* mapping;
2393
            int j, parent_path_len;
2394

    
2395
#ifdef __MINGW32__
2396
            if (mkdir(commit->path))
2397
                return -5;
2398
#else
2399
            if (mkdir(commit->path, 0755))
2400
                return -5;
2401
#endif
2402

    
2403
            mapping = insert_mapping(s, commit->param.mkdir.cluster,
2404
                    commit->param.mkdir.cluster + 1);
2405
            if (mapping == NULL)
2406
                return -6;
2407

    
2408
            mapping->mode = MODE_DIRECTORY;
2409
            mapping->read_only = 0;
2410
            mapping->path = commit->path;
2411
            j = s->directory.next;
2412
            assert(j);
2413
            insert_direntries(s, s->directory.next,
2414
                    0x10 * s->sectors_per_cluster);
2415
            mapping->info.dir.first_dir_index = j;
2416

    
2417
            parent_path_len = strlen(commit->path)
2418
                - strlen(get_basename(commit->path)) - 1;
2419
            for (j = 0; j < s->mapping.next; j++) {
2420
                mapping_t* m = array_get(&(s->mapping), j);
2421
                if (m->first_mapping_index < 0 && m != mapping &&
2422
                        !strncmp(m->path, mapping->path, parent_path_len) &&
2423
                        strlen(m->path) == parent_path_len)
2424
                    break;
2425
            }
2426
            assert(j < s->mapping.next);
2427
            mapping->info.dir.parent_mapping_index = j;
2428

    
2429
            array_remove(&(s->commits), i);
2430
            continue;
2431
        }
2432

    
2433
        i++;
2434
    }
2435
    return 0;
2436
}
2437

    
2438
/*
2439
 * TODO: make sure that the short name is not matching *another* file
2440
 */
2441
static int handle_commits(BDRVVVFATState* s)
2442
{
2443
    int i, fail = 0;
2444

    
2445
    vvfat_close_current_file(s);
2446

    
2447
    for (i = 0; !fail && i < s->commits.next; i++) {
2448
        commit_t* commit = array_get(&(s->commits), i);
2449
        switch(commit->action) {
2450
        case ACTION_RENAME: case ACTION_MKDIR:
2451
            assert(0);
2452
            fail = -2;
2453
            break;
2454
        case ACTION_WRITEOUT: {
2455
            direntry_t* entry = array_get(&(s->directory),
2456
                    commit->param.writeout.dir_index);
2457
            uint32_t begin = begin_of_direntry(entry);
2458
            mapping_t* mapping = find_mapping_for_cluster(s, begin);
2459

    
2460
            assert(mapping);
2461
            assert(mapping->begin == begin);
2462
            assert(commit->path == NULL);
2463

    
2464
            if (commit_one_file(s, commit->param.writeout.dir_index,
2465
                        commit->param.writeout.modified_offset))
2466
                fail = -3;
2467

    
2468
            break;
2469
        }
2470
        case ACTION_NEW_FILE: {
2471
            int begin = commit->param.new_file.first_cluster;
2472
            mapping_t* mapping = find_mapping_for_cluster(s, begin);
2473
            direntry_t* entry;
2474
            int i;
2475

    
2476
            /* find direntry */
2477
            for (i = 0; i < s->directory.next; i++) {
2478
                entry = array_get(&(s->directory), i);
2479
                if (is_file(entry) && begin_of_direntry(entry) == begin)
2480
                    break;
2481
            }
2482

    
2483
            if (i >= s->directory.next) {
2484
                fail = -6;
2485
                continue;
2486
            }
2487

    
2488
            /* make sure there exists an initial mapping */
2489
            if (mapping && mapping->begin != begin) {
2490
                mapping->end = begin;
2491
                mapping = NULL;
2492
            }
2493
            if (mapping == NULL) {
2494
                mapping = insert_mapping(s, begin, begin+1);
2495
            }
2496
            /* most members will be fixed in commit_mappings() */
2497
            assert(commit->path);
2498
            mapping->path = commit->path;
2499
            mapping->read_only = 0;
2500
            mapping->mode = MODE_NORMAL;
2501
            mapping->info.file.offset = 0;
2502

    
2503
            if (commit_one_file(s, i, 0))
2504
                fail = -7;
2505

    
2506
            break;
2507
        }
2508
        default:
2509
            assert(0);
2510
        }
2511
    }
2512
    if (i > 0 && array_remove_slice(&(s->commits), 0, i))
2513
        return -1;
2514
    return fail;
2515
}
2516

    
2517
static int handle_deletes(BDRVVVFATState* s)
2518
{
2519
    int i, deferred = 1, deleted = 1;
2520

    
2521
    /* delete files corresponding to mappings marked as deleted */
2522
    /* handle DELETEs and unused mappings (modified_fat_get(s, mapping->begin) == 0) */
2523
    while (deferred && deleted) {
2524
        deferred = 0;
2525
        deleted = 0;
2526

    
2527
        for (i = 1; i < s->mapping.next; i++) {
2528
            mapping_t* mapping = array_get(&(s->mapping), i);
2529
            if (mapping->mode & MODE_DELETED) {
2530
                direntry_t* entry = array_get(&(s->directory),
2531
                        mapping->dir_index);
2532

    
2533
                if (is_free(entry)) {
2534
                    /* remove file/directory */
2535
                    if (mapping->mode & MODE_DIRECTORY) {
2536
                        int j, next_dir_index = s->directory.next,
2537
                        first_dir_index = mapping->info.dir.first_dir_index;
2538

    
2539
                        if (rmdir(mapping->path) < 0) {
2540
                            if (errno == ENOTEMPTY) {
2541
                                deferred++;
2542
                                continue;
2543
                            } else
2544
                                return -5;
2545
                        }
2546

    
2547
                        for (j = 1; j < s->mapping.next; j++) {
2548
                            mapping_t* m = array_get(&(s->mapping), j);
2549
                            if (m->mode & MODE_DIRECTORY &&
2550
                                    m->info.dir.first_dir_index >
2551
                                    first_dir_index &&
2552
                                    m->info.dir.first_dir_index <
2553
                                    next_dir_index)
2554
                                next_dir_index =
2555
                                    m->info.dir.first_dir_index;
2556
                        }
2557
                        remove_direntries(s, first_dir_index,
2558
                                next_dir_index - first_dir_index);
2559

    
2560
                        deleted++;
2561
                    }
2562
                } else {
2563
                    if (unlink(mapping->path))
2564
                        return -4;
2565
                    deleted++;
2566
                }
2567
                DLOG(fprintf(stderr, "DELETE (%d)\n", i); print_mapping(mapping); print_direntry(entry));
2568
                remove_mapping(s, i);
2569
            }
2570
        }
2571
    }
2572

    
2573
    return 0;
2574
}
2575

    
2576
/*
2577
 * synchronize mapping with new state:
2578
 *
2579
 * - copy FAT (with bdrv_read)
2580
 * - mark all filenames corresponding to mappings as deleted
2581
 * - recurse direntries from root (using bs->bdrv_read)
2582
 * - delete files corresponding to mappings marked as deleted
2583
 */
2584
static int do_commit(BDRVVVFATState* s)
2585
{
2586
    int ret = 0;
2587

    
2588
    /* the real meat are the commits. Nothing to do? Move along! */
2589
    if (s->commits.next == 0)
2590
        return 0;
2591

    
2592
    vvfat_close_current_file(s);
2593

    
2594
    ret = handle_renames_and_mkdirs(s);
2595
    if (ret) {
2596
        fprintf(stderr, "Error handling renames (%d)\n", ret);
2597
        assert(0);
2598
        return ret;
2599
    }
2600

    
2601
    /* copy FAT (with bdrv_read) */
2602
    memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
2603

    
2604
    /* recurse direntries from root (using bs->bdrv_read) */
2605
    ret = commit_direntries(s, 0, -1);
2606
    if (ret) {
2607
        fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
2608
        assert(0);
2609
        return ret;
2610
    }
2611

    
2612
    ret = handle_commits(s);
2613
    if (ret) {
2614
        fprintf(stderr, "Error handling commits (%d)\n", ret);
2615
        assert(0);
2616
        return ret;
2617
    }
2618

    
2619
    ret = handle_deletes(s);
2620
    if (ret) {
2621
        fprintf(stderr, "Error deleting\n");
2622
        assert(0);
2623
        return ret;
2624
    }
2625

    
2626
    s->qcow->drv->bdrv_make_empty(s->qcow);
2627

    
2628
    memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
2629

    
2630
DLOG(checkpoint());
2631
    return 0;
2632
}
2633

    
2634
static int try_commit(BDRVVVFATState* s)
2635
{
2636
    vvfat_close_current_file(s);
2637
DLOG(checkpoint());
2638
    if(!is_consistent(s))
2639
        return -1;
2640
    return do_commit(s);
2641
}
2642

    
2643
static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
2644
                    const uint8_t *buf, int nb_sectors)
2645
{
2646
    BDRVVVFATState *s = bs->opaque;
2647
    int i, ret;
2648

    
2649
DLOG(checkpoint());
2650

    
2651
    vvfat_close_current_file(s);
2652

    
2653
    /*
2654
     * Some sanity checks:
2655
     * - do not allow writing to the boot sector
2656
     * - do not allow to write non-ASCII filenames
2657
     */
2658

    
2659
    if (sector_num < s->first_sectors_number)
2660
        return -1;
2661

    
2662
    for (i = sector2cluster(s, sector_num);
2663
            i <= sector2cluster(s, sector_num + nb_sectors - 1);) {
2664
        mapping_t* mapping = find_mapping_for_cluster(s, i);
2665
        if (mapping) {
2666
            if (mapping->read_only) {
2667
                fprintf(stderr, "Tried to write to write-protected file %s\n",
2668
                        mapping->path);
2669
                return -1;
2670
            }
2671

    
2672
            if (mapping->mode & MODE_DIRECTORY) {
2673
                int begin = cluster2sector(s, i);
2674
                int end = begin + s->sectors_per_cluster, k;
2675
                int dir_index;
2676
                const direntry_t* direntries;
2677
                long_file_name lfn;
2678

    
2679
                lfn_init(&lfn);
2680

    
2681
                if (begin < sector_num)
2682
                    begin = sector_num;
2683
                if (end > sector_num + nb_sectors)
2684
                    end = sector_num + nb_sectors;
2685
                dir_index  = mapping->dir_index +
2686
                    0x10 * (begin - mapping->begin * s->sectors_per_cluster);
2687
                direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
2688

    
2689
                for (k = 0; k < (end - begin) * 0x10; k++) {
2690
                    /* do not allow non-ASCII filenames */
2691
                    if (parse_long_name(&lfn, direntries + k) < 0) {
2692
                        fprintf(stderr, "Warning: non-ASCII filename\n");
2693
                        return -1;
2694
                    }
2695
                    /* no access to the direntry of a read-only file */
2696
                    else if (is_short_name(direntries+k) &&
2697
                            (direntries[k].attributes & 1)) {
2698
                        if (memcmp(direntries + k,
2699
                                    array_get(&(s->directory), dir_index + k),
2700
                                    sizeof(direntry_t))) {
2701
                            fprintf(stderr, "Warning: tried to write to write-protected file\n");
2702
                            return -1;
2703
                        }
2704
                    }
2705
                }
2706
            }
2707
            i = mapping->end;
2708
        } else
2709
            i++;
2710
    }
2711

    
2712
    /*
2713
     * Use qcow backend. Commit later.
2714
     */
2715
DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
2716
    ret = s->qcow->drv->bdrv_write(s->qcow, sector_num, buf, nb_sectors);
2717
    if (ret < 0) {
2718
        fprintf(stderr, "Error writing to qcow backend\n");
2719
        return ret;
2720
    }
2721

    
2722
    for (i = sector2cluster(s, sector_num);
2723
            i <= sector2cluster(s, sector_num + nb_sectors - 1); i++)
2724
        if (i >= 0)
2725
            s->used_clusters[i] |= USED_ALLOCATED;
2726

    
2727
DLOG(checkpoint());
2728
    /* TODO: add timeout */
2729
    try_commit(s);
2730

    
2731
DLOG(checkpoint());
2732
    return 0;
2733
}
2734

    
2735
static int vvfat_is_allocated(BlockDriverState *bs,
2736
        int64_t sector_num, int nb_sectors, int* n)
2737
{
2738
    BDRVVVFATState* s = bs->opaque;
2739
    *n = s->sector_count - sector_num;
2740
    if (*n > nb_sectors)
2741
        *n = nb_sectors;
2742
    else if (*n < 0)
2743
        return 0;
2744
    return 1;
2745
}
2746

    
2747
static int write_target_commit(BlockDriverState *bs, int64_t sector_num,
2748
        const uint8_t* buffer, int nb_sectors) {
2749
    BDRVVVFATState* s = bs->opaque;
2750
    return try_commit(s);
2751
}
2752

    
2753
static void write_target_close(BlockDriverState *bs) {
2754
    BDRVVVFATState* s = bs->opaque;
2755
    bdrv_delete(s->qcow);
2756
    free(s->qcow_filename);
2757
}
2758

    
2759
static BlockDriver vvfat_write_target = {
2760
    "vvfat_write_target", 0, NULL, NULL, NULL,
2761
    write_target_commit,
2762
    write_target_close,
2763
    NULL, NULL, NULL
2764
};
2765

    
2766
static int enable_write_target(BDRVVVFATState *s)
2767
{
2768
    int size = sector2cluster(s, s->sector_count);
2769
    s->used_clusters = calloc(size, 1);
2770

    
2771
    array_init(&(s->commits), sizeof(commit_t));
2772

    
2773
    s->qcow_filename = malloc(1024);
2774
    get_tmp_filename(s->qcow_filename, 1024);
2775
    if (bdrv_create(&bdrv_qcow,
2776
                s->qcow_filename, s->sector_count, "fat:", 0) < 0)
2777
        return -1;
2778
    s->qcow = bdrv_new("");
2779
    if (s->qcow == NULL || bdrv_open(s->qcow, s->qcow_filename, 0) < 0)
2780
        return -1;
2781

    
2782
#ifndef _WIN32
2783
    unlink(s->qcow_filename);
2784
#endif
2785

    
2786
    s->bs->backing_hd = calloc(sizeof(BlockDriverState), 1);
2787
    s->bs->backing_hd->drv = &vvfat_write_target;
2788
    s->bs->backing_hd->opaque = s;
2789

    
2790
    return 0;
2791
}
2792

    
2793
static void vvfat_close(BlockDriverState *bs)
2794
{
2795
    BDRVVVFATState *s = bs->opaque;
2796

    
2797
    vvfat_close_current_file(s);
2798
    array_free(&(s->fat));
2799
    array_free(&(s->directory));
2800
    array_free(&(s->mapping));
2801
    if(s->cluster_buffer)
2802
        free(s->cluster_buffer);
2803
}
2804

    
2805
BlockDriver bdrv_vvfat = {
2806
    "vvfat",
2807
    sizeof(BDRVVVFATState),
2808
    NULL, /* no probe for protocols */
2809
    vvfat_open,
2810
    vvfat_read,
2811
    vvfat_write,
2812
    vvfat_close,
2813
    NULL, /* ??? Not sure if we can do any meaningful flushing.  */
2814
    NULL,
2815
    vvfat_is_allocated,
2816
    .protocol_name = "fat",
2817
};
2818

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