Statistics
| Branch: | Revision:

root / block / vvfat.c @ 5c171afa

History | View | Annotate | Download (81.3 kB)

1
/* vim:set shiftwidth=4 ts=8: */
2
/*
3
 * QEMU Block driver for virtual VFAT (shadows a local directory)
4
 *
5
 * Copyright (c) 2004,2005 Johannes E. Schindelin
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
 * THE SOFTWARE.
24
 */
25
#include <sys/stat.h>
26
#include <dirent.h>
27
#include "qemu-common.h"
28
#include "block_int.h"
29
#include "module.h"
30
#include "migration.h"
31

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

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

    
47
/* #define DEBUG */
48

    
49
#ifdef DEBUG
50

    
51
#define DLOG(a) a
52

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

    
57
static void checkpoint(void);
58

    
59
#ifdef __MINGW32__
60
void nonono(const char* file, int line, const char* msg) {
61
    fprintf(stderr, "Nonono! %s:%d %s\n", file, line, msg);
62
    exit(-5);
63
}
64
#undef assert
65
#define assert(a) do {if (!(a)) nonono(__FILE__, __LINE__, #a);}while(0)
66
#endif
67

    
68
#else
69

    
70
#define DLOG(a)
71

    
72
#endif
73

    
74
/* dynamic array functions */
75
typedef struct array_t {
76
    char* pointer;
77
    unsigned int size,next,item_size;
78
} array_t;
79

    
80
static inline void array_init(array_t* array,unsigned int item_size)
81
{
82
    array->pointer = NULL;
83
    array->size=0;
84
    array->next=0;
85
    array->item_size=item_size;
86
}
87

    
88
static inline void array_free(array_t* array)
89
{
90
    g_free(array->pointer);
91
    array->size=array->next=0;
92
}
93

    
94
/* does not automatically grow */
95
static inline void* array_get(array_t* array,unsigned int index) {
96
    assert(index < array->next);
97
    return array->pointer + index * array->item_size;
98
}
99

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

    
111
    return 0;
112
}
113

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

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

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

    
124
    return result;
125
}
126

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

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

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

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

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

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

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

    
172
    g_free(buf);
173

    
174
    return 0;
175
}
176

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

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

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

    
202
/* These structures are used to fake a disk and the VFAT filesystem.
203
 * For this reason we need to use QEMU_PACKED. */
204

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

    
243
typedef struct {
244
    uint8_t head;
245
    uint8_t sector;
246
    uint8_t cylinder;
247
} mbr_chs_t;
248

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

    
258
typedef struct mbr_t {
259
    uint8_t ignored[0x1b8];
260
    uint32_t nt_id;
261
    uint8_t ignored2[2];
262
    partition_t partition[4];
263
    uint8_t magic[2];
264
} QEMU_PACKED mbr_t;
265

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

    
281
/* this structure are used to transparently access the files */
282

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

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

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

    
318
/* here begins the real VVFAT driver */
319

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

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

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

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

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

    
355
    Error *migration_blocker;
356
} BDRVVVFATState;
357

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

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

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

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

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

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

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

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

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

    
413
/* direntry functions */
414

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

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

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

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

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

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

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

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

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

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

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

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

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

    
508
/* fat functions */
509

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

    
515
    for(i=0;i<11;i++) {
516
        unsigned char c;
517

    
518
        c = (i < 8) ? entry->name[i] : entry->extension[i-8];
519
        chksum=(((chksum&0xfe)>>1)|((chksum&0x01)?0x80:0)) + c;
520
    }
521

    
522
    return chksum;
523
}
524

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

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

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

    
578
static inline int fat_eof(BDRVVVFATState* s,uint32_t fat_entry)
579
{
580
    if(fat_entry>s->max_fat_value-8)
581
        return -1;
582
    return 0;
583
}
584

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

    
598
    switch(s->fat_type) {
599
        case 12: s->max_fat_value=0xfff; break;
600
        case 16: s->max_fat_value=0xffff; break;
601
        case 32: s->max_fat_value=0x0fffffff; break;
602
        default: s->max_fat_value=0; /* error... */
603
    }
604

    
605
}
606

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

    
616
    if(is_dot) {
617
        entry=array_get_next(&(s->directory));
618
        memset(entry->name,0x20,11);
619
        memcpy(entry->name,filename,strlen(filename));
620
        return entry;
621
    }
622

    
623
    entry_long=create_long_filename(s,filename);
624

    
625
    i = strlen(filename);
626
    for(j = i - 1; j>0  && filename[j]!='.';j--);
627
    if (j > 0)
628
        i = (j > 8 ? 8 : j);
629
    else if (i > 8)
630
        i = 8;
631

    
632
    entry=array_get_next(&(s->directory));
633
    memset(entry->name,0x20,11);
634
    memcpy(entry->name, filename, i);
635

    
636
    if(j > 0)
637
        for (i = 0; i < 3 && filename[j+1+i]; i++)
638
            entry->extension[i] = filename[j+1+i];
639

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

    
650
    /* mangle duplicates */
651
    while(1) {
652
        direntry_t* entry1=array_get(&(s->directory),directory_start);
653
        int j;
654

    
655
        for(;entry1<entry;entry1++)
656
            if(!is_long_name(entry1) && !memcmp(entry1->name,entry->name,11))
657
                break; /* found dupe */
658
        if(entry1==entry) /* no dupe found */
659
            break;
660

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

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

    
679
    /* calculate checksum; propagate to long name */
680
    if(entry_long) {
681
        uint8_t chksum=fat_chksum(entry);
682

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

    
691
    return entry;
692
}
693

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

    
708
    DIR* dir=opendir(dirname);
709
    struct dirent* entry;
710
    int i;
711

    
712
    assert(mapping->mode & MODE_DIRECTORY);
713

    
714
    if(!dir) {
715
        mapping->end = mapping->begin;
716
        return -1;
717
    }
718

    
719
    i = mapping->info.dir.first_dir_index =
720
            first_cluster == 0 ? 0 : s->directory.next;
721

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

    
731
        if(first_cluster == 0 && (is_dotdot || is_dot))
732
            continue;
733

    
734
        buffer=(char*)g_malloc(length);
735
        snprintf(buffer,length,"%s/%s",dirname,entry->d_name);
736

    
737
        if(stat(buffer,&st)<0) {
738
            g_free(buffer);
739
            continue;
740
        }
741

    
742
        /* create directory entry for this file */
743
        direntry=create_short_and_long_name(s, i, entry->d_name,
744
                is_dot || is_dotdot);
745
        direntry->attributes=(S_ISDIR(st.st_mode)?0x10:0x20);
746
        direntry->reserved[0]=direntry->reserved[1]=0;
747
        direntry->ctime=fat_datetime(st.st_ctime,1);
748
        direntry->cdate=fat_datetime(st.st_ctime,0);
749
        direntry->adate=fat_datetime(st.st_atime,0);
750
        direntry->begin_hi=0;
751
        direntry->mtime=fat_datetime(st.st_mtime,1);
752
        direntry->mdate=fat_datetime(st.st_mtime,0);
753
        if(is_dotdot)
754
            set_begin_of_direntry(direntry, first_cluster_of_parent);
755
        else if(is_dot)
756
            set_begin_of_direntry(direntry, first_cluster);
757
        else
758
            direntry->begin=0; /* do that later */
759
        if (st.st_size > 0x7fffffff) {
760
            fprintf(stderr, "File %s is larger than 2GB\n", buffer);
761
            g_free(buffer);
762
            closedir(dir);
763
            return -2;
764
        }
765
        direntry->size=cpu_to_le32(S_ISDIR(st.st_mode)?0:st.st_size);
766

    
767
        /* create mapping for this file */
768
        if(!is_dot && !is_dotdot && (S_ISDIR(st.st_mode) || st.st_size)) {
769
            s->current_mapping=(mapping_t*)array_get_next(&(s->mapping));
770
            s->current_mapping->begin=0;
771
            s->current_mapping->end=st.st_size;
772
            /*
773
             * we get the direntry of the most recent direntry, which
774
             * contains the short name and all the relevant information.
775
             */
776
            s->current_mapping->dir_index=s->directory.next-1;
777
            s->current_mapping->first_mapping_index = -1;
778
            if (S_ISDIR(st.st_mode)) {
779
                s->current_mapping->mode = MODE_DIRECTORY;
780
                s->current_mapping->info.dir.parent_mapping_index =
781
                    mapping_index;
782
            } else {
783
                s->current_mapping->mode = MODE_UNDEFINED;
784
                s->current_mapping->info.file.offset = 0;
785
            }
786
            s->current_mapping->path=buffer;
787
            s->current_mapping->read_only =
788
                (st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0;
789
        }
790
    }
791
    closedir(dir);
792

    
793
    /* fill with zeroes up to the end of the cluster */
794
    while(s->directory.next%(0x10*s->sectors_per_cluster)) {
795
        direntry_t* direntry=array_get_next(&(s->directory));
796
        memset(direntry,0,sizeof(direntry_t));
797
    }
798

    
799
/* TODO: if there are more entries, bootsector has to be adjusted! */
800
#define ROOT_ENTRIES (0x02 * 0x10 * s->sectors_per_cluster)
801
    if (mapping_index == 0 && s->directory.next < ROOT_ENTRIES) {
802
        /* root directory */
803
        int cur = s->directory.next;
804
        array_ensure_allocated(&(s->directory), ROOT_ENTRIES - 1);
805
        s->directory.next = ROOT_ENTRIES;
806
        memset(array_get(&(s->directory), cur), 0,
807
                (ROOT_ENTRIES - cur) * sizeof(direntry_t));
808
    }
809

    
810
     /* reget the mapping, since s->mapping was possibly realloc()ed */
811
    mapping = (mapping_t*)array_get(&(s->mapping), mapping_index);
812
    first_cluster += (s->directory.next - mapping->info.dir.first_dir_index)
813
        * 0x20 / s->cluster_size;
814
    mapping->end = first_cluster;
815

    
816
    direntry = (direntry_t*)array_get(&(s->directory), mapping->dir_index);
817
    set_begin_of_direntry(direntry, mapping->begin);
818

    
819
    return 0;
820
}
821

    
822
static inline uint32_t sector2cluster(BDRVVVFATState* s,off_t sector_num)
823
{
824
    return (sector_num-s->faked_sectors)/s->sectors_per_cluster;
825
}
826

    
827
static inline off_t cluster2sector(BDRVVVFATState* s, uint32_t cluster_num)
828
{
829
    return s->faked_sectors + s->sectors_per_cluster * cluster_num;
830
}
831

    
832
static int init_directories(BDRVVVFATState* s,
833
        const char* dirname)
834
{
835
    bootsector_t* bootsector;
836
    mapping_t* mapping;
837
    unsigned int i;
838
    unsigned int cluster;
839

    
840
    memset(&(s->first_sectors[0]),0,0x40*0x200);
841

    
842
    s->cluster_size=s->sectors_per_cluster*0x200;
843
    s->cluster_buffer=g_malloc(s->cluster_size);
844

    
845
    /*
846
     * The formula: sc = spf+1+spf*spc*(512*8/fat_type),
847
     * where sc is sector_count,
848
     * spf is sectors_per_fat,
849
     * spc is sectors_per_clusters, and
850
     * fat_type = 12, 16 or 32.
851
     */
852
    i = 1+s->sectors_per_cluster*0x200*8/s->fat_type;
853
    s->sectors_per_fat=(s->sector_count+i)/i; /* round up */
854

    
855
    array_init(&(s->mapping),sizeof(mapping_t));
856
    array_init(&(s->directory),sizeof(direntry_t));
857

    
858
    /* add volume label */
859
    {
860
        direntry_t* entry=array_get_next(&(s->directory));
861
        entry->attributes=0x28; /* archive | volume label */
862
        memcpy(entry->name,"QEMU VVF",8);
863
        memcpy(entry->extension,"AT ",3);
864
    }
865

    
866
    /* Now build FAT, and write back information into directory */
867
    init_fat(s);
868

    
869
    s->faked_sectors=s->first_sectors_number+s->sectors_per_fat*2;
870
    s->cluster_count=sector2cluster(s, s->sector_count);
871

    
872
    mapping = array_get_next(&(s->mapping));
873
    mapping->begin = 0;
874
    mapping->dir_index = 0;
875
    mapping->info.dir.parent_mapping_index = -1;
876
    mapping->first_mapping_index = -1;
877
    mapping->path = g_strdup(dirname);
878
    i = strlen(mapping->path);
879
    if (i > 0 && mapping->path[i - 1] == '/')
880
        mapping->path[i - 1] = '\0';
881
    mapping->mode = MODE_DIRECTORY;
882
    mapping->read_only = 0;
883
    s->path = mapping->path;
884

    
885
    for (i = 0, cluster = 0; i < s->mapping.next; i++) {
886
        /* MS-DOS expects the FAT to be 0 for the root directory
887
         * (except for the media byte). */
888
        /* LATER TODO: still true for FAT32? */
889
        int fix_fat = (i != 0);
890
        mapping = array_get(&(s->mapping), i);
891

    
892
        if (mapping->mode & MODE_DIRECTORY) {
893
            mapping->begin = cluster;
894
            if(read_directory(s, i)) {
895
                fprintf(stderr, "Could not read directory %s\n",
896
                        mapping->path);
897
                return -1;
898
            }
899
            mapping = array_get(&(s->mapping), i);
900
        } else {
901
            assert(mapping->mode == MODE_UNDEFINED);
902
            mapping->mode=MODE_NORMAL;
903
            mapping->begin = cluster;
904
            if (mapping->end > 0) {
905
                direntry_t* direntry = array_get(&(s->directory),
906
                        mapping->dir_index);
907

    
908
                mapping->end = cluster + 1 + (mapping->end-1)/s->cluster_size;
909
                set_begin_of_direntry(direntry, mapping->begin);
910
            } else {
911
                mapping->end = cluster + 1;
912
                fix_fat = 0;
913
            }
914
        }
915

    
916
        assert(mapping->begin < mapping->end);
917

    
918
        /* next free cluster */
919
        cluster = mapping->end;
920

    
921
        if(cluster > s->cluster_count) {
922
            fprintf(stderr,"Directory does not fit in FAT%d (capacity %.2f MB)\n",
923
                    s->fat_type, s->sector_count / 2000.0);
924
            return -EINVAL;
925
        }
926

    
927
        /* fix fat for entry */
928
        if (fix_fat) {
929
            int j;
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

    
936
    mapping = array_get(&(s->mapping), 0);
937
    s->sectors_of_root_directory = mapping->end * s->sectors_per_cluster;
938
    s->last_cluster_of_root_directory = mapping->end;
939

    
940
    /* the FAT signature */
941
    fat_set(s,0,s->max_fat_value);
942
    fat_set(s,1,s->max_fat_value);
943

    
944
    s->current_mapping = NULL;
945

    
946
    bootsector=(bootsector_t*)(s->first_sectors+(s->first_sectors_number-1)*0x200);
947
    bootsector->jump[0]=0xeb;
948
    bootsector->jump[1]=0x3e;
949
    bootsector->jump[2]=0x90;
950
    memcpy(bootsector->name,"QEMU    ",8);
951
    bootsector->sector_size=cpu_to_le16(0x200);
952
    bootsector->sectors_per_cluster=s->sectors_per_cluster;
953
    bootsector->reserved_sectors=cpu_to_le16(1);
954
    bootsector->number_of_fats=0x2; /* number of FATs */
955
    bootsector->root_entries=cpu_to_le16(s->sectors_of_root_directory*0x10);
956
    bootsector->total_sectors16=s->sector_count>0xffff?0:cpu_to_le16(s->sector_count);
957
    bootsector->media_type=(s->first_sectors_number>1?0xf8:0xf0); /* media descriptor (f8=hd, f0=3.5 fd)*/
958
    s->fat.pointer[0] = bootsector->media_type;
959
    bootsector->sectors_per_fat=cpu_to_le16(s->sectors_per_fat);
960
    bootsector->sectors_per_track=cpu_to_le16(s->bs->secs);
961
    bootsector->number_of_heads=cpu_to_le16(s->bs->heads);
962
    bootsector->hidden_sectors=cpu_to_le32(s->first_sectors_number==1?0:0x3f);
963
    bootsector->total_sectors=cpu_to_le32(s->sector_count>0xffff?s->sector_count:0);
964

    
965
    /* LATER TODO: if FAT32, this is wrong */
966
    bootsector->u.fat16.drive_number=s->first_sectors_number==1?0:0x80; /* fda=0, hda=0x80 */
967
    bootsector->u.fat16.current_head=0;
968
    bootsector->u.fat16.signature=0x29;
969
    bootsector->u.fat16.id=cpu_to_le32(0xfabe1afd);
970

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

    
975
    return 0;
976
}
977

    
978
#ifdef DEBUG
979
static BDRVVVFATState *vvv = NULL;
980
#endif
981

    
982
static int enable_write_target(BDRVVVFATState *s);
983
static int is_consistent(BDRVVVFATState *s);
984

    
985
static void vvfat_rebind(BlockDriverState *bs)
986
{
987
    BDRVVVFATState *s = bs->opaque;
988
    s->bs = bs;
989
}
990

    
991
static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
992
{
993
    BDRVVVFATState *s = bs->opaque;
994
    int i;
995

    
996
#ifdef DEBUG
997
    vvv = s;
998
#endif
999

    
1000
DLOG(if (stderr == NULL) {
1001
    stderr = fopen("vvfat.log", "a");
1002
    setbuf(stderr, NULL);
1003
})
1004

    
1005
    s->bs = bs;
1006

    
1007
    /* LATER TODO: if FAT32, adjust */
1008
    s->sectors_per_cluster=0x10;
1009

    
1010
    s->current_cluster=0xffffffff;
1011

    
1012
    s->first_sectors_number=0x40;
1013
    /* read only is the default for safety */
1014
    bs->read_only = 1;
1015
    s->qcow = s->write_target = NULL;
1016
    s->qcow_filename = NULL;
1017
    s->fat2 = NULL;
1018
    s->downcase_short_names = 1;
1019

    
1020
    if (!strstart(dirname, "fat:", NULL))
1021
        return -1;
1022

    
1023
    if (strstr(dirname, ":32:")) {
1024
        fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. You are welcome to do so!\n");
1025
        s->fat_type = 32;
1026
    } else if (strstr(dirname, ":16:")) {
1027
        s->fat_type = 16;
1028
    } else if (strstr(dirname, ":12:")) {
1029
        s->fat_type = 12;
1030
    }
1031

    
1032
    if (strstr(dirname, ":floppy:")) {
1033
        /* 1.44MB or 2.88MB floppy.  2.88MB can be FAT12 (default) or FAT16. */
1034
        if (!s->fat_type) {
1035
            s->fat_type = 12;
1036
            bs->secs = 36;
1037
            s->sectors_per_cluster=2;
1038
        } else {
1039
            bs->secs=(s->fat_type == 12 ? 18 : 36);
1040
            s->sectors_per_cluster=1;
1041
        }
1042
        s->first_sectors_number = 1;
1043
        bs->cyls=80; bs->heads=2;
1044
    } else {
1045
        /* 32MB or 504MB disk*/
1046
        if (!s->fat_type) {
1047
            s->fat_type = 16;
1048
        }
1049
        bs->cyls=(s->fat_type == 12 ? 64 : 1024);
1050
        bs->heads=16; bs->secs=63;
1051
    }
1052

    
1053
    s->sector_count=bs->cyls*bs->heads*bs->secs-(s->first_sectors_number-1);
1054

    
1055
    if (strstr(dirname, ":rw:")) {
1056
        if (enable_write_target(s))
1057
            return -1;
1058
        bs->read_only = 0;
1059
    }
1060

    
1061
    i = strrchr(dirname, ':') - dirname;
1062
    assert(i >= 3);
1063
    if (dirname[i-2] == ':' && qemu_isalpha(dirname[i-1]))
1064
        /* workaround for DOS drive names */
1065
        dirname += i-1;
1066
    else
1067
        dirname += i+1;
1068

    
1069
    bs->total_sectors=bs->cyls*bs->heads*bs->secs;
1070

    
1071
    if(init_directories(s, dirname))
1072
        return -1;
1073

    
1074
    s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
1075

    
1076
    if(s->first_sectors_number==0x40)
1077
        init_mbr(s);
1078
    else {
1079
        /* MS-DOS does not like to know about CHS (?). */
1080
        bs->heads = bs->cyls = bs->secs = 0;
1081
    }
1082

    
1083
    //    assert(is_consistent(s));
1084
    qemu_co_mutex_init(&s->lock);
1085

    
1086
    /* Disable migration when vvfat is used rw */
1087
    if (s->qcow) {
1088
        error_set(&s->migration_blocker,
1089
                  QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
1090
                  "vvfat (rw)", bs->device_name, "live migration");
1091
        migrate_add_blocker(s->migration_blocker);
1092
    }
1093

    
1094
    return 0;
1095
}
1096

    
1097
static inline void vvfat_close_current_file(BDRVVVFATState *s)
1098
{
1099
    if(s->current_mapping) {
1100
        s->current_mapping = NULL;
1101
        if (s->current_fd) {
1102
                close(s->current_fd);
1103
                s->current_fd = 0;
1104
        }
1105
    }
1106
    s->current_cluster = -1;
1107
}
1108

    
1109
/* mappings between index1 and index2-1 are supposed to be ordered
1110
 * return value is the index of the last mapping for which end>cluster_num
1111
 */
1112
static inline int find_mapping_for_cluster_aux(BDRVVVFATState* s,int cluster_num,int index1,int index2)
1113
{
1114
    while(1) {
1115
        int index3;
1116
        mapping_t* mapping;
1117
        index3=(index1+index2)/2;
1118
        mapping=array_get(&(s->mapping),index3);
1119
        assert(mapping->begin < mapping->end);
1120
        if(mapping->begin>=cluster_num) {
1121
            assert(index2!=index3 || index2==0);
1122
            if(index2==index3)
1123
                return index1;
1124
            index2=index3;
1125
        } else {
1126
            if(index1==index3)
1127
                return mapping->end<=cluster_num ? index2 : index1;
1128
            index1=index3;
1129
        }
1130
        assert(index1<=index2);
1131
        DLOG(mapping=array_get(&(s->mapping),index1);
1132
        assert(mapping->begin<=cluster_num);
1133
        assert(index2 >= s->mapping.next ||
1134
                ((mapping = array_get(&(s->mapping),index2)) &&
1135
                mapping->end>cluster_num)));
1136
    }
1137
}
1138

    
1139
static inline mapping_t* find_mapping_for_cluster(BDRVVVFATState* s,int cluster_num)
1140
{
1141
    int index=find_mapping_for_cluster_aux(s,cluster_num,0,s->mapping.next);
1142
    mapping_t* mapping;
1143
    if(index>=s->mapping.next)
1144
        return NULL;
1145
    mapping=array_get(&(s->mapping),index);
1146
    if(mapping->begin>cluster_num)
1147
        return NULL;
1148
    assert(mapping->begin<=cluster_num && mapping->end>cluster_num);
1149
    return mapping;
1150
}
1151

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

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

    
1181
            assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
1182

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

    
1196
            if(open_file(s,mapping))
1197
                return -2;
1198
        } else if (s->current_mapping->mode & MODE_DIRECTORY)
1199
            goto read_cluster_directory;
1200

    
1201
        assert(s->current_fd);
1202

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

    
1217
#ifdef DEBUG
1218
static void print_direntry(const direntry_t* direntry)
1219
{
1220
    int j = 0;
1221
    char buffer[1024];
1222

    
1223
    fprintf(stderr, "direntry %p: ", direntry);
1224
    if(!direntry)
1225
        return;
1226
    if(is_long_name(direntry)) {
1227
        unsigned char* c=(unsigned char*)direntry;
1228
        int i;
1229
        for(i=1;i<11 && c[i] && c[i]!=0xff;i+=2)
1230
#define ADD_CHAR(c) {buffer[j] = (c); if (buffer[j] < ' ') buffer[j] = 0xb0; j++;}
1231
            ADD_CHAR(c[i]);
1232
        for(i=14;i<26 && c[i] && c[i]!=0xff;i+=2)
1233
            ADD_CHAR(c[i]);
1234
        for(i=28;i<32 && c[i] && c[i]!=0xff;i+=2)
1235
            ADD_CHAR(c[i]);
1236
        buffer[j] = 0;
1237
        fprintf(stderr, "%s\n", buffer);
1238
    } else {
1239
        int i;
1240
        for(i=0;i<11;i++)
1241
            ADD_CHAR(direntry->name[i]);
1242
        buffer[j] = 0;
1243
        fprintf(stderr,"%s attributes=0x%02x begin=%d size=%d\n",
1244
                buffer,
1245
                direntry->attributes,
1246
                begin_of_direntry(direntry),le32_to_cpu(direntry->size));
1247
    }
1248
}
1249

    
1250
static void print_mapping(const mapping_t* mapping)
1251
{
1252
    fprintf(stderr, "mapping (%p): begin, end = %d, %d, dir_index = %d, "
1253
        "first_mapping_index = %d, name = %s, mode = 0x%x, " ,
1254
        mapping, mapping->begin, mapping->end, mapping->dir_index,
1255
        mapping->first_mapping_index, mapping->path, mapping->mode);
1256

    
1257
    if (mapping->mode & MODE_DIRECTORY)
1258
        fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
1259
    else
1260
        fprintf(stderr, "offset = %d\n", mapping->info.file.offset);
1261
}
1262
#endif
1263

    
1264
static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
1265
                    uint8_t *buf, int nb_sectors)
1266
{
1267
    BDRVVVFATState *s = bs->opaque;
1268
    int i;
1269

    
1270
    for(i=0;i<nb_sectors;i++,sector_num++) {
1271
        if (sector_num >= bs->total_sectors)
1272
           return -1;
1273
        if (s->qcow) {
1274
            int n;
1275
            if (bdrv_is_allocated(s->qcow, sector_num, nb_sectors-i, &n)) {
1276
DLOG(fprintf(stderr, "sectors %d+%d allocated\n", (int)sector_num, n));
1277
                if (bdrv_read(s->qcow, sector_num, buf + i*0x200, n)) {
1278
                    return -1;
1279
                }
1280
                i += n - 1;
1281
                sector_num += n - 1;
1282
                continue;
1283
            }
1284
DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num));
1285
        }
1286
        if(sector_num<s->faked_sectors) {
1287
            if(sector_num<s->first_sectors_number)
1288
                memcpy(buf+i*0x200,&(s->first_sectors[sector_num*0x200]),0x200);
1289
            else if(sector_num-s->first_sectors_number<s->sectors_per_fat)
1290
                memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number)*0x200]),0x200);
1291
            else if(sector_num-s->first_sectors_number-s->sectors_per_fat<s->sectors_per_fat)
1292
                memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number-s->sectors_per_fat)*0x200]),0x200);
1293
        } else {
1294
            uint32_t sector=sector_num-s->faked_sectors,
1295
            sector_offset_in_cluster=(sector%s->sectors_per_cluster),
1296
            cluster_num=sector/s->sectors_per_cluster;
1297
            if(cluster_num > s->cluster_count || read_cluster(s, cluster_num) != 0) {
1298
                /* LATER TODO: strict: return -1; */
1299
                memset(buf+i*0x200,0,0x200);
1300
                continue;
1301
            }
1302
            memcpy(buf+i*0x200,s->cluster+sector_offset_in_cluster*0x200,0x200);
1303
        }
1304
    }
1305
    return 0;
1306
}
1307

    
1308
static coroutine_fn int vvfat_co_read(BlockDriverState *bs, int64_t sector_num,
1309
                                      uint8_t *buf, int nb_sectors)
1310
{
1311
    int ret;
1312
    BDRVVVFATState *s = bs->opaque;
1313
    qemu_co_mutex_lock(&s->lock);
1314
    ret = vvfat_read(bs, sector_num, buf, nb_sectors);
1315
    qemu_co_mutex_unlock(&s->lock);
1316
    return ret;
1317
}
1318

    
1319
/* LATER TODO: statify all functions */
1320

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

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

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

    
1371
static void schedule_rename(BDRVVVFATState* s,
1372
        uint32_t cluster, char* new_path)
1373
{
1374
    commit_t* commit = array_get_next(&(s->commits));
1375
    commit->path = new_path;
1376
    commit->param.rename.cluster = cluster;
1377
    commit->action = ACTION_RENAME;
1378
}
1379

    
1380
static void schedule_writeout(BDRVVVFATState* s,
1381
        int dir_index, uint32_t modified_offset)
1382
{
1383
    commit_t* commit = array_get_next(&(s->commits));
1384
    commit->path = NULL;
1385
    commit->param.writeout.dir_index = dir_index;
1386
    commit->param.writeout.modified_offset = modified_offset;
1387
    commit->action = ACTION_WRITEOUT;
1388
}
1389

    
1390
static void schedule_new_file(BDRVVVFATState* s,
1391
        char* path, uint32_t first_cluster)
1392
{
1393
    commit_t* commit = array_get_next(&(s->commits));
1394
    commit->path = path;
1395
    commit->param.new_file.first_cluster = first_cluster;
1396
    commit->action = ACTION_NEW_FILE;
1397
}
1398

    
1399
static void schedule_mkdir(BDRVVVFATState* s, uint32_t cluster, char* path)
1400
{
1401
    commit_t* commit = array_get_next(&(s->commits));
1402
    commit->path = path;
1403
    commit->param.mkdir.cluster = cluster;
1404
    commit->action = ACTION_MKDIR;
1405
}
1406

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

    
1418
static void lfn_init(long_file_name* lfn)
1419
{
1420
   lfn->sequence_number = lfn->len = 0;
1421
   lfn->checksum = 0x100;
1422
}
1423

    
1424
/* return 0 if parsed successfully, > 0 if no long name, < 0 if error */
1425
static int parse_long_name(long_file_name* lfn,
1426
        const direntry_t* direntry)
1427
{
1428
    int i, j, offset;
1429
    const unsigned char* pointer = (const unsigned char*)direntry;
1430

    
1431
    if (!is_long_name(direntry))
1432
        return 1;
1433

    
1434
    if (pointer[0] & 0x40) {
1435
        lfn->sequence_number = pointer[0] & 0x3f;
1436
        lfn->checksum = pointer[13];
1437
        lfn->name[0] = 0;
1438
        lfn->name[lfn->sequence_number * 13] = 0;
1439
    } else if ((pointer[0] & 0x3f) != --lfn->sequence_number)
1440
        return -1;
1441
    else if (pointer[13] != lfn->checksum)
1442
        return -2;
1443
    else if (pointer[12] || pointer[26] || pointer[27])
1444
        return -3;
1445

    
1446
    offset = 13 * (lfn->sequence_number - 1);
1447
    for (i = 0, j = 1; i < 13; i++, j+=2) {
1448
        if (j == 11)
1449
            j = 14;
1450
        else if (j == 26)
1451
            j = 28;
1452

    
1453
        if (pointer[j+1] == 0)
1454
            lfn->name[offset + i] = pointer[j];
1455
        else if (pointer[j+1] != 0xff || (pointer[0] & 0x40) == 0)
1456
            return -4;
1457
        else
1458
            lfn->name[offset + i] = 0;
1459
    }
1460

    
1461
    if (pointer[0] & 0x40)
1462
        lfn->len = offset + strlen((char*)lfn->name + offset);
1463

    
1464
    return 0;
1465
}
1466

    
1467
/* returns 0 if successful, >0 if no short_name, and <0 on error */
1468
static int parse_short_name(BDRVVVFATState* s,
1469
        long_file_name* lfn, direntry_t* direntry)
1470
{
1471
    int i, j;
1472

    
1473
    if (!is_short_name(direntry))
1474
        return 1;
1475

    
1476
    for (j = 7; j >= 0 && direntry->name[j] == ' '; j--);
1477
    for (i = 0; i <= j; i++) {
1478
        if (direntry->name[i] <= ' ' || direntry->name[i] > 0x7f)
1479
            return -1;
1480
        else if (s->downcase_short_names)
1481
            lfn->name[i] = qemu_tolower(direntry->name[i]);
1482
        else
1483
            lfn->name[i] = direntry->name[i];
1484
    }
1485

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

    
1501
    lfn->len = strlen((char*)lfn->name);
1502

    
1503
    return 0;
1504
}
1505

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

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

    
1528
static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num)
1529
{
1530
    int was_modified = 0;
1531
    int i, dummy;
1532

    
1533
    if (s->qcow == NULL)
1534
        return 0;
1535

    
1536
    for (i = 0; !was_modified && i < s->sectors_per_cluster; i++)
1537
        was_modified = bdrv_is_allocated(s->qcow,
1538
                cluster2sector(s, cluster_num) + i, 1, &dummy);
1539

    
1540
    return was_modified;
1541
}
1542

    
1543
static const char* get_basename(const char* path)
1544
{
1545
    char* basename = strrchr(path, '/');
1546
    if (basename == NULL)
1547
        return path;
1548
    else
1549
        return basename + 1; /* strip '/' */
1550
}
1551

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

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

    
1597
    uint32_t cluster_num = begin_of_direntry(direntry);
1598
    uint32_t offset = 0;
1599
    int first_mapping_index = -1;
1600
    mapping_t* mapping = NULL;
1601
    const char* basename2 = NULL;
1602

    
1603
    vvfat_close_current_file(s);
1604

    
1605
    /* the root directory */
1606
    if (cluster_num == 0)
1607
        return 0;
1608

    
1609
    /* write support */
1610
    if (s->qcow) {
1611
        basename2 = get_basename(path);
1612

    
1613
        mapping = find_mapping_for_cluster(s, cluster_num);
1614

    
1615
        if (mapping) {
1616
            const char* basename;
1617

    
1618
            assert(mapping->mode & MODE_DELETED);
1619
            mapping->mode &= ~MODE_DELETED;
1620

    
1621
            basename = get_basename(mapping->path);
1622

    
1623
            assert(mapping->mode & MODE_NORMAL);
1624

    
1625
            /* rename */
1626
            if (strcmp(basename, basename2))
1627
                schedule_rename(s, cluster_num, g_strdup(path));
1628
        } else if (is_file(direntry))
1629
            /* new file */
1630
            schedule_new_file(s, g_strdup(path), cluster_num);
1631
        else {
1632
            abort();
1633
            return 0;
1634
        }
1635
    }
1636

    
1637
    while(1) {
1638
        if (s->qcow) {
1639
            if (!copy_it && cluster_was_modified(s, cluster_num)) {
1640
                if (mapping == NULL ||
1641
                        mapping->begin > cluster_num ||
1642
                        mapping->end <= cluster_num)
1643
                mapping = find_mapping_for_cluster(s, cluster_num);
1644

    
1645

    
1646
                if (mapping &&
1647
                        (mapping->mode & MODE_DIRECTORY) == 0) {
1648

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

    
1658
                        if (strcmp(basename, basename2))
1659
                            copy_it = 1;
1660
                        first_mapping_index = array_index(&(s->mapping), mapping);
1661
                    }
1662

    
1663
                    if (mapping->first_mapping_index != first_mapping_index
1664
                            && mapping->info.file.offset > 0) {
1665
                        abort();
1666
                        copy_it = 1;
1667
                    }
1668

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

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

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

    
1699
        ret++;
1700
        if (s->used_clusters[cluster_num] & USED_ANY)
1701
            return 0;
1702
        s->used_clusters[cluster_num] = USED_FILE;
1703

    
1704
        cluster_num = modified_fat_get(s, cluster_num);
1705

    
1706
        if (fat_eof(s, cluster_num))
1707
            return ret;
1708
        else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
1709
            return -1;
1710

    
1711
        offset += s->cluster_size;
1712
    }
1713
}
1714

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

    
1728
    long_file_name lfn;
1729
    int path_len = strlen(path);
1730
    char path2[PATH_MAX + 1];
1731

    
1732
    assert(path_len < PATH_MAX); /* len was tested before! */
1733
    pstrcpy(path2, sizeof(path2), path);
1734
    path2[path_len] = '/';
1735
    path2[path_len + 1] = '\0';
1736

    
1737
    if (mapping) {
1738
        const char* basename = get_basename(mapping->path);
1739
        const char* basename2 = get_basename(path);
1740

    
1741
        assert(mapping->mode & MODE_DIRECTORY);
1742

    
1743
        assert(mapping->mode & MODE_DELETED);
1744
        mapping->mode &= ~MODE_DELETED;
1745

    
1746
        if (strcmp(basename, basename2))
1747
            schedule_rename(s, cluster_num, g_strdup(path));
1748
    } else
1749
        /* new directory */
1750
        schedule_mkdir(s, cluster_num, g_strdup(path));
1751

    
1752
    lfn_init(&lfn);
1753
    do {
1754
        int i;
1755
        int subret = 0;
1756

    
1757
        ret++;
1758

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

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

    
1775
        for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
1776
            int cluster_count = 0;
1777

    
1778
DLOG(fprintf(stderr, "check direntry %d:\n", i); print_direntry(direntries + i));
1779
            if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
1780
                    is_free(direntries + i))
1781
                continue;
1782

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

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

    
1803
            if (path_len + 1 + lfn.len >= PATH_MAX) {
1804
                fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
1805
                goto fail;
1806
            }
1807
            pstrcpy(path2 + path_len + 1, sizeof(path2) - path_len - 1,
1808
                    (char*)lfn.name);
1809

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

    
1833
            ret += cluster_count;
1834
        }
1835

    
1836
        cluster_num = modified_fat_get(s, cluster_num);
1837
    } while(!fat_eof(s, cluster_num));
1838

    
1839
    g_free(cluster);
1840
    return ret;
1841
}
1842

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

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

    
1878
    clear_commits(s);
1879

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

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

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

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

    
1912
    if (check != used_clusters_count)
1913
        return 0;
1914

    
1915
    return used_clusters_count;
1916
}
1917

    
1918
static inline void adjust_mapping_indices(BDRVVVFATState* s,
1919
        int offset, int adjust)
1920
{
1921
    int i;
1922

    
1923
    for (i = 0; i < s->mapping.next; i++) {
1924
        mapping_t* mapping = array_get(&(s->mapping), i);
1925

    
1926
#define ADJUST_MAPPING_INDEX(name) \
1927
        if (mapping->name >= offset) \
1928
            mapping->name += adjust
1929

    
1930
        ADJUST_MAPPING_INDEX(first_mapping_index);
1931
        if (mapping->mode & MODE_DIRECTORY)
1932
            ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
1933
    }
1934
}
1935

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

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

    
1963
    mapping->begin = begin;
1964
    mapping->end = end;
1965

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

    
1971
    if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1972
        s->current_mapping = array_get(&(s->mapping),
1973
                s->current_mapping - first_mapping);
1974

    
1975
    return mapping;
1976
}
1977

    
1978
static int remove_mapping(BDRVVVFATState* s, int mapping_index)
1979
{
1980
    mapping_t* mapping = array_get(&(s->mapping), mapping_index);
1981
    mapping_t* first_mapping = array_get(&(s->mapping), 0);
1982

    
1983
    /* free mapping */
1984
    if (mapping->first_mapping_index < 0) {
1985
        g_free(mapping->path);
1986
    }
1987

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

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

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

    
1998
    return 0;
1999
}
2000

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

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

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

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

    
2050
    vvfat_close_current_file(s);
2051

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

    
2059
    while (!fat_eof(s, cluster)) {
2060
        uint32_t c, c1;
2061

    
2062
        for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
2063
                c = c1, c1 = modified_fat_get(s, c1));
2064

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

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

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

    
2085
                next_mapping = insert_mapping(s, c1, c1+1);
2086

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

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

    
2111
            mapping = next_mapping;
2112
        }
2113

    
2114
        cluster = c1;
2115
    }
2116

    
2117
    return 0;
2118
}
2119

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

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

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

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

    
2143
    mapping->info.dir.parent_mapping_index = parent_mapping_index;
2144

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

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

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

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

    
2178
    ret = commit_mappings(s, first_cluster, dir_index);
2179
    if (ret)
2180
        return ret;
2181

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

    
2195
    return 0;
2196
}
2197

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

    
2212
    assert(offset < size);
2213
    assert((offset % s->cluster_size) == 0);
2214

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

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

    
2233
    while (offset < size) {
2234
        uint32_t c1;
2235
        int rest_size = (size - offset > s->cluster_size ?
2236
                s->cluster_size : size - offset);
2237
        int ret;
2238

    
2239
        c1 = modified_fat_get(s, c);
2240

    
2241
        assert((size - offset == 0 && fat_eof(s, c)) ||
2242
                (size > offset && c >=2 && !fat_eof(s, c)));
2243

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

    
2247
        if (ret < 0) {
2248
            close(fd);
2249
            g_free(cluster);
2250
            return ret;
2251
        }
2252

    
2253
        if (write(fd, cluster, rest_size) < 0) {
2254
            close(fd);
2255
            g_free(cluster);
2256
            return -2;
2257
        }
2258

    
2259
        offset += rest_size;
2260
        c = c1;
2261
    }
2262

    
2263
    if (ftruncate(fd, size)) {
2264
        perror("ftruncate()");
2265
        close(fd);
2266
        g_free(cluster);
2267
        return -4;
2268
    }
2269
    close(fd);
2270
    g_free(cluster);
2271

    
2272
    return commit_mappings(s, first_cluster, dir_index);
2273
}
2274

    
2275
#ifdef DEBUG
2276
/* test, if all mappings point to valid direntries */
2277
static void check1(BDRVVVFATState* s)
2278
{
2279
    int i;
2280
    for (i = 0; i < s->mapping.next; i++) {
2281
        mapping_t* mapping = array_get(&(s->mapping), i);
2282
        if (mapping->mode & MODE_DELETED) {
2283
            fprintf(stderr, "deleted\n");
2284
            continue;
2285
        }
2286
        assert(mapping->dir_index < s->directory.next);
2287
        direntry_t* direntry = array_get(&(s->directory), mapping->dir_index);
2288
        assert(mapping->begin == begin_of_direntry(direntry) || mapping->first_mapping_index >= 0);
2289
        if (mapping->mode & MODE_DIRECTORY) {
2290
            assert(mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster * (mapping->end - mapping->begin) <= s->directory.next);
2291
            assert((mapping->info.dir.first_dir_index % (0x10 * s->sectors_per_cluster)) == 0);
2292
        }
2293
    }
2294
}
2295

    
2296
/* test, if all direntries have mappings */
2297
static void check2(BDRVVVFATState* s)
2298
{
2299
    int i;
2300
    int first_mapping = -1;
2301

    
2302
    for (i = 0; i < s->directory.next; i++) {
2303
        direntry_t* direntry = array_get(&(s->directory), i);
2304

    
2305
        if (is_short_name(direntry) && begin_of_direntry(direntry)) {
2306
            mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
2307
            assert(mapping);
2308
            assert(mapping->dir_index == i || is_dot(direntry));
2309
            assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry));
2310
        }
2311

    
2312
        if ((i % (0x10 * s->sectors_per_cluster)) == 0) {
2313
            /* cluster start */
2314
            int j, count = 0;
2315

    
2316
            for (j = 0; j < s->mapping.next; j++) {
2317
                mapping_t* mapping = array_get(&(s->mapping), j);
2318
                if (mapping->mode & MODE_DELETED)
2319
                    continue;
2320
                if (mapping->mode & MODE_DIRECTORY) {
2321
                    if (mapping->info.dir.first_dir_index <= i && mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster > i) {
2322
                        assert(++count == 1);
2323
                        if (mapping->first_mapping_index == -1)
2324
                            first_mapping = array_index(&(s->mapping), mapping);
2325
                        else
2326
                            assert(first_mapping == mapping->first_mapping_index);
2327
                        if (mapping->info.dir.parent_mapping_index < 0)
2328
                            assert(j == 0);
2329
                        else {
2330
                            mapping_t* parent = array_get(&(s->mapping), mapping->info.dir.parent_mapping_index);
2331
                            assert(parent->mode & MODE_DIRECTORY);
2332
                            assert(parent->info.dir.first_dir_index < mapping->info.dir.first_dir_index);
2333
                        }
2334
                    }
2335
                }
2336
            }
2337
            if (count == 0)
2338
                first_mapping = -1;
2339
        }
2340
    }
2341
}
2342
#endif
2343

    
2344
static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2345
{
2346
    int i;
2347

    
2348
#ifdef DEBUG
2349
    fprintf(stderr, "handle_renames\n");
2350
    for (i = 0; i < s->commits.next; i++) {
2351
        commit_t* commit = array_get(&(s->commits), i);
2352
        fprintf(stderr, "%d, %s (%d, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action);
2353
    }
2354
#endif
2355

    
2356
    for (i = 0; i < s->commits.next;) {
2357
        commit_t* commit = array_get(&(s->commits), i);
2358
        if (commit->action == ACTION_RENAME) {
2359
            mapping_t* mapping = find_mapping_for_cluster(s,
2360
                    commit->param.rename.cluster);
2361
            char* old_path = mapping->path;
2362

    
2363
            assert(commit->path);
2364
            mapping->path = commit->path;
2365
            if (rename(old_path, mapping->path))
2366
                return -2;
2367

    
2368
            if (mapping->mode & MODE_DIRECTORY) {
2369
                int l1 = strlen(mapping->path);
2370
                int l2 = strlen(old_path);
2371
                int diff = l1 - l2;
2372
                direntry_t* direntry = array_get(&(s->directory),
2373
                        mapping->info.dir.first_dir_index);
2374
                uint32_t c = mapping->begin;
2375
                int i = 0;
2376

    
2377
                /* recurse */
2378
                while (!fat_eof(s, c)) {
2379
                    do {
2380
                        direntry_t* d = direntry + i;
2381

    
2382
                        if (is_file(d) || (is_directory(d) && !is_dot(d))) {
2383
                            mapping_t* m = find_mapping_for_cluster(s,
2384
                                    begin_of_direntry(d));
2385
                            int l = strlen(m->path);
2386
                            char* new_path = g_malloc(l + diff + 1);
2387

    
2388
                            assert(!strncmp(m->path, mapping->path, l2));
2389

    
2390
                            pstrcpy(new_path, l + diff + 1, mapping->path);
2391
                            pstrcpy(new_path + l1, l + diff + 1 - l1,
2392
                                    m->path + l2);
2393

    
2394
                            schedule_rename(s, m->begin, new_path);
2395
                        }
2396
                        i++;
2397
                    } while((i % (0x10 * s->sectors_per_cluster)) != 0);
2398
                    c = fat_get(s, c);
2399
                }
2400
            }
2401

    
2402
            g_free(old_path);
2403
            array_remove(&(s->commits), i);
2404
            continue;
2405
        } else if (commit->action == ACTION_MKDIR) {
2406
            mapping_t* mapping;
2407
            int j, parent_path_len;
2408

    
2409
#ifdef __MINGW32__
2410
            if (mkdir(commit->path))
2411
                return -5;
2412
#else
2413
            if (mkdir(commit->path, 0755))
2414
                return -5;
2415
#endif
2416

    
2417
            mapping = insert_mapping(s, commit->param.mkdir.cluster,
2418
                    commit->param.mkdir.cluster + 1);
2419
            if (mapping == NULL)
2420
                return -6;
2421

    
2422
            mapping->mode = MODE_DIRECTORY;
2423
            mapping->read_only = 0;
2424
            mapping->path = commit->path;
2425
            j = s->directory.next;
2426
            assert(j);
2427
            insert_direntries(s, s->directory.next,
2428
                    0x10 * s->sectors_per_cluster);
2429
            mapping->info.dir.first_dir_index = j;
2430

    
2431
            parent_path_len = strlen(commit->path)
2432
                - strlen(get_basename(commit->path)) - 1;
2433
            for (j = 0; j < s->mapping.next; j++) {
2434
                mapping_t* m = array_get(&(s->mapping), j);
2435
                if (m->first_mapping_index < 0 && m != mapping &&
2436
                        !strncmp(m->path, mapping->path, parent_path_len) &&
2437
                        strlen(m->path) == parent_path_len)
2438
                    break;
2439
            }
2440
            assert(j < s->mapping.next);
2441
            mapping->info.dir.parent_mapping_index = j;
2442

    
2443
            array_remove(&(s->commits), i);
2444
            continue;
2445
        }
2446

    
2447
        i++;
2448
    }
2449
    return 0;
2450
}
2451

    
2452
/*
2453
 * TODO: make sure that the short name is not matching *another* file
2454
 */
2455
static int handle_commits(BDRVVVFATState* s)
2456
{
2457
    int i, fail = 0;
2458

    
2459
    vvfat_close_current_file(s);
2460

    
2461
    for (i = 0; !fail && i < s->commits.next; i++) {
2462
        commit_t* commit = array_get(&(s->commits), i);
2463
        switch(commit->action) {
2464
        case ACTION_RENAME: case ACTION_MKDIR:
2465
            abort();
2466
            fail = -2;
2467
            break;
2468
        case ACTION_WRITEOUT: {
2469
#ifndef NDEBUG
2470
            /* these variables are only used by assert() below */
2471
            direntry_t* entry = array_get(&(s->directory),
2472
                    commit->param.writeout.dir_index);
2473
            uint32_t begin = begin_of_direntry(entry);
2474
            mapping_t* mapping = find_mapping_for_cluster(s, begin);
2475
#endif
2476

    
2477
            assert(mapping);
2478
            assert(mapping->begin == begin);
2479
            assert(commit->path == NULL);
2480

    
2481
            if (commit_one_file(s, commit->param.writeout.dir_index,
2482
                        commit->param.writeout.modified_offset))
2483
                fail = -3;
2484

    
2485
            break;
2486
        }
2487
        case ACTION_NEW_FILE: {
2488
            int begin = commit->param.new_file.first_cluster;
2489
            mapping_t* mapping = find_mapping_for_cluster(s, begin);
2490
            direntry_t* entry;
2491
            int i;
2492

    
2493
            /* find direntry */
2494
            for (i = 0; i < s->directory.next; i++) {
2495
                entry = array_get(&(s->directory), i);
2496
                if (is_file(entry) && begin_of_direntry(entry) == begin)
2497
                    break;
2498
            }
2499

    
2500
            if (i >= s->directory.next) {
2501
                fail = -6;
2502
                continue;
2503
            }
2504

    
2505
            /* make sure there exists an initial mapping */
2506
            if (mapping && mapping->begin != begin) {
2507
                mapping->end = begin;
2508
                mapping = NULL;
2509
            }
2510
            if (mapping == NULL) {
2511
                mapping = insert_mapping(s, begin, begin+1);
2512
            }
2513
            /* most members will be fixed in commit_mappings() */
2514
            assert(commit->path);
2515
            mapping->path = commit->path;
2516
            mapping->read_only = 0;
2517
            mapping->mode = MODE_NORMAL;
2518
            mapping->info.file.offset = 0;
2519

    
2520
            if (commit_one_file(s, i, 0))
2521
                fail = -7;
2522

    
2523
            break;
2524
        }
2525
        default:
2526
            abort();
2527
        }
2528
    }
2529
    if (i > 0 && array_remove_slice(&(s->commits), 0, i))
2530
        return -1;
2531
    return fail;
2532
}
2533

    
2534
static int handle_deletes(BDRVVVFATState* s)
2535
{
2536
    int i, deferred = 1, deleted = 1;
2537

    
2538
    /* delete files corresponding to mappings marked as deleted */
2539
    /* handle DELETEs and unused mappings (modified_fat_get(s, mapping->begin) == 0) */
2540
    while (deferred && deleted) {
2541
        deferred = 0;
2542
        deleted = 0;
2543

    
2544
        for (i = 1; i < s->mapping.next; i++) {
2545
            mapping_t* mapping = array_get(&(s->mapping), i);
2546
            if (mapping->mode & MODE_DELETED) {
2547
                direntry_t* entry = array_get(&(s->directory),
2548
                        mapping->dir_index);
2549

    
2550
                if (is_free(entry)) {
2551
                    /* remove file/directory */
2552
                    if (mapping->mode & MODE_DIRECTORY) {
2553
                        int j, next_dir_index = s->directory.next,
2554
                        first_dir_index = mapping->info.dir.first_dir_index;
2555

    
2556
                        if (rmdir(mapping->path) < 0) {
2557
                            if (errno == ENOTEMPTY) {
2558
                                deferred++;
2559
                                continue;
2560
                            } else
2561
                                return -5;
2562
                        }
2563

    
2564
                        for (j = 1; j < s->mapping.next; j++) {
2565
                            mapping_t* m = array_get(&(s->mapping), j);
2566
                            if (m->mode & MODE_DIRECTORY &&
2567
                                    m->info.dir.first_dir_index >
2568
                                    first_dir_index &&
2569
                                    m->info.dir.first_dir_index <
2570
                                    next_dir_index)
2571
                                next_dir_index =
2572
                                    m->info.dir.first_dir_index;
2573
                        }
2574
                        remove_direntries(s, first_dir_index,
2575
                                next_dir_index - first_dir_index);
2576

    
2577
                        deleted++;
2578
                    }
2579
                } else {
2580
                    if (unlink(mapping->path))
2581
                        return -4;
2582
                    deleted++;
2583
                }
2584
                DLOG(fprintf(stderr, "DELETE (%d)\n", i); print_mapping(mapping); print_direntry(entry));
2585
                remove_mapping(s, i);
2586
            }
2587
        }
2588
    }
2589

    
2590
    return 0;
2591
}
2592

    
2593
/*
2594
 * synchronize mapping with new state:
2595
 *
2596
 * - copy FAT (with bdrv_read)
2597
 * - mark all filenames corresponding to mappings as deleted
2598
 * - recurse direntries from root (using bs->bdrv_read)
2599
 * - delete files corresponding to mappings marked as deleted
2600
 */
2601
static int do_commit(BDRVVVFATState* s)
2602
{
2603
    int ret = 0;
2604

    
2605
    /* the real meat are the commits. Nothing to do? Move along! */
2606
    if (s->commits.next == 0)
2607
        return 0;
2608

    
2609
    vvfat_close_current_file(s);
2610

    
2611
    ret = handle_renames_and_mkdirs(s);
2612
    if (ret) {
2613
        fprintf(stderr, "Error handling renames (%d)\n", ret);
2614
        abort();
2615
        return ret;
2616
    }
2617

    
2618
    /* copy FAT (with bdrv_read) */
2619
    memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
2620

    
2621
    /* recurse direntries from root (using bs->bdrv_read) */
2622
    ret = commit_direntries(s, 0, -1);
2623
    if (ret) {
2624
        fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
2625
        abort();
2626
        return ret;
2627
    }
2628

    
2629
    ret = handle_commits(s);
2630
    if (ret) {
2631
        fprintf(stderr, "Error handling commits (%d)\n", ret);
2632
        abort();
2633
        return ret;
2634
    }
2635

    
2636
    ret = handle_deletes(s);
2637
    if (ret) {
2638
        fprintf(stderr, "Error deleting\n");
2639
        abort();
2640
        return ret;
2641
    }
2642

    
2643
    if (s->qcow->drv->bdrv_make_empty) {
2644
        s->qcow->drv->bdrv_make_empty(s->qcow);
2645
    }
2646

    
2647
    memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
2648

    
2649
DLOG(checkpoint());
2650
    return 0;
2651
}
2652

    
2653
static int try_commit(BDRVVVFATState* s)
2654
{
2655
    vvfat_close_current_file(s);
2656
DLOG(checkpoint());
2657
    if(!is_consistent(s))
2658
        return -1;
2659
    return do_commit(s);
2660
}
2661

    
2662
static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
2663
                    const uint8_t *buf, int nb_sectors)
2664
{
2665
    BDRVVVFATState *s = bs->opaque;
2666
    int i, ret;
2667

    
2668
DLOG(checkpoint());
2669

    
2670
    /* Check if we're operating in read-only mode */
2671
    if (s->qcow == NULL) {
2672
        return -EACCES;
2673
    }
2674

    
2675
    vvfat_close_current_file(s);
2676

    
2677
    /*
2678
     * Some sanity checks:
2679
     * - do not allow writing to the boot sector
2680
     * - do not allow to write non-ASCII filenames
2681
     */
2682

    
2683
    if (sector_num < s->first_sectors_number)
2684
        return -1;
2685

    
2686
    for (i = sector2cluster(s, sector_num);
2687
            i <= sector2cluster(s, sector_num + nb_sectors - 1);) {
2688
        mapping_t* mapping = find_mapping_for_cluster(s, i);
2689
        if (mapping) {
2690
            if (mapping->read_only) {
2691
                fprintf(stderr, "Tried to write to write-protected file %s\n",
2692
                        mapping->path);
2693
                return -1;
2694
            }
2695

    
2696
            if (mapping->mode & MODE_DIRECTORY) {
2697
                int begin = cluster2sector(s, i);
2698
                int end = begin + s->sectors_per_cluster, k;
2699
                int dir_index;
2700
                const direntry_t* direntries;
2701
                long_file_name lfn;
2702

    
2703
                lfn_init(&lfn);
2704

    
2705
                if (begin < sector_num)
2706
                    begin = sector_num;
2707
                if (end > sector_num + nb_sectors)
2708
                    end = sector_num + nb_sectors;
2709
                dir_index  = mapping->dir_index +
2710
                    0x10 * (begin - mapping->begin * s->sectors_per_cluster);
2711
                direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
2712

    
2713
                for (k = 0; k < (end - begin) * 0x10; k++) {
2714
                    /* do not allow non-ASCII filenames */
2715
                    if (parse_long_name(&lfn, direntries + k) < 0) {
2716
                        fprintf(stderr, "Warning: non-ASCII filename\n");
2717
                        return -1;
2718
                    }
2719
                    /* no access to the direntry of a read-only file */
2720
                    else if (is_short_name(direntries+k) &&
2721
                            (direntries[k].attributes & 1)) {
2722
                        if (memcmp(direntries + k,
2723
                                    array_get(&(s->directory), dir_index + k),
2724
                                    sizeof(direntry_t))) {
2725
                            fprintf(stderr, "Warning: tried to write to write-protected file\n");
2726
                            return -1;
2727
                        }
2728
                    }
2729
                }
2730
            }
2731
            i = mapping->end;
2732
        } else
2733
            i++;
2734
    }
2735

    
2736
    /*
2737
     * Use qcow backend. Commit later.
2738
     */
2739
DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
2740
    ret = bdrv_write(s->qcow, sector_num, buf, nb_sectors);
2741
    if (ret < 0) {
2742
        fprintf(stderr, "Error writing to qcow backend\n");
2743
        return ret;
2744
    }
2745

    
2746
    for (i = sector2cluster(s, sector_num);
2747
            i <= sector2cluster(s, sector_num + nb_sectors - 1); i++)
2748
        if (i >= 0)
2749
            s->used_clusters[i] |= USED_ALLOCATED;
2750

    
2751
DLOG(checkpoint());
2752
    /* TODO: add timeout */
2753
    try_commit(s);
2754

    
2755
DLOG(checkpoint());
2756
    return 0;
2757
}
2758

    
2759
static coroutine_fn int vvfat_co_write(BlockDriverState *bs, int64_t sector_num,
2760
                                       const uint8_t *buf, int nb_sectors)
2761
{
2762
    int ret;
2763
    BDRVVVFATState *s = bs->opaque;
2764
    qemu_co_mutex_lock(&s->lock);
2765
    ret = vvfat_write(bs, sector_num, buf, nb_sectors);
2766
    qemu_co_mutex_unlock(&s->lock);
2767
    return ret;
2768
}
2769

    
2770
static int coroutine_fn vvfat_co_is_allocated(BlockDriverState *bs,
2771
        int64_t sector_num, int nb_sectors, int* n)
2772
{
2773
    BDRVVVFATState* s = bs->opaque;
2774
    *n = s->sector_count - sector_num;
2775
    if (*n > nb_sectors)
2776
        *n = nb_sectors;
2777
    else if (*n < 0)
2778
        return 0;
2779
    return 1;
2780
}
2781

    
2782
static int write_target_commit(BlockDriverState *bs, int64_t sector_num,
2783
        const uint8_t* buffer, int nb_sectors) {
2784
    BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
2785
    return try_commit(s);
2786
}
2787

    
2788
static void write_target_close(BlockDriverState *bs) {
2789
    BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
2790
    bdrv_delete(s->qcow);
2791
    g_free(s->qcow_filename);
2792
}
2793

    
2794
static BlockDriver vvfat_write_target = {
2795
    .format_name        = "vvfat_write_target",
2796
    .bdrv_write         = write_target_commit,
2797
    .bdrv_close         = write_target_close,
2798
};
2799

    
2800
static int enable_write_target(BDRVVVFATState *s)
2801
{
2802
    BlockDriver *bdrv_qcow;
2803
    QEMUOptionParameter *options;
2804
    int ret;
2805
    int size = sector2cluster(s, s->sector_count);
2806
    s->used_clusters = calloc(size, 1);
2807

    
2808
    array_init(&(s->commits), sizeof(commit_t));
2809

    
2810
    s->qcow_filename = g_malloc(1024);
2811
    ret = get_tmp_filename(s->qcow_filename, 1024);
2812
    if (ret < 0) {
2813
        g_free(s->qcow_filename);
2814
        s->qcow_filename = NULL;
2815
        return ret;
2816
    }
2817

    
2818
    bdrv_qcow = bdrv_find_format("qcow");
2819
    options = parse_option_parameters("", bdrv_qcow->create_options, NULL);
2820
    set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512);
2821
    set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:");
2822

    
2823
    if (bdrv_create(bdrv_qcow, s->qcow_filename, options) < 0)
2824
        return -1;
2825

    
2826
    s->qcow = bdrv_new("");
2827
    if (s->qcow == NULL) {
2828
        return -1;
2829
    }
2830

    
2831
    ret = bdrv_open(s->qcow, s->qcow_filename,
2832
            BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, bdrv_qcow);
2833
    if (ret < 0) {
2834
        return ret;
2835
    }
2836

    
2837
#ifndef _WIN32
2838
    unlink(s->qcow_filename);
2839
#endif
2840

    
2841
    s->bs->backing_hd = calloc(sizeof(BlockDriverState), 1);
2842
    s->bs->backing_hd->drv = &vvfat_write_target;
2843
    s->bs->backing_hd->opaque = g_malloc(sizeof(void*));
2844
    *(void**)s->bs->backing_hd->opaque = s;
2845

    
2846
    return 0;
2847
}
2848

    
2849
static void vvfat_close(BlockDriverState *bs)
2850
{
2851
    BDRVVVFATState *s = bs->opaque;
2852

    
2853
    vvfat_close_current_file(s);
2854
    array_free(&(s->fat));
2855
    array_free(&(s->directory));
2856
    array_free(&(s->mapping));
2857
    g_free(s->cluster_buffer);
2858

    
2859
    if (s->qcow) {
2860
        migrate_del_blocker(s->migration_blocker);
2861
        error_free(s->migration_blocker);
2862
    }
2863
}
2864

    
2865
static BlockDriver bdrv_vvfat = {
2866
    .format_name        = "vvfat",
2867
    .instance_size        = sizeof(BDRVVVFATState),
2868
    .bdrv_file_open        = vvfat_open,
2869
    .bdrv_rebind        = vvfat_rebind,
2870
    .bdrv_read          = vvfat_co_read,
2871
    .bdrv_write         = vvfat_co_write,
2872
    .bdrv_close                = vvfat_close,
2873
    .bdrv_co_is_allocated = vvfat_co_is_allocated,
2874
    .protocol_name        = "fat",
2875
};
2876

    
2877
static void bdrv_vvfat_init(void)
2878
{
2879
    bdrv_register(&bdrv_vvfat);
2880
}
2881

    
2882
block_init(bdrv_vvfat_init);
2883

    
2884
#ifdef DEBUG
2885
static void checkpoint(void) {
2886
    assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2);
2887
    check1(vvv);
2888
    check2(vvv);
2889
    assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY));
2890
#if 0
2891
    if (((direntry_t*)vvv->directory.pointer)[1].attributes != 0xf)
2892
        fprintf(stderr, "Nonono!\n");
2893
    mapping_t* mapping;
2894
    direntry_t* direntry;
2895
    assert(vvv->mapping.size >= vvv->mapping.item_size * vvv->mapping.next);
2896
    assert(vvv->directory.size >= vvv->directory.item_size * vvv->directory.next);
2897
    if (vvv->mapping.next<47)
2898
        return;
2899
    assert((mapping = array_get(&(vvv->mapping), 47)));
2900
    assert(mapping->dir_index < vvv->directory.next);
2901
    direntry = array_get(&(vvv->directory), mapping->dir_index);
2902
    assert(!memcmp(direntry->name, "USB     H  ", 11) || direntry->name[0]==0);
2903
#endif
2904
}
2905
#endif