Statistics
| Branch: | Revision:

root / block / vvfat.c @ de9c0cec

History | View | Annotate | Download (81.6 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/block_int.h"
29
#include "qemu/module.h"
30
#include "migration/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(mbr_chs_t *chs, int spos, int cyls, int heads, int secs)
363
{
364
    int head,sector;
365
    sector   = spos % secs;  spos /= secs;
366
    head     = spos % heads; spos /= heads;
367
    if (spos >= cyls) {
368
        /* Overflow,
369
        it happens if 32bit sector positions are used, while CHS is only 24bit.
370
        Windows/Dos is said to take 1023/255/63 as nonrepresentable CHS */
371
        chs->head     = 0xFF;
372
        chs->sector   = 0xFF;
373
        chs->cylinder = 0xFF;
374
        return 1;
375
    }
376
    chs->head     = (uint8_t)head;
377
    chs->sector   = (uint8_t)( (sector+1) | ((spos>>8)<<6) );
378
    chs->cylinder = (uint8_t)spos;
379
    return 0;
380
}
381

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

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

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

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

    
396
    /* LBA is used when partition is outside the CHS geometry */
397
    lba  = sector2CHS(&partition->start_CHS, s->first_sectors_number - 1,
398
                     cyls, heads, secs);
399
    lba |= sector2CHS(&partition->end_CHS,   s->bs->total_sectors - 1,
400
                     cyls, heads, secs);
401

    
402
    /*LBA partitions are identified only by start/length_sector_long not by CHS*/
403
    partition->start_sector_long  = cpu_to_le32(s->first_sectors_number - 1);
404
    partition->length_sector_long = cpu_to_le32(s->bs->total_sectors
405
                                                - s->first_sectors_number + 1);
406

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

    
414
    real_mbr->magic[0]=0x55; real_mbr->magic[1]=0xaa;
415
}
416

    
417
/* direntry functions */
418

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

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

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

    
460
static char is_free(const direntry_t* direntry)
461
{
462
    return direntry->name[0]==0xe5 || direntry->name[0]==0x00;
463
}
464

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

    
470
static char is_long_name(const direntry_t* direntry)
471
{
472
    return direntry->attributes == 0xf;
473
}
474

    
475
static char is_short_name(const direntry_t* direntry)
476
{
477
    return !is_volume_label(direntry) && !is_long_name(direntry)
478
        && !is_free(direntry);
479
}
480

    
481
static char is_directory(const direntry_t* direntry)
482
{
483
    return direntry->attributes & 0x10 && direntry->name[0] != 0xe5;
484
}
485

    
486
static inline char is_dot(const direntry_t* direntry)
487
{
488
    return is_short_name(direntry) && direntry->name[0] == '.';
489
}
490

    
491
static char is_file(const direntry_t* direntry)
492
{
493
    return is_short_name(direntry) && !is_directory(direntry);
494
}
495

    
496
static inline uint32_t begin_of_direntry(const direntry_t* direntry)
497
{
498
    return le16_to_cpu(direntry->begin)|(le16_to_cpu(direntry->begin_hi)<<16);
499
}
500

    
501
static inline uint32_t filesize_of_direntry(const direntry_t* direntry)
502
{
503
    return le32_to_cpu(direntry->size);
504
}
505

    
506
static void set_begin_of_direntry(direntry_t* direntry, uint32_t begin)
507
{
508
    direntry->begin = cpu_to_le16(begin & 0xffff);
509
    direntry->begin_hi = cpu_to_le16((begin >> 16) & 0xffff);
510
}
511

    
512
/* fat functions */
513

    
514
static inline uint8_t fat_chksum(const direntry_t* entry)
515
{
516
    uint8_t chksum=0;
517
    int i;
518

    
519
    for(i=0;i<11;i++) {
520
        unsigned char c;
521

    
522
        c = (i < 8) ? entry->name[i] : entry->extension[i-8];
523
        chksum=(((chksum&0xfe)>>1)|((chksum&0x01)?0x80:0)) + c;
524
    }
525

    
526
    return chksum;
527
}
528

    
529
/* if return_time==0, this returns the fat_date, else the fat_time */
530
static uint16_t fat_datetime(time_t time,int return_time) {
531
    struct tm* t;
532
    struct tm t1;
533
    t = &t1;
534
    localtime_r(&time,t);
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, int heads, int secs)
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(secs);
961
    bootsector->number_of_heads = cpu_to_le16(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, cyls, heads, secs;
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
            secs = 36;
1037
            s->sectors_per_cluster=2;
1038
        } else {
1039
            secs = s->fat_type == 12 ? 18 : 36;
1040
            s->sectors_per_cluster=1;
1041
        }
1042
        s->first_sectors_number = 1;
1043
        cyls = 80;
1044
        heads = 2;
1045
    } else {
1046
        /* 32MB or 504MB disk*/
1047
        if (!s->fat_type) {
1048
            s->fat_type = 16;
1049
        }
1050
        cyls = s->fat_type == 12 ? 64 : 1024;
1051
        heads = 16;
1052
        secs = 63;
1053
    }
1054
    fprintf(stderr, "vvfat %s chs %d,%d,%d\n",
1055
            dirname, cyls, heads, secs);
1056

    
1057
    s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1);
1058

    
1059
    if (strstr(dirname, ":rw:")) {
1060
        if (enable_write_target(s))
1061
            return -1;
1062
        bs->read_only = 0;
1063
    }
1064

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

    
1073
    bs->total_sectors = cyls * heads * secs;
1074

    
1075
    if (init_directories(s, dirname, heads, secs)) {
1076
        return -1;
1077
    }
1078

    
1079
    s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
1080

    
1081
    if (s->first_sectors_number == 0x40) {
1082
        init_mbr(s, cyls, heads, secs);
1083
    }
1084

    
1085
    //    assert(is_consistent(s));
1086
    qemu_co_mutex_init(&s->lock);
1087

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

    
1096
    return 0;
1097
}
1098

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

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

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

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

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

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

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

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

    
1203
        assert(s->current_fd);
1204

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

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

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

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

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

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

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

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

    
1321
/* LATER TODO: statify all functions */
1322

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

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

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

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

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

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

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

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

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

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

    
1433
    if (!is_long_name(direntry))
1434
        return 1;
1435

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

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

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

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

    
1466
    return 0;
1467
}
1468

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

    
1475
    if (!is_short_name(direntry))
1476
        return 1;
1477

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

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

    
1503
    lfn->len = strlen((char*)lfn->name);
1504

    
1505
    return 0;
1506
}
1507

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

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

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

    
1535
    if (s->qcow == NULL)
1536
        return 0;
1537

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

    
1542
    return was_modified;
1543
}
1544

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

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

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

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

    
1605
    vvfat_close_current_file(s);
1606

    
1607
    /* the root directory */
1608
    if (cluster_num == 0)
1609
        return 0;
1610

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

    
1615
        mapping = find_mapping_for_cluster(s, cluster_num);
1616

    
1617
        if (mapping) {
1618
            const char* basename;
1619

    
1620
            assert(mapping->mode & MODE_DELETED);
1621
            mapping->mode &= ~MODE_DELETED;
1622

    
1623
            basename = get_basename(mapping->path);
1624

    
1625
            assert(mapping->mode & MODE_NORMAL);
1626

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

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

    
1647

    
1648
                if (mapping &&
1649
                        (mapping->mode & MODE_DIRECTORY) == 0) {
1650

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

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

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

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

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

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

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

    
1706
        cluster_num = modified_fat_get(s, cluster_num);
1707

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

    
1713
        offset += s->cluster_size;
1714
    }
1715
}
1716

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

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

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

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

    
1743
        assert(mapping->mode & MODE_DIRECTORY);
1744

    
1745
        assert(mapping->mode & MODE_DELETED);
1746
        mapping->mode &= ~MODE_DELETED;
1747

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

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

    
1759
        ret++;
1760

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

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

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

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

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

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

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

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

    
1835
            ret += cluster_count;
1836
        }
1837

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

    
1841
    g_free(cluster);
1842
    return ret;
1843
}
1844

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

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

    
1880
    clear_commits(s);
1881

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

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

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

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

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

    
1917
    return used_clusters_count;
1918
}
1919

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

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

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

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

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

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

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

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

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

    
1977
    return mapping;
1978
}
1979

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

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

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

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

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

    
2000
    return 0;
2001
}
2002

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

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

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

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

    
2052
    vvfat_close_current_file(s);
2053

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

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

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

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

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

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

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

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

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

    
2113
            mapping = next_mapping;
2114
        }
2115

    
2116
        cluster = c1;
2117
    }
2118

    
2119
    return 0;
2120
}
2121

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

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

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

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

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

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

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

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

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

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

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

    
2197
    return 0;
2198
}
2199

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

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

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

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

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

    
2241
        c1 = modified_fat_get(s, c);
2242

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

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

    
2249
        if (ret < 0) {
2250
            qemu_close(fd);
2251
            g_free(cluster);
2252
            return ret;
2253
        }
2254

    
2255
        if (write(fd, cluster, rest_size) < 0) {
2256
            qemu_close(fd);
2257
            g_free(cluster);
2258
            return -2;
2259
        }
2260

    
2261
        offset += rest_size;
2262
        c = c1;
2263
    }
2264

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

    
2274
    return commit_mappings(s, first_cluster, dir_index);
2275
}
2276

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

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

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

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

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

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

    
2346
static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2347
{
2348
    int i;
2349

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

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

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

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

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

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

    
2390
                            assert(!strncmp(m->path, mapping->path, l2));
2391

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

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

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

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

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

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

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

    
2445
            array_remove(&(s->commits), i);
2446
            continue;
2447
        }
2448

    
2449
        i++;
2450
    }
2451
    return 0;
2452
}
2453

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

    
2461
    vvfat_close_current_file(s);
2462

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

    
2479
            assert(mapping);
2480
            assert(mapping->begin == begin);
2481
            assert(commit->path == NULL);
2482

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

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

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

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

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

    
2522
            if (commit_one_file(s, i, 0))
2523
                fail = -7;
2524

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

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

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

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

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

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

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

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

    
2592
    return 0;
2593
}
2594

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

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

    
2611
    vvfat_close_current_file(s);
2612

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

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

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

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

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

    
2645
    if (s->qcow->drv->bdrv_make_empty) {
2646
        s->qcow->drv->bdrv_make_empty(s->qcow);
2647
    }
2648

    
2649
    memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
2650

    
2651
DLOG(checkpoint());
2652
    return 0;
2653
}
2654

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

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

    
2670
DLOG(checkpoint());
2671

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

    
2677
    vvfat_close_current_file(s);
2678

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

    
2685
    if (sector_num < s->first_sectors_number)
2686
        return -1;
2687

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

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

    
2705
                lfn_init(&lfn);
2706

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

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

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

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

    
2753
DLOG(checkpoint());
2754
    /* TODO: add timeout */
2755
    try_commit(s);
2756

    
2757
DLOG(checkpoint());
2758
    return 0;
2759
}
2760

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

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

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

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

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

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

    
2810
    array_init(&(s->commits), sizeof(commit_t));
2811

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

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

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

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

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

    
2839
#ifndef _WIN32
2840
    unlink(s->qcow_filename);
2841
#endif
2842

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

    
2848
    return 0;
2849
}
2850

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

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

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

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

    
2879
static void bdrv_vvfat_init(void)
2880
{
2881
    bdrv_register(&bdrv_vvfat);
2882
}
2883

    
2884
block_init(bdrv_vvfat_init);
2885

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