Statistics
| Branch: | Revision:

root / block / vvfat.c @ f67503e5

History | View | Annotate | Download (84.8 kB)

1
/* vim:set shiftwidth=4 ts=4: */
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
#include "qapi/qmp/qint.h"
32
#include "qapi/qmp/qbool.h"
33

    
34
#ifndef S_IWGRP
35
#define S_IWGRP 0
36
#endif
37
#ifndef S_IWOTH
38
#define S_IWOTH 0
39
#endif
40

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

    
49
/* #define DEBUG */
50

    
51
#ifdef DEBUG
52

    
53
#define DLOG(a) a
54

    
55
#undef stderr
56
#define stderr STDERR
57
FILE* stderr = NULL;
58

    
59
static void checkpoint(void);
60

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

    
70
#else
71

    
72
#define DLOG(a)
73

    
74
#endif
75

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

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

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

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

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

    
113
    return 0;
114
}
115

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

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

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

    
126
    return result;
127
}
128

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

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

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

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

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

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

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

    
174
    g_free(buf);
175

    
176
    return 0;
177
}
178

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
356
    Error *migration_blocker;
357
} BDRVVVFATState;
358

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

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

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

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

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

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

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

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

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

    
418
/* direntry functions */
419

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

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

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

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

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

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

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

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

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

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

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

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

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

    
513
/* fat functions */
514

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

    
520
    for (i = 0; i < ARRAY_SIZE(entry->name); i++) {
521
        chksum = (((chksum & 0xfe) >> 1) |
522
                  ((chksum & 0x01) ? 0x80 : 0)) + entry->name[i];
523
    }
524

    
525
    return chksum;
526
}
527

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

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

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

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

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

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

    
604
}
605

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

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

    
622
    entry_long=create_long_filename(s,filename);
623

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

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

    
635
    if (j > 0) {
636
        for (i = 0; i < 3 && filename[j + 1 + i]; i++) {
637
            entry->name[8 + i] = filename[j + 1 + i];
638
        }
639
    }
640

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

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

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

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

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

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

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

    
692
    return entry;
693
}
694

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
820
    return 0;
821
}
822

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

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

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

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

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

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

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

    
859
    /* add volume label */
860
    {
861
        direntry_t* entry=array_get_next(&(s->directory));
862
        entry->attributes=0x28; /* archive | volume label */
863
        memcpy(entry->name, "QEMU VVFAT ", sizeof(entry->name));
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 QemuOptsList runtime_opts = {
992
    .name = "vvfat",
993
    .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
994
    .desc = {
995
        {
996
            .name = "dir",
997
            .type = QEMU_OPT_STRING,
998
            .help = "Host directory to map to the vvfat device",
999
        },
1000
        {
1001
            .name = "fat-type",
1002
            .type = QEMU_OPT_NUMBER,
1003
            .help = "FAT type (12, 16 or 32)",
1004
        },
1005
        {
1006
            .name = "floppy",
1007
            .type = QEMU_OPT_BOOL,
1008
            .help = "Create a floppy rather than a hard disk image",
1009
        },
1010
        {
1011
            .name = "rw",
1012
            .type = QEMU_OPT_BOOL,
1013
            .help = "Make the image writable",
1014
        },
1015
        { /* end of list */ }
1016
    },
1017
};
1018

    
1019
static void vvfat_parse_filename(const char *filename, QDict *options,
1020
                                 Error **errp)
1021
{
1022
    int fat_type = 0;
1023
    bool floppy = false;
1024
    bool rw = false;
1025
    int i;
1026

    
1027
    if (!strstart(filename, "fat:", NULL)) {
1028
        error_setg(errp, "File name string must start with 'fat:'");
1029
        return;
1030
    }
1031

    
1032
    /* Parse options */
1033
    if (strstr(filename, ":32:")) {
1034
        fat_type = 32;
1035
    } else if (strstr(filename, ":16:")) {
1036
        fat_type = 16;
1037
    } else if (strstr(filename, ":12:")) {
1038
        fat_type = 12;
1039
    }
1040

    
1041
    if (strstr(filename, ":floppy:")) {
1042
        floppy = true;
1043
    }
1044

    
1045
    if (strstr(filename, ":rw:")) {
1046
        rw = true;
1047
    }
1048

    
1049
    /* Get the directory name without options */
1050
    i = strrchr(filename, ':') - filename;
1051
    assert(i >= 3);
1052
    if (filename[i - 2] == ':' && qemu_isalpha(filename[i - 1])) {
1053
        /* workaround for DOS drive names */
1054
        filename += i - 1;
1055
    } else {
1056
        filename += i + 1;
1057
    }
1058

    
1059
    /* Fill in the options QDict */
1060
    qdict_put(options, "dir", qstring_from_str(filename));
1061
    qdict_put(options, "fat-type", qint_from_int(fat_type));
1062
    qdict_put(options, "floppy", qbool_from_int(floppy));
1063
    qdict_put(options, "rw", qbool_from_int(rw));
1064
}
1065

    
1066
static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
1067
                      Error **errp)
1068
{
1069
    BDRVVVFATState *s = bs->opaque;
1070
    int cyls, heads, secs;
1071
    bool floppy;
1072
    const char *dirname;
1073
    QemuOpts *opts;
1074
    Error *local_err = NULL;
1075
    int ret;
1076

    
1077
#ifdef DEBUG
1078
    vvv = s;
1079
#endif
1080

    
1081
DLOG(if (stderr == NULL) {
1082
    stderr = fopen("vvfat.log", "a");
1083
    setbuf(stderr, NULL);
1084
})
1085

    
1086
    opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
1087
    qemu_opts_absorb_qdict(opts, options, &local_err);
1088
    if (local_err) {
1089
        qerror_report_err(local_err);
1090
        error_free(local_err);
1091
        ret = -EINVAL;
1092
        goto fail;
1093
    }
1094

    
1095
    dirname = qemu_opt_get(opts, "dir");
1096
    if (!dirname) {
1097
        qerror_report(ERROR_CLASS_GENERIC_ERROR, "vvfat block driver requires "
1098
                      "a 'dir' option");
1099
        ret = -EINVAL;
1100
        goto fail;
1101
    }
1102

    
1103
    s->fat_type = qemu_opt_get_number(opts, "fat-type", 0);
1104
    floppy = qemu_opt_get_bool(opts, "floppy", false);
1105

    
1106
    if (floppy) {
1107
        /* 1.44MB or 2.88MB floppy.  2.88MB can be FAT12 (default) or FAT16. */
1108
        if (!s->fat_type) {
1109
            s->fat_type = 12;
1110
            secs = 36;
1111
            s->sectors_per_cluster = 2;
1112
        } else {
1113
            secs = s->fat_type == 12 ? 18 : 36;
1114
            s->sectors_per_cluster = 1;
1115
        }
1116
        s->first_sectors_number = 1;
1117
        cyls = 80;
1118
        heads = 2;
1119
    } else {
1120
        /* 32MB or 504MB disk*/
1121
        if (!s->fat_type) {
1122
            s->fat_type = 16;
1123
        }
1124
        cyls = s->fat_type == 12 ? 64 : 1024;
1125
        heads = 16;
1126
        secs = 63;
1127
    }
1128

    
1129
    switch (s->fat_type) {
1130
    case 32:
1131
            fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. "
1132
                "You are welcome to do so!\n");
1133
        break;
1134
    case 16:
1135
    case 12:
1136
        break;
1137
    default:
1138
        qerror_report(ERROR_CLASS_GENERIC_ERROR, "Valid FAT types are only "
1139
                      "12, 16 and 32");
1140
        ret = -EINVAL;
1141
        goto fail;
1142
    }
1143

    
1144

    
1145
    s->bs = bs;
1146

    
1147
    /* LATER TODO: if FAT32, adjust */
1148
    s->sectors_per_cluster=0x10;
1149

    
1150
    s->current_cluster=0xffffffff;
1151

    
1152
    s->first_sectors_number=0x40;
1153
    /* read only is the default for safety */
1154
    bs->read_only = 1;
1155
    s->qcow = s->write_target = NULL;
1156
    s->qcow_filename = NULL;
1157
    s->fat2 = NULL;
1158
    s->downcase_short_names = 1;
1159

    
1160
    fprintf(stderr, "vvfat %s chs %d,%d,%d\n",
1161
            dirname, cyls, heads, secs);
1162

    
1163
    s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1);
1164

    
1165
    if (qemu_opt_get_bool(opts, "rw", false)) {
1166
        ret = enable_write_target(s);
1167
        if (ret < 0) {
1168
            goto fail;
1169
        }
1170
        bs->read_only = 0;
1171
    }
1172

    
1173
    bs->total_sectors = cyls * heads * secs;
1174

    
1175
    if (init_directories(s, dirname, heads, secs)) {
1176
        ret = -EIO;
1177
        goto fail;
1178
    }
1179

    
1180
    s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
1181

    
1182
    if (s->first_sectors_number == 0x40) {
1183
        init_mbr(s, cyls, heads, secs);
1184
    }
1185

    
1186
    //    assert(is_consistent(s));
1187
    qemu_co_mutex_init(&s->lock);
1188

    
1189
    /* Disable migration when vvfat is used rw */
1190
    if (s->qcow) {
1191
        error_set(&s->migration_blocker,
1192
                  QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
1193
                  "vvfat (rw)", bs->device_name, "live migration");
1194
        migrate_add_blocker(s->migration_blocker);
1195
    }
1196

    
1197
    ret = 0;
1198
fail:
1199
    qemu_opts_del(opts);
1200
    return ret;
1201
}
1202

    
1203
static inline void vvfat_close_current_file(BDRVVVFATState *s)
1204
{
1205
    if(s->current_mapping) {
1206
        s->current_mapping = NULL;
1207
        if (s->current_fd) {
1208
                qemu_close(s->current_fd);
1209
                s->current_fd = 0;
1210
        }
1211
    }
1212
    s->current_cluster = -1;
1213
}
1214

    
1215
/* mappings between index1 and index2-1 are supposed to be ordered
1216
 * return value is the index of the last mapping for which end>cluster_num
1217
 */
1218
static inline int find_mapping_for_cluster_aux(BDRVVVFATState* s,int cluster_num,int index1,int index2)
1219
{
1220
    while(1) {
1221
        int index3;
1222
        mapping_t* mapping;
1223
        index3=(index1+index2)/2;
1224
        mapping=array_get(&(s->mapping),index3);
1225
        assert(mapping->begin < mapping->end);
1226
        if(mapping->begin>=cluster_num) {
1227
            assert(index2!=index3 || index2==0);
1228
            if(index2==index3)
1229
                return index1;
1230
            index2=index3;
1231
        } else {
1232
            if(index1==index3)
1233
                return mapping->end<=cluster_num ? index2 : index1;
1234
            index1=index3;
1235
        }
1236
        assert(index1<=index2);
1237
        DLOG(mapping=array_get(&(s->mapping),index1);
1238
        assert(mapping->begin<=cluster_num);
1239
        assert(index2 >= s->mapping.next ||
1240
                ((mapping = array_get(&(s->mapping),index2)) &&
1241
                mapping->end>cluster_num)));
1242
    }
1243
}
1244

    
1245
static inline mapping_t* find_mapping_for_cluster(BDRVVVFATState* s,int cluster_num)
1246
{
1247
    int index=find_mapping_for_cluster_aux(s,cluster_num,0,s->mapping.next);
1248
    mapping_t* mapping;
1249
    if(index>=s->mapping.next)
1250
        return NULL;
1251
    mapping=array_get(&(s->mapping),index);
1252
    if(mapping->begin>cluster_num)
1253
        return NULL;
1254
    assert(mapping->begin<=cluster_num && mapping->end>cluster_num);
1255
    return mapping;
1256
}
1257

    
1258
static int open_file(BDRVVVFATState* s,mapping_t* mapping)
1259
{
1260
    if(!mapping)
1261
        return -1;
1262
    if(!s->current_mapping ||
1263
            strcmp(s->current_mapping->path,mapping->path)) {
1264
        /* open file */
1265
        int fd = qemu_open(mapping->path, O_RDONLY | O_BINARY | O_LARGEFILE);
1266
        if(fd<0)
1267
            return -1;
1268
        vvfat_close_current_file(s);
1269
        s->current_fd = fd;
1270
        s->current_mapping = mapping;
1271
    }
1272
    return 0;
1273
}
1274

    
1275
static inline int read_cluster(BDRVVVFATState *s,int cluster_num)
1276
{
1277
    if(s->current_cluster != cluster_num) {
1278
        int result=0;
1279
        off_t offset;
1280
        assert(!s->current_mapping || s->current_fd || (s->current_mapping->mode & MODE_DIRECTORY));
1281
        if(!s->current_mapping
1282
                || s->current_mapping->begin>cluster_num
1283
                || s->current_mapping->end<=cluster_num) {
1284
            /* binary search of mappings for file */
1285
            mapping_t* mapping=find_mapping_for_cluster(s,cluster_num);
1286

    
1287
            assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
1288

    
1289
            if (mapping && mapping->mode & MODE_DIRECTORY) {
1290
                vvfat_close_current_file(s);
1291
                s->current_mapping = mapping;
1292
read_cluster_directory:
1293
                offset = s->cluster_size*(cluster_num-s->current_mapping->begin);
1294
                s->cluster = (unsigned char*)s->directory.pointer+offset
1295
                        + 0x20*s->current_mapping->info.dir.first_dir_index;
1296
                assert(((s->cluster-(unsigned char*)s->directory.pointer)%s->cluster_size)==0);
1297
                assert((char*)s->cluster+s->cluster_size <= s->directory.pointer+s->directory.next*s->directory.item_size);
1298
                s->current_cluster = cluster_num;
1299
                return 0;
1300
            }
1301

    
1302
            if(open_file(s,mapping))
1303
                return -2;
1304
        } else if (s->current_mapping->mode & MODE_DIRECTORY)
1305
            goto read_cluster_directory;
1306

    
1307
        assert(s->current_fd);
1308

    
1309
        offset=s->cluster_size*(cluster_num-s->current_mapping->begin)+s->current_mapping->info.file.offset;
1310
        if(lseek(s->current_fd, offset, SEEK_SET)!=offset)
1311
            return -3;
1312
        s->cluster=s->cluster_buffer;
1313
        result=read(s->current_fd,s->cluster,s->cluster_size);
1314
        if(result<0) {
1315
            s->current_cluster = -1;
1316
            return -1;
1317
        }
1318
        s->current_cluster = cluster_num;
1319
    }
1320
    return 0;
1321
}
1322

    
1323
#ifdef DEBUG
1324
static void print_direntry(const direntry_t* direntry)
1325
{
1326
    int j = 0;
1327
    char buffer[1024];
1328

    
1329
    fprintf(stderr, "direntry %p: ", direntry);
1330
    if(!direntry)
1331
        return;
1332
    if(is_long_name(direntry)) {
1333
        unsigned char* c=(unsigned char*)direntry;
1334
        int i;
1335
        for(i=1;i<11 && c[i] && c[i]!=0xff;i+=2)
1336
#define ADD_CHAR(c) {buffer[j] = (c); if (buffer[j] < ' ') buffer[j] = 0xb0; j++;}
1337
            ADD_CHAR(c[i]);
1338
        for(i=14;i<26 && c[i] && c[i]!=0xff;i+=2)
1339
            ADD_CHAR(c[i]);
1340
        for(i=28;i<32 && c[i] && c[i]!=0xff;i+=2)
1341
            ADD_CHAR(c[i]);
1342
        buffer[j] = 0;
1343
        fprintf(stderr, "%s\n", buffer);
1344
    } else {
1345
        int i;
1346
        for(i=0;i<11;i++)
1347
            ADD_CHAR(direntry->name[i]);
1348
        buffer[j] = 0;
1349
        fprintf(stderr,"%s attributes=0x%02x begin=%d size=%d\n",
1350
                buffer,
1351
                direntry->attributes,
1352
                begin_of_direntry(direntry),le32_to_cpu(direntry->size));
1353
    }
1354
}
1355

    
1356
static void print_mapping(const mapping_t* mapping)
1357
{
1358
    fprintf(stderr, "mapping (%p): begin, end = %d, %d, dir_index = %d, "
1359
        "first_mapping_index = %d, name = %s, mode = 0x%x, " ,
1360
        mapping, mapping->begin, mapping->end, mapping->dir_index,
1361
        mapping->first_mapping_index, mapping->path, mapping->mode);
1362

    
1363
    if (mapping->mode & MODE_DIRECTORY)
1364
        fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
1365
    else
1366
        fprintf(stderr, "offset = %d\n", mapping->info.file.offset);
1367
}
1368
#endif
1369

    
1370
static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
1371
                    uint8_t *buf, int nb_sectors)
1372
{
1373
    BDRVVVFATState *s = bs->opaque;
1374
    int i;
1375

    
1376
    for(i=0;i<nb_sectors;i++,sector_num++) {
1377
        if (sector_num >= bs->total_sectors)
1378
           return -1;
1379
        if (s->qcow) {
1380
            int n;
1381
            if (bdrv_is_allocated(s->qcow, sector_num, nb_sectors-i, &n)) {
1382
DLOG(fprintf(stderr, "sectors %d+%d allocated\n", (int)sector_num, n));
1383
                if (bdrv_read(s->qcow, sector_num, buf + i*0x200, n)) {
1384
                    return -1;
1385
                }
1386
                i += n - 1;
1387
                sector_num += n - 1;
1388
                continue;
1389
            }
1390
DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num));
1391
        }
1392
        if(sector_num<s->faked_sectors) {
1393
            if(sector_num<s->first_sectors_number)
1394
                memcpy(buf+i*0x200,&(s->first_sectors[sector_num*0x200]),0x200);
1395
            else if(sector_num-s->first_sectors_number<s->sectors_per_fat)
1396
                memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number)*0x200]),0x200);
1397
            else if(sector_num-s->first_sectors_number-s->sectors_per_fat<s->sectors_per_fat)
1398
                memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number-s->sectors_per_fat)*0x200]),0x200);
1399
        } else {
1400
            uint32_t sector=sector_num-s->faked_sectors,
1401
            sector_offset_in_cluster=(sector%s->sectors_per_cluster),
1402
            cluster_num=sector/s->sectors_per_cluster;
1403
            if(cluster_num > s->cluster_count || read_cluster(s, cluster_num) != 0) {
1404
                /* LATER TODO: strict: return -1; */
1405
                memset(buf+i*0x200,0,0x200);
1406
                continue;
1407
            }
1408
            memcpy(buf+i*0x200,s->cluster+sector_offset_in_cluster*0x200,0x200);
1409
        }
1410
    }
1411
    return 0;
1412
}
1413

    
1414
static coroutine_fn int vvfat_co_read(BlockDriverState *bs, int64_t sector_num,
1415
                                      uint8_t *buf, int nb_sectors)
1416
{
1417
    int ret;
1418
    BDRVVVFATState *s = bs->opaque;
1419
    qemu_co_mutex_lock(&s->lock);
1420
    ret = vvfat_read(bs, sector_num, buf, nb_sectors);
1421
    qemu_co_mutex_unlock(&s->lock);
1422
    return ret;
1423
}
1424

    
1425
/* LATER TODO: statify all functions */
1426

    
1427
/*
1428
 * Idea of the write support (use snapshot):
1429
 *
1430
 * 1. check if all data is consistent, recording renames, modifications,
1431
 *    new files and directories (in s->commits).
1432
 *
1433
 * 2. if the data is not consistent, stop committing
1434
 *
1435
 * 3. handle renames, and create new files and directories (do not yet
1436
 *    write their contents)
1437
 *
1438
 * 4. walk the directories, fixing the mapping and direntries, and marking
1439
 *    the handled mappings as not deleted
1440
 *
1441
 * 5. commit the contents of the files
1442
 *
1443
 * 6. handle deleted files and directories
1444
 *
1445
 */
1446

    
1447
typedef struct commit_t {
1448
    char* path;
1449
    union {
1450
        struct { uint32_t cluster; } rename;
1451
        struct { int dir_index; uint32_t modified_offset; } writeout;
1452
        struct { uint32_t first_cluster; } new_file;
1453
        struct { uint32_t cluster; } mkdir;
1454
    } param;
1455
    /* DELETEs and RMDIRs are handled differently: see handle_deletes() */
1456
    enum {
1457
        ACTION_RENAME, ACTION_WRITEOUT, ACTION_NEW_FILE, ACTION_MKDIR
1458
    } action;
1459
} commit_t;
1460

    
1461
static void clear_commits(BDRVVVFATState* s)
1462
{
1463
    int i;
1464
DLOG(fprintf(stderr, "clear_commits (%d commits)\n", s->commits.next));
1465
    for (i = 0; i < s->commits.next; i++) {
1466
        commit_t* commit = array_get(&(s->commits), i);
1467
        assert(commit->path || commit->action == ACTION_WRITEOUT);
1468
        if (commit->action != ACTION_WRITEOUT) {
1469
            assert(commit->path);
1470
            g_free(commit->path);
1471
        } else
1472
            assert(commit->path == NULL);
1473
    }
1474
    s->commits.next = 0;
1475
}
1476

    
1477
static void schedule_rename(BDRVVVFATState* s,
1478
        uint32_t cluster, char* new_path)
1479
{
1480
    commit_t* commit = array_get_next(&(s->commits));
1481
    commit->path = new_path;
1482
    commit->param.rename.cluster = cluster;
1483
    commit->action = ACTION_RENAME;
1484
}
1485

    
1486
static void schedule_writeout(BDRVVVFATState* s,
1487
        int dir_index, uint32_t modified_offset)
1488
{
1489
    commit_t* commit = array_get_next(&(s->commits));
1490
    commit->path = NULL;
1491
    commit->param.writeout.dir_index = dir_index;
1492
    commit->param.writeout.modified_offset = modified_offset;
1493
    commit->action = ACTION_WRITEOUT;
1494
}
1495

    
1496
static void schedule_new_file(BDRVVVFATState* s,
1497
        char* path, uint32_t first_cluster)
1498
{
1499
    commit_t* commit = array_get_next(&(s->commits));
1500
    commit->path = path;
1501
    commit->param.new_file.first_cluster = first_cluster;
1502
    commit->action = ACTION_NEW_FILE;
1503
}
1504

    
1505
static void schedule_mkdir(BDRVVVFATState* s, uint32_t cluster, char* path)
1506
{
1507
    commit_t* commit = array_get_next(&(s->commits));
1508
    commit->path = path;
1509
    commit->param.mkdir.cluster = cluster;
1510
    commit->action = ACTION_MKDIR;
1511
}
1512

    
1513
typedef struct {
1514
    /*
1515
     * Since the sequence number is at most 0x3f, and the filename
1516
     * length is at most 13 times the sequence number, the maximal
1517
     * filename length is 0x3f * 13 bytes.
1518
     */
1519
    unsigned char name[0x3f * 13 + 1];
1520
    int checksum, len;
1521
    int sequence_number;
1522
} long_file_name;
1523

    
1524
static void lfn_init(long_file_name* lfn)
1525
{
1526
   lfn->sequence_number = lfn->len = 0;
1527
   lfn->checksum = 0x100;
1528
}
1529

    
1530
/* return 0 if parsed successfully, > 0 if no long name, < 0 if error */
1531
static int parse_long_name(long_file_name* lfn,
1532
        const direntry_t* direntry)
1533
{
1534
    int i, j, offset;
1535
    const unsigned char* pointer = (const unsigned char*)direntry;
1536

    
1537
    if (!is_long_name(direntry))
1538
        return 1;
1539

    
1540
    if (pointer[0] & 0x40) {
1541
        lfn->sequence_number = pointer[0] & 0x3f;
1542
        lfn->checksum = pointer[13];
1543
        lfn->name[0] = 0;
1544
        lfn->name[lfn->sequence_number * 13] = 0;
1545
    } else if ((pointer[0] & 0x3f) != --lfn->sequence_number)
1546
        return -1;
1547
    else if (pointer[13] != lfn->checksum)
1548
        return -2;
1549
    else if (pointer[12] || pointer[26] || pointer[27])
1550
        return -3;
1551

    
1552
    offset = 13 * (lfn->sequence_number - 1);
1553
    for (i = 0, j = 1; i < 13; i++, j+=2) {
1554
        if (j == 11)
1555
            j = 14;
1556
        else if (j == 26)
1557
            j = 28;
1558

    
1559
        if (pointer[j+1] == 0)
1560
            lfn->name[offset + i] = pointer[j];
1561
        else if (pointer[j+1] != 0xff || (pointer[0] & 0x40) == 0)
1562
            return -4;
1563
        else
1564
            lfn->name[offset + i] = 0;
1565
    }
1566

    
1567
    if (pointer[0] & 0x40)
1568
        lfn->len = offset + strlen((char*)lfn->name + offset);
1569

    
1570
    return 0;
1571
}
1572

    
1573
/* returns 0 if successful, >0 if no short_name, and <0 on error */
1574
static int parse_short_name(BDRVVVFATState* s,
1575
        long_file_name* lfn, direntry_t* direntry)
1576
{
1577
    int i, j;
1578

    
1579
    if (!is_short_name(direntry))
1580
        return 1;
1581

    
1582
    for (j = 7; j >= 0 && direntry->name[j] == ' '; j--);
1583
    for (i = 0; i <= j; i++) {
1584
        if (direntry->name[i] <= ' ' || direntry->name[i] > 0x7f)
1585
            return -1;
1586
        else if (s->downcase_short_names)
1587
            lfn->name[i] = qemu_tolower(direntry->name[i]);
1588
        else
1589
            lfn->name[i] = direntry->name[i];
1590
    }
1591

    
1592
    for (j = 2; j >= 0 && direntry->name[8 + j] == ' '; j--) {
1593
    }
1594
    if (j >= 0) {
1595
        lfn->name[i++] = '.';
1596
        lfn->name[i + j + 1] = '\0';
1597
        for (;j >= 0; j--) {
1598
            uint8_t c = direntry->name[8 + j];
1599
            if (c <= ' ' || c > 0x7f) {
1600
                return -2;
1601
            } else if (s->downcase_short_names) {
1602
                lfn->name[i + j] = qemu_tolower(c);
1603
            } else {
1604
                lfn->name[i + j] = c;
1605
            }
1606
        }
1607
    } else
1608
        lfn->name[i + j + 1] = '\0';
1609

    
1610
    lfn->len = strlen((char*)lfn->name);
1611

    
1612
    return 0;
1613
}
1614

    
1615
static inline uint32_t modified_fat_get(BDRVVVFATState* s,
1616
        unsigned int cluster)
1617
{
1618
    if (cluster < s->last_cluster_of_root_directory) {
1619
        if (cluster + 1 == s->last_cluster_of_root_directory)
1620
            return s->max_fat_value;
1621
        else
1622
            return cluster + 1;
1623
    }
1624

    
1625
    if (s->fat_type==32) {
1626
        uint32_t* entry=((uint32_t*)s->fat2)+cluster;
1627
        return le32_to_cpu(*entry);
1628
    } else if (s->fat_type==16) {
1629
        uint16_t* entry=((uint16_t*)s->fat2)+cluster;
1630
        return le16_to_cpu(*entry);
1631
    } else {
1632
        const uint8_t* x=s->fat2+cluster*3/2;
1633
        return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
1634
    }
1635
}
1636

    
1637
static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num)
1638
{
1639
    int was_modified = 0;
1640
    int i, dummy;
1641

    
1642
    if (s->qcow == NULL)
1643
        return 0;
1644

    
1645
    for (i = 0; !was_modified && i < s->sectors_per_cluster; i++)
1646
        was_modified = bdrv_is_allocated(s->qcow,
1647
                cluster2sector(s, cluster_num) + i, 1, &dummy);
1648

    
1649
    return was_modified;
1650
}
1651

    
1652
static const char* get_basename(const char* path)
1653
{
1654
    char* basename = strrchr(path, '/');
1655
    if (basename == NULL)
1656
        return path;
1657
    else
1658
        return basename + 1; /* strip '/' */
1659
}
1660

    
1661
/*
1662
 * The array s->used_clusters holds the states of the clusters. If it is
1663
 * part of a file, it has bit 2 set, in case of a directory, bit 1. If it
1664
 * was modified, bit 3 is set.
1665
 * If any cluster is allocated, but not part of a file or directory, this
1666
 * driver refuses to commit.
1667
 */
1668
typedef enum {
1669
     USED_DIRECTORY = 1, USED_FILE = 2, USED_ANY = 3, USED_ALLOCATED = 4
1670
} used_t;
1671

    
1672
/*
1673
 * get_cluster_count_for_direntry() not only determines how many clusters
1674
 * are occupied by direntry, but also if it was renamed or modified.
1675
 *
1676
 * A file is thought to be renamed *only* if there already was a file with
1677
 * exactly the same first cluster, but a different name.
1678
 *
1679
 * Further, the files/directories handled by this function are
1680
 * assumed to be *not* deleted (and *only* those).
1681
 */
1682
static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
1683
        direntry_t* direntry, const char* path)
1684
{
1685
    /*
1686
     * This is a little bit tricky:
1687
     * IF the guest OS just inserts a cluster into the file chain,
1688
     * and leaves the rest alone, (i.e. the original file had clusters
1689
     * 15 -> 16, but now has 15 -> 32 -> 16), then the following happens:
1690
     *
1691
     * - do_commit will write the cluster into the file at the given
1692
     *   offset, but
1693
     *
1694
     * - the cluster which is overwritten should be moved to a later
1695
     *   position in the file.
1696
     *
1697
     * I am not aware that any OS does something as braindead, but this
1698
     * situation could happen anyway when not committing for a long time.
1699
     * Just to be sure that this does not bite us, detect it, and copy the
1700
     * contents of the clusters to-be-overwritten into the qcow.
1701
     */
1702
    int copy_it = 0;
1703
    int was_modified = 0;
1704
    int32_t ret = 0;
1705

    
1706
    uint32_t cluster_num = begin_of_direntry(direntry);
1707
    uint32_t offset = 0;
1708
    int first_mapping_index = -1;
1709
    mapping_t* mapping = NULL;
1710
    const char* basename2 = NULL;
1711

    
1712
    vvfat_close_current_file(s);
1713

    
1714
    /* the root directory */
1715
    if (cluster_num == 0)
1716
        return 0;
1717

    
1718
    /* write support */
1719
    if (s->qcow) {
1720
        basename2 = get_basename(path);
1721

    
1722
        mapping = find_mapping_for_cluster(s, cluster_num);
1723

    
1724
        if (mapping) {
1725
            const char* basename;
1726

    
1727
            assert(mapping->mode & MODE_DELETED);
1728
            mapping->mode &= ~MODE_DELETED;
1729

    
1730
            basename = get_basename(mapping->path);
1731

    
1732
            assert(mapping->mode & MODE_NORMAL);
1733

    
1734
            /* rename */
1735
            if (strcmp(basename, basename2))
1736
                schedule_rename(s, cluster_num, g_strdup(path));
1737
        } else if (is_file(direntry))
1738
            /* new file */
1739
            schedule_new_file(s, g_strdup(path), cluster_num);
1740
        else {
1741
            abort();
1742
            return 0;
1743
        }
1744
    }
1745

    
1746
    while(1) {
1747
        if (s->qcow) {
1748
            if (!copy_it && cluster_was_modified(s, cluster_num)) {
1749
                if (mapping == NULL ||
1750
                        mapping->begin > cluster_num ||
1751
                        mapping->end <= cluster_num)
1752
                mapping = find_mapping_for_cluster(s, cluster_num);
1753

    
1754

    
1755
                if (mapping &&
1756
                        (mapping->mode & MODE_DIRECTORY) == 0) {
1757

    
1758
                    /* was modified in qcow */
1759
                    if (offset != mapping->info.file.offset + s->cluster_size
1760
                            * (cluster_num - mapping->begin)) {
1761
                        /* offset of this cluster in file chain has changed */
1762
                        abort();
1763
                        copy_it = 1;
1764
                    } else if (offset == 0) {
1765
                        const char* basename = get_basename(mapping->path);
1766

    
1767
                        if (strcmp(basename, basename2))
1768
                            copy_it = 1;
1769
                        first_mapping_index = array_index(&(s->mapping), mapping);
1770
                    }
1771

    
1772
                    if (mapping->first_mapping_index != first_mapping_index
1773
                            && mapping->info.file.offset > 0) {
1774
                        abort();
1775
                        copy_it = 1;
1776
                    }
1777

    
1778
                    /* need to write out? */
1779
                    if (!was_modified && is_file(direntry)) {
1780
                        was_modified = 1;
1781
                        schedule_writeout(s, mapping->dir_index, offset);
1782
                    }
1783
                }
1784
            }
1785

    
1786
            if (copy_it) {
1787
                int i, dummy;
1788
                /*
1789
                 * This is horribly inefficient, but that is okay, since
1790
                 * it is rarely executed, if at all.
1791
                 */
1792
                int64_t offset = cluster2sector(s, cluster_num);
1793

    
1794
                vvfat_close_current_file(s);
1795
                for (i = 0; i < s->sectors_per_cluster; i++) {
1796
                    if (!bdrv_is_allocated(s->qcow, offset + i, 1, &dummy)) {
1797
                        if (vvfat_read(s->bs, offset, s->cluster_buffer, 1)) {
1798
                            return -1;
1799
                        }
1800
                        if (bdrv_write(s->qcow, offset, s->cluster_buffer, 1)) {
1801
                            return -2;
1802
                        }
1803
                    }
1804
                }
1805
            }
1806
        }
1807

    
1808
        ret++;
1809
        if (s->used_clusters[cluster_num] & USED_ANY)
1810
            return 0;
1811
        s->used_clusters[cluster_num] = USED_FILE;
1812

    
1813
        cluster_num = modified_fat_get(s, cluster_num);
1814

    
1815
        if (fat_eof(s, cluster_num))
1816
            return ret;
1817
        else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
1818
            return -1;
1819

    
1820
        offset += s->cluster_size;
1821
    }
1822
}
1823

    
1824
/*
1825
 * This function looks at the modified data (qcow).
1826
 * It returns 0 upon inconsistency or error, and the number of clusters
1827
 * used by the directory, its subdirectories and their files.
1828
 */
1829
static int check_directory_consistency(BDRVVVFATState *s,
1830
        int cluster_num, const char* path)
1831
{
1832
    int ret = 0;
1833
    unsigned char* cluster = g_malloc(s->cluster_size);
1834
    direntry_t* direntries = (direntry_t*)cluster;
1835
    mapping_t* mapping = find_mapping_for_cluster(s, cluster_num);
1836

    
1837
    long_file_name lfn;
1838
    int path_len = strlen(path);
1839
    char path2[PATH_MAX + 1];
1840

    
1841
    assert(path_len < PATH_MAX); /* len was tested before! */
1842
    pstrcpy(path2, sizeof(path2), path);
1843
    path2[path_len] = '/';
1844
    path2[path_len + 1] = '\0';
1845

    
1846
    if (mapping) {
1847
        const char* basename = get_basename(mapping->path);
1848
        const char* basename2 = get_basename(path);
1849

    
1850
        assert(mapping->mode & MODE_DIRECTORY);
1851

    
1852
        assert(mapping->mode & MODE_DELETED);
1853
        mapping->mode &= ~MODE_DELETED;
1854

    
1855
        if (strcmp(basename, basename2))
1856
            schedule_rename(s, cluster_num, g_strdup(path));
1857
    } else
1858
        /* new directory */
1859
        schedule_mkdir(s, cluster_num, g_strdup(path));
1860

    
1861
    lfn_init(&lfn);
1862
    do {
1863
        int i;
1864
        int subret = 0;
1865

    
1866
        ret++;
1867

    
1868
        if (s->used_clusters[cluster_num] & USED_ANY) {
1869
            fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
1870
            return 0;
1871
        }
1872
        s->used_clusters[cluster_num] = USED_DIRECTORY;
1873

    
1874
DLOG(fprintf(stderr, "read cluster %d (sector %d)\n", (int)cluster_num, (int)cluster2sector(s, cluster_num)));
1875
        subret = vvfat_read(s->bs, cluster2sector(s, cluster_num), cluster,
1876
                s->sectors_per_cluster);
1877
        if (subret) {
1878
            fprintf(stderr, "Error fetching direntries\n");
1879
        fail:
1880
            g_free(cluster);
1881
            return 0;
1882
        }
1883

    
1884
        for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
1885
            int cluster_count = 0;
1886

    
1887
DLOG(fprintf(stderr, "check direntry %d:\n", i); print_direntry(direntries + i));
1888
            if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
1889
                    is_free(direntries + i))
1890
                continue;
1891

    
1892
            subret = parse_long_name(&lfn, direntries + i);
1893
            if (subret < 0) {
1894
                fprintf(stderr, "Error in long name\n");
1895
                goto fail;
1896
            }
1897
            if (subret == 0 || is_free(direntries + i))
1898
                continue;
1899

    
1900
            if (fat_chksum(direntries+i) != lfn.checksum) {
1901
                subret = parse_short_name(s, &lfn, direntries + i);
1902
                if (subret < 0) {
1903
                    fprintf(stderr, "Error in short name (%d)\n", subret);
1904
                    goto fail;
1905
                }
1906
                if (subret > 0 || !strcmp((char*)lfn.name, ".")
1907
                        || !strcmp((char*)lfn.name, ".."))
1908
                    continue;
1909
            }
1910
            lfn.checksum = 0x100; /* cannot use long name twice */
1911

    
1912
            if (path_len + 1 + lfn.len >= PATH_MAX) {
1913
                fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
1914
                goto fail;
1915
            }
1916
            pstrcpy(path2 + path_len + 1, sizeof(path2) - path_len - 1,
1917
                    (char*)lfn.name);
1918

    
1919
            if (is_directory(direntries + i)) {
1920
                if (begin_of_direntry(direntries + i) == 0) {
1921
                    DLOG(fprintf(stderr, "invalid begin for directory: %s\n", path2); print_direntry(direntries + i));
1922
                    goto fail;
1923
                }
1924
                cluster_count = check_directory_consistency(s,
1925
                        begin_of_direntry(direntries + i), path2);
1926
                if (cluster_count == 0) {
1927
                    DLOG(fprintf(stderr, "problem in directory %s:\n", path2); print_direntry(direntries + i));
1928
                    goto fail;
1929
                }
1930
            } else if (is_file(direntries + i)) {
1931
                /* check file size with FAT */
1932
                cluster_count = get_cluster_count_for_direntry(s, direntries + i, path2);
1933
                if (cluster_count !=
1934
                        (le32_to_cpu(direntries[i].size) + s->cluster_size
1935
                         - 1) / s->cluster_size) {
1936
                    DLOG(fprintf(stderr, "Cluster count mismatch\n"));
1937
                    goto fail;
1938
                }
1939
            } else
1940
                abort(); /* cluster_count = 0; */
1941

    
1942
            ret += cluster_count;
1943
        }
1944

    
1945
        cluster_num = modified_fat_get(s, cluster_num);
1946
    } while(!fat_eof(s, cluster_num));
1947

    
1948
    g_free(cluster);
1949
    return ret;
1950
}
1951

    
1952
/* returns 1 on success */
1953
static int is_consistent(BDRVVVFATState* s)
1954
{
1955
    int i, check;
1956
    int used_clusters_count = 0;
1957

    
1958
DLOG(checkpoint());
1959
    /*
1960
     * - get modified FAT
1961
     * - compare the two FATs (TODO)
1962
     * - get buffer for marking used clusters
1963
     * - recurse direntries from root (using bs->bdrv_read to make
1964
     *    sure to get the new data)
1965
     *   - check that the FAT agrees with the size
1966
     *   - count the number of clusters occupied by this directory and
1967
     *     its files
1968
     * - check that the cumulative used cluster count agrees with the
1969
     *   FAT
1970
     * - if all is fine, return number of used clusters
1971
     */
1972
    if (s->fat2 == NULL) {
1973
        int size = 0x200 * s->sectors_per_fat;
1974
        s->fat2 = g_malloc(size);
1975
        memcpy(s->fat2, s->fat.pointer, size);
1976
    }
1977
    check = vvfat_read(s->bs,
1978
            s->first_sectors_number, s->fat2, s->sectors_per_fat);
1979
    if (check) {
1980
        fprintf(stderr, "Could not copy fat\n");
1981
        return 0;
1982
    }
1983
    assert (s->used_clusters);
1984
    for (i = 0; i < sector2cluster(s, s->sector_count); i++)
1985
        s->used_clusters[i] &= ~USED_ANY;
1986

    
1987
    clear_commits(s);
1988

    
1989
    /* mark every mapped file/directory as deleted.
1990
     * (check_directory_consistency() will unmark those still present). */
1991
    if (s->qcow)
1992
        for (i = 0; i < s->mapping.next; i++) {
1993
            mapping_t* mapping = array_get(&(s->mapping), i);
1994
            if (mapping->first_mapping_index < 0)
1995
                mapping->mode |= MODE_DELETED;
1996
        }
1997

    
1998
    used_clusters_count = check_directory_consistency(s, 0, s->path);
1999
    if (used_clusters_count <= 0) {
2000
        DLOG(fprintf(stderr, "problem in directory\n"));
2001
        return 0;
2002
    }
2003

    
2004
    check = s->last_cluster_of_root_directory;
2005
    for (i = check; i < sector2cluster(s, s->sector_count); i++) {
2006
        if (modified_fat_get(s, i)) {
2007
            if(!s->used_clusters[i]) {
2008
                DLOG(fprintf(stderr, "FAT was modified (%d), but cluster is not used?\n", i));
2009
                return 0;
2010
            }
2011
            check++;
2012
        }
2013

    
2014
        if (s->used_clusters[i] == USED_ALLOCATED) {
2015
            /* allocated, but not used... */
2016
            DLOG(fprintf(stderr, "unused, modified cluster: %d\n", i));
2017
            return 0;
2018
        }
2019
    }
2020

    
2021
    if (check != used_clusters_count)
2022
        return 0;
2023

    
2024
    return used_clusters_count;
2025
}
2026

    
2027
static inline void adjust_mapping_indices(BDRVVVFATState* s,
2028
        int offset, int adjust)
2029
{
2030
    int i;
2031

    
2032
    for (i = 0; i < s->mapping.next; i++) {
2033
        mapping_t* mapping = array_get(&(s->mapping), i);
2034

    
2035
#define ADJUST_MAPPING_INDEX(name) \
2036
        if (mapping->name >= offset) \
2037
            mapping->name += adjust
2038

    
2039
        ADJUST_MAPPING_INDEX(first_mapping_index);
2040
        if (mapping->mode & MODE_DIRECTORY)
2041
            ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
2042
    }
2043
}
2044

    
2045
/* insert or update mapping */
2046
static mapping_t* insert_mapping(BDRVVVFATState* s,
2047
        uint32_t begin, uint32_t end)
2048
{
2049
    /*
2050
     * - find mapping where mapping->begin >= begin,
2051
     * - if mapping->begin > begin: insert
2052
     *   - adjust all references to mappings!
2053
     * - else: adjust
2054
     * - replace name
2055
     */
2056
    int index = find_mapping_for_cluster_aux(s, begin, 0, s->mapping.next);
2057
    mapping_t* mapping = NULL;
2058
    mapping_t* first_mapping = array_get(&(s->mapping), 0);
2059

    
2060
    if (index < s->mapping.next && (mapping = array_get(&(s->mapping), index))
2061
            && mapping->begin < begin) {
2062
        mapping->end = begin;
2063
        index++;
2064
        mapping = array_get(&(s->mapping), index);
2065
    }
2066
    if (index >= s->mapping.next || mapping->begin > begin) {
2067
        mapping = array_insert(&(s->mapping), index, 1);
2068
        mapping->path = NULL;
2069
        adjust_mapping_indices(s, index, +1);
2070
    }
2071

    
2072
    mapping->begin = begin;
2073
    mapping->end = end;
2074

    
2075
DLOG(mapping_t* next_mapping;
2076
assert(index + 1 >= s->mapping.next ||
2077
((next_mapping = array_get(&(s->mapping), index + 1)) &&
2078
 next_mapping->begin >= end)));
2079

    
2080
    if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
2081
        s->current_mapping = array_get(&(s->mapping),
2082
                s->current_mapping - first_mapping);
2083

    
2084
    return mapping;
2085
}
2086

    
2087
static int remove_mapping(BDRVVVFATState* s, int mapping_index)
2088
{
2089
    mapping_t* mapping = array_get(&(s->mapping), mapping_index);
2090
    mapping_t* first_mapping = array_get(&(s->mapping), 0);
2091

    
2092
    /* free mapping */
2093
    if (mapping->first_mapping_index < 0) {
2094
        g_free(mapping->path);
2095
    }
2096

    
2097
    /* remove from s->mapping */
2098
    array_remove(&(s->mapping), mapping_index);
2099

    
2100
    /* adjust all references to mappings */
2101
    adjust_mapping_indices(s, mapping_index, -1);
2102

    
2103
    if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
2104
        s->current_mapping = array_get(&(s->mapping),
2105
                s->current_mapping - first_mapping);
2106

    
2107
    return 0;
2108
}
2109

    
2110
static void adjust_dirindices(BDRVVVFATState* s, int offset, int adjust)
2111
{
2112
    int i;
2113
    for (i = 0; i < s->mapping.next; i++) {
2114
        mapping_t* mapping = array_get(&(s->mapping), i);
2115
        if (mapping->dir_index >= offset)
2116
            mapping->dir_index += adjust;
2117
        if ((mapping->mode & MODE_DIRECTORY) &&
2118
                mapping->info.dir.first_dir_index >= offset)
2119
            mapping->info.dir.first_dir_index += adjust;
2120
    }
2121
}
2122

    
2123
static direntry_t* insert_direntries(BDRVVVFATState* s,
2124
        int dir_index, int count)
2125
{
2126
    /*
2127
     * make room in s->directory,
2128
     * adjust_dirindices
2129
     */
2130
    direntry_t* result = array_insert(&(s->directory), dir_index, count);
2131
    if (result == NULL)
2132
        return NULL;
2133
    adjust_dirindices(s, dir_index, count);
2134
    return result;
2135
}
2136

    
2137
static int remove_direntries(BDRVVVFATState* s, int dir_index, int count)
2138
{
2139
    int ret = array_remove_slice(&(s->directory), dir_index, count);
2140
    if (ret)
2141
        return ret;
2142
    adjust_dirindices(s, dir_index, -count);
2143
    return 0;
2144
}
2145

    
2146
/*
2147
 * Adapt the mappings of the cluster chain starting at first cluster
2148
 * (i.e. if a file starts at first_cluster, the chain is followed according
2149
 * to the modified fat, and the corresponding entries in s->mapping are
2150
 * adjusted)
2151
 */
2152
static int commit_mappings(BDRVVVFATState* s,
2153
        uint32_t first_cluster, int dir_index)
2154
{
2155
    mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2156
    direntry_t* direntry = array_get(&(s->directory), dir_index);
2157
    uint32_t cluster = first_cluster;
2158

    
2159
    vvfat_close_current_file(s);
2160

    
2161
    assert(mapping);
2162
    assert(mapping->begin == first_cluster);
2163
    mapping->first_mapping_index = -1;
2164
    mapping->dir_index = dir_index;
2165
    mapping->mode = (dir_index <= 0 || is_directory(direntry)) ?
2166
        MODE_DIRECTORY : MODE_NORMAL;
2167

    
2168
    while (!fat_eof(s, cluster)) {
2169
        uint32_t c, c1;
2170

    
2171
        for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
2172
                c = c1, c1 = modified_fat_get(s, c1));
2173

    
2174
        c++;
2175
        if (c > mapping->end) {
2176
            int index = array_index(&(s->mapping), mapping);
2177
            int i, max_i = s->mapping.next - index;
2178
            for (i = 1; i < max_i && mapping[i].begin < c; i++);
2179
            while (--i > 0)
2180
                remove_mapping(s, index + 1);
2181
        }
2182
        assert(mapping == array_get(&(s->mapping), s->mapping.next - 1)
2183
                || mapping[1].begin >= c);
2184
        mapping->end = c;
2185

    
2186
        if (!fat_eof(s, c1)) {
2187
            int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next);
2188
            mapping_t* next_mapping = i >= s->mapping.next ? NULL :
2189
                array_get(&(s->mapping), i);
2190

    
2191
            if (next_mapping == NULL || next_mapping->begin > c1) {
2192
                int i1 = array_index(&(s->mapping), mapping);
2193

    
2194
                next_mapping = insert_mapping(s, c1, c1+1);
2195

    
2196
                if (c1 < c)
2197
                    i1++;
2198
                mapping = array_get(&(s->mapping), i1);
2199
            }
2200

    
2201
            next_mapping->dir_index = mapping->dir_index;
2202
            next_mapping->first_mapping_index =
2203
                mapping->first_mapping_index < 0 ?
2204
                array_index(&(s->mapping), mapping) :
2205
                mapping->first_mapping_index;
2206
            next_mapping->path = mapping->path;
2207
            next_mapping->mode = mapping->mode;
2208
            next_mapping->read_only = mapping->read_only;
2209
            if (mapping->mode & MODE_DIRECTORY) {
2210
                next_mapping->info.dir.parent_mapping_index =
2211
                        mapping->info.dir.parent_mapping_index;
2212
                next_mapping->info.dir.first_dir_index =
2213
                        mapping->info.dir.first_dir_index +
2214
                        0x10 * s->sectors_per_cluster *
2215
                        (mapping->end - mapping->begin);
2216
            } else
2217
                next_mapping->info.file.offset = mapping->info.file.offset +
2218
                        mapping->end - mapping->begin;
2219

    
2220
            mapping = next_mapping;
2221
        }
2222

    
2223
        cluster = c1;
2224
    }
2225

    
2226
    return 0;
2227
}
2228

    
2229
static int commit_direntries(BDRVVVFATState* s,
2230
        int dir_index, int parent_mapping_index)
2231
{
2232
    direntry_t* direntry = array_get(&(s->directory), dir_index);
2233
    uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
2234
    mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2235

    
2236
    int factor = 0x10 * s->sectors_per_cluster;
2237
    int old_cluster_count, new_cluster_count;
2238
    int current_dir_index = mapping->info.dir.first_dir_index;
2239
    int first_dir_index = current_dir_index;
2240
    int ret, i;
2241
    uint32_t c;
2242

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

    
2245
    assert(direntry);
2246
    assert(mapping);
2247
    assert(mapping->begin == first_cluster);
2248
    assert(mapping->info.dir.first_dir_index < s->directory.next);
2249
    assert(mapping->mode & MODE_DIRECTORY);
2250
    assert(dir_index == 0 || is_directory(direntry));
2251

    
2252
    mapping->info.dir.parent_mapping_index = parent_mapping_index;
2253

    
2254
    if (first_cluster == 0) {
2255
        old_cluster_count = new_cluster_count =
2256
            s->last_cluster_of_root_directory;
2257
    } else {
2258
        for (old_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2259
                c = fat_get(s, c))
2260
            old_cluster_count++;
2261

    
2262
        for (new_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2263
                c = modified_fat_get(s, c))
2264
            new_cluster_count++;
2265
    }
2266

    
2267
    if (new_cluster_count > old_cluster_count) {
2268
        if (insert_direntries(s,
2269
                current_dir_index + factor * old_cluster_count,
2270
                factor * (new_cluster_count - old_cluster_count)) == NULL)
2271
            return -1;
2272
    } else if (new_cluster_count < old_cluster_count)
2273
        remove_direntries(s,
2274
                current_dir_index + factor * new_cluster_count,
2275
                factor * (old_cluster_count - new_cluster_count));
2276

    
2277
    for (c = first_cluster; !fat_eof(s, c); c = modified_fat_get(s, c)) {
2278
        void* direntry = array_get(&(s->directory), current_dir_index);
2279
        int ret = vvfat_read(s->bs, cluster2sector(s, c), direntry,
2280
                s->sectors_per_cluster);
2281
        if (ret)
2282
            return ret;
2283
        assert(!strncmp(s->directory.pointer, "QEMU", 4));
2284
        current_dir_index += factor;
2285
    }
2286

    
2287
    ret = commit_mappings(s, first_cluster, dir_index);
2288
    if (ret)
2289
        return ret;
2290

    
2291
    /* recurse */
2292
    for (i = 0; i < factor * new_cluster_count; i++) {
2293
        direntry = array_get(&(s->directory), first_dir_index + i);
2294
        if (is_directory(direntry) && !is_dot(direntry)) {
2295
            mapping = find_mapping_for_cluster(s, first_cluster);
2296
            assert(mapping->mode & MODE_DIRECTORY);
2297
            ret = commit_direntries(s, first_dir_index + i,
2298
                array_index(&(s->mapping), mapping));
2299
            if (ret)
2300
                return ret;
2301
        }
2302
    }
2303

    
2304
    return 0;
2305
}
2306

    
2307
/* commit one file (adjust contents, adjust mapping),
2308
   return first_mapping_index */
2309
static int commit_one_file(BDRVVVFATState* s,
2310
        int dir_index, uint32_t offset)
2311
{
2312
    direntry_t* direntry = array_get(&(s->directory), dir_index);
2313
    uint32_t c = begin_of_direntry(direntry);
2314
    uint32_t first_cluster = c;
2315
    mapping_t* mapping = find_mapping_for_cluster(s, c);
2316
    uint32_t size = filesize_of_direntry(direntry);
2317
    char* cluster = g_malloc(s->cluster_size);
2318
    uint32_t i;
2319
    int fd = 0;
2320

    
2321
    assert(offset < size);
2322
    assert((offset % s->cluster_size) == 0);
2323

    
2324
    for (i = s->cluster_size; i < offset; i += s->cluster_size)
2325
        c = modified_fat_get(s, c);
2326

    
2327
    fd = qemu_open(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666);
2328
    if (fd < 0) {
2329
        fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path,
2330
                strerror(errno), errno);
2331
        g_free(cluster);
2332
        return fd;
2333
    }
2334
    if (offset > 0) {
2335
        if (lseek(fd, offset, SEEK_SET) != offset) {
2336
            qemu_close(fd);
2337
            g_free(cluster);
2338
            return -3;
2339
        }
2340
    }
2341

    
2342
    while (offset < size) {
2343
        uint32_t c1;
2344
        int rest_size = (size - offset > s->cluster_size ?
2345
                s->cluster_size : size - offset);
2346
        int ret;
2347

    
2348
        c1 = modified_fat_get(s, c);
2349

    
2350
        assert((size - offset == 0 && fat_eof(s, c)) ||
2351
                (size > offset && c >=2 && !fat_eof(s, c)));
2352

    
2353
        ret = vvfat_read(s->bs, cluster2sector(s, c),
2354
            (uint8_t*)cluster, (rest_size + 0x1ff) / 0x200);
2355

    
2356
        if (ret < 0) {
2357
            qemu_close(fd);
2358
            g_free(cluster);
2359
            return ret;
2360
        }
2361

    
2362
        if (write(fd, cluster, rest_size) < 0) {
2363
            qemu_close(fd);
2364
            g_free(cluster);
2365
            return -2;
2366
        }
2367

    
2368
        offset += rest_size;
2369
        c = c1;
2370
    }
2371

    
2372
    if (ftruncate(fd, size)) {
2373
        perror("ftruncate()");
2374
        qemu_close(fd);
2375
        g_free(cluster);
2376
        return -4;
2377
    }
2378
    qemu_close(fd);
2379
    g_free(cluster);
2380

    
2381
    return commit_mappings(s, first_cluster, dir_index);
2382
}
2383

    
2384
#ifdef DEBUG
2385
/* test, if all mappings point to valid direntries */
2386
static void check1(BDRVVVFATState* s)
2387
{
2388
    int i;
2389
    for (i = 0; i < s->mapping.next; i++) {
2390
        mapping_t* mapping = array_get(&(s->mapping), i);
2391
        if (mapping->mode & MODE_DELETED) {
2392
            fprintf(stderr, "deleted\n");
2393
            continue;
2394
        }
2395
        assert(mapping->dir_index < s->directory.next);
2396
        direntry_t* direntry = array_get(&(s->directory), mapping->dir_index);
2397
        assert(mapping->begin == begin_of_direntry(direntry) || mapping->first_mapping_index >= 0);
2398
        if (mapping->mode & MODE_DIRECTORY) {
2399
            assert(mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster * (mapping->end - mapping->begin) <= s->directory.next);
2400
            assert((mapping->info.dir.first_dir_index % (0x10 * s->sectors_per_cluster)) == 0);
2401
        }
2402
    }
2403
}
2404

    
2405
/* test, if all direntries have mappings */
2406
static void check2(BDRVVVFATState* s)
2407
{
2408
    int i;
2409
    int first_mapping = -1;
2410

    
2411
    for (i = 0; i < s->directory.next; i++) {
2412
        direntry_t* direntry = array_get(&(s->directory), i);
2413

    
2414
        if (is_short_name(direntry) && begin_of_direntry(direntry)) {
2415
            mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
2416
            assert(mapping);
2417
            assert(mapping->dir_index == i || is_dot(direntry));
2418
            assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry));
2419
        }
2420

    
2421
        if ((i % (0x10 * s->sectors_per_cluster)) == 0) {
2422
            /* cluster start */
2423
            int j, count = 0;
2424

    
2425
            for (j = 0; j < s->mapping.next; j++) {
2426
                mapping_t* mapping = array_get(&(s->mapping), j);
2427
                if (mapping->mode & MODE_DELETED)
2428
                    continue;
2429
                if (mapping->mode & MODE_DIRECTORY) {
2430
                    if (mapping->info.dir.first_dir_index <= i && mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster > i) {
2431
                        assert(++count == 1);
2432
                        if (mapping->first_mapping_index == -1)
2433
                            first_mapping = array_index(&(s->mapping), mapping);
2434
                        else
2435
                            assert(first_mapping == mapping->first_mapping_index);
2436
                        if (mapping->info.dir.parent_mapping_index < 0)
2437
                            assert(j == 0);
2438
                        else {
2439
                            mapping_t* parent = array_get(&(s->mapping), mapping->info.dir.parent_mapping_index);
2440
                            assert(parent->mode & MODE_DIRECTORY);
2441
                            assert(parent->info.dir.first_dir_index < mapping->info.dir.first_dir_index);
2442
                        }
2443
                    }
2444
                }
2445
            }
2446
            if (count == 0)
2447
                first_mapping = -1;
2448
        }
2449
    }
2450
}
2451
#endif
2452

    
2453
static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2454
{
2455
    int i;
2456

    
2457
#ifdef DEBUG
2458
    fprintf(stderr, "handle_renames\n");
2459
    for (i = 0; i < s->commits.next; i++) {
2460
        commit_t* commit = array_get(&(s->commits), i);
2461
        fprintf(stderr, "%d, %s (%d, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action);
2462
    }
2463
#endif
2464

    
2465
    for (i = 0; i < s->commits.next;) {
2466
        commit_t* commit = array_get(&(s->commits), i);
2467
        if (commit->action == ACTION_RENAME) {
2468
            mapping_t* mapping = find_mapping_for_cluster(s,
2469
                    commit->param.rename.cluster);
2470
            char* old_path = mapping->path;
2471

    
2472
            assert(commit->path);
2473
            mapping->path = commit->path;
2474
            if (rename(old_path, mapping->path))
2475
                return -2;
2476

    
2477
            if (mapping->mode & MODE_DIRECTORY) {
2478
                int l1 = strlen(mapping->path);
2479
                int l2 = strlen(old_path);
2480
                int diff = l1 - l2;
2481
                direntry_t* direntry = array_get(&(s->directory),
2482
                        mapping->info.dir.first_dir_index);
2483
                uint32_t c = mapping->begin;
2484
                int i = 0;
2485

    
2486
                /* recurse */
2487
                while (!fat_eof(s, c)) {
2488
                    do {
2489
                        direntry_t* d = direntry + i;
2490

    
2491
                        if (is_file(d) || (is_directory(d) && !is_dot(d))) {
2492
                            mapping_t* m = find_mapping_for_cluster(s,
2493
                                    begin_of_direntry(d));
2494
                            int l = strlen(m->path);
2495
                            char* new_path = g_malloc(l + diff + 1);
2496

    
2497
                            assert(!strncmp(m->path, mapping->path, l2));
2498

    
2499
                            pstrcpy(new_path, l + diff + 1, mapping->path);
2500
                            pstrcpy(new_path + l1, l + diff + 1 - l1,
2501
                                    m->path + l2);
2502

    
2503
                            schedule_rename(s, m->begin, new_path);
2504
                        }
2505
                        i++;
2506
                    } while((i % (0x10 * s->sectors_per_cluster)) != 0);
2507
                    c = fat_get(s, c);
2508
                }
2509
            }
2510

    
2511
            g_free(old_path);
2512
            array_remove(&(s->commits), i);
2513
            continue;
2514
        } else if (commit->action == ACTION_MKDIR) {
2515
            mapping_t* mapping;
2516
            int j, parent_path_len;
2517

    
2518
#ifdef __MINGW32__
2519
            if (mkdir(commit->path))
2520
                return -5;
2521
#else
2522
            if (mkdir(commit->path, 0755))
2523
                return -5;
2524
#endif
2525

    
2526
            mapping = insert_mapping(s, commit->param.mkdir.cluster,
2527
                    commit->param.mkdir.cluster + 1);
2528
            if (mapping == NULL)
2529
                return -6;
2530

    
2531
            mapping->mode = MODE_DIRECTORY;
2532
            mapping->read_only = 0;
2533
            mapping->path = commit->path;
2534
            j = s->directory.next;
2535
            assert(j);
2536
            insert_direntries(s, s->directory.next,
2537
                    0x10 * s->sectors_per_cluster);
2538
            mapping->info.dir.first_dir_index = j;
2539

    
2540
            parent_path_len = strlen(commit->path)
2541
                - strlen(get_basename(commit->path)) - 1;
2542
            for (j = 0; j < s->mapping.next; j++) {
2543
                mapping_t* m = array_get(&(s->mapping), j);
2544
                if (m->first_mapping_index < 0 && m != mapping &&
2545
                        !strncmp(m->path, mapping->path, parent_path_len) &&
2546
                        strlen(m->path) == parent_path_len)
2547
                    break;
2548
            }
2549
            assert(j < s->mapping.next);
2550
            mapping->info.dir.parent_mapping_index = j;
2551

    
2552
            array_remove(&(s->commits), i);
2553
            continue;
2554
        }
2555

    
2556
        i++;
2557
    }
2558
    return 0;
2559
}
2560

    
2561
/*
2562
 * TODO: make sure that the short name is not matching *another* file
2563
 */
2564
static int handle_commits(BDRVVVFATState* s)
2565
{
2566
    int i, fail = 0;
2567

    
2568
    vvfat_close_current_file(s);
2569

    
2570
    for (i = 0; !fail && i < s->commits.next; i++) {
2571
        commit_t* commit = array_get(&(s->commits), i);
2572
        switch(commit->action) {
2573
        case ACTION_RENAME: case ACTION_MKDIR:
2574
            abort();
2575
            fail = -2;
2576
            break;
2577
        case ACTION_WRITEOUT: {
2578
#ifndef NDEBUG
2579
            /* these variables are only used by assert() below */
2580
            direntry_t* entry = array_get(&(s->directory),
2581
                    commit->param.writeout.dir_index);
2582
            uint32_t begin = begin_of_direntry(entry);
2583
            mapping_t* mapping = find_mapping_for_cluster(s, begin);
2584
#endif
2585

    
2586
            assert(mapping);
2587
            assert(mapping->begin == begin);
2588
            assert(commit->path == NULL);
2589

    
2590
            if (commit_one_file(s, commit->param.writeout.dir_index,
2591
                        commit->param.writeout.modified_offset))
2592
                fail = -3;
2593

    
2594
            break;
2595
        }
2596
        case ACTION_NEW_FILE: {
2597
            int begin = commit->param.new_file.first_cluster;
2598
            mapping_t* mapping = find_mapping_for_cluster(s, begin);
2599
            direntry_t* entry;
2600
            int i;
2601

    
2602
            /* find direntry */
2603
            for (i = 0; i < s->directory.next; i++) {
2604
                entry = array_get(&(s->directory), i);
2605
                if (is_file(entry) && begin_of_direntry(entry) == begin)
2606
                    break;
2607
            }
2608

    
2609
            if (i >= s->directory.next) {
2610
                fail = -6;
2611
                continue;
2612
            }
2613

    
2614
            /* make sure there exists an initial mapping */
2615
            if (mapping && mapping->begin != begin) {
2616
                mapping->end = begin;
2617
                mapping = NULL;
2618
            }
2619
            if (mapping == NULL) {
2620
                mapping = insert_mapping(s, begin, begin+1);
2621
            }
2622
            /* most members will be fixed in commit_mappings() */
2623
            assert(commit->path);
2624
            mapping->path = commit->path;
2625
            mapping->read_only = 0;
2626
            mapping->mode = MODE_NORMAL;
2627
            mapping->info.file.offset = 0;
2628

    
2629
            if (commit_one_file(s, i, 0))
2630
                fail = -7;
2631

    
2632
            break;
2633
        }
2634
        default:
2635
            abort();
2636
        }
2637
    }
2638
    if (i > 0 && array_remove_slice(&(s->commits), 0, i))
2639
        return -1;
2640
    return fail;
2641
}
2642

    
2643
static int handle_deletes(BDRVVVFATState* s)
2644
{
2645
    int i, deferred = 1, deleted = 1;
2646

    
2647
    /* delete files corresponding to mappings marked as deleted */
2648
    /* handle DELETEs and unused mappings (modified_fat_get(s, mapping->begin) == 0) */
2649
    while (deferred && deleted) {
2650
        deferred = 0;
2651
        deleted = 0;
2652

    
2653
        for (i = 1; i < s->mapping.next; i++) {
2654
            mapping_t* mapping = array_get(&(s->mapping), i);
2655
            if (mapping->mode & MODE_DELETED) {
2656
                direntry_t* entry = array_get(&(s->directory),
2657
                        mapping->dir_index);
2658

    
2659
                if (is_free(entry)) {
2660
                    /* remove file/directory */
2661
                    if (mapping->mode & MODE_DIRECTORY) {
2662
                        int j, next_dir_index = s->directory.next,
2663
                        first_dir_index = mapping->info.dir.first_dir_index;
2664

    
2665
                        if (rmdir(mapping->path) < 0) {
2666
                            if (errno == ENOTEMPTY) {
2667
                                deferred++;
2668
                                continue;
2669
                            } else
2670
                                return -5;
2671
                        }
2672

    
2673
                        for (j = 1; j < s->mapping.next; j++) {
2674
                            mapping_t* m = array_get(&(s->mapping), j);
2675
                            if (m->mode & MODE_DIRECTORY &&
2676
                                    m->info.dir.first_dir_index >
2677
                                    first_dir_index &&
2678
                                    m->info.dir.first_dir_index <
2679
                                    next_dir_index)
2680
                                next_dir_index =
2681
                                    m->info.dir.first_dir_index;
2682
                        }
2683
                        remove_direntries(s, first_dir_index,
2684
                                next_dir_index - first_dir_index);
2685

    
2686
                        deleted++;
2687
                    }
2688
                } else {
2689
                    if (unlink(mapping->path))
2690
                        return -4;
2691
                    deleted++;
2692
                }
2693
                DLOG(fprintf(stderr, "DELETE (%d)\n", i); print_mapping(mapping); print_direntry(entry));
2694
                remove_mapping(s, i);
2695
            }
2696
        }
2697
    }
2698

    
2699
    return 0;
2700
}
2701

    
2702
/*
2703
 * synchronize mapping with new state:
2704
 *
2705
 * - copy FAT (with bdrv_read)
2706
 * - mark all filenames corresponding to mappings as deleted
2707
 * - recurse direntries from root (using bs->bdrv_read)
2708
 * - delete files corresponding to mappings marked as deleted
2709
 */
2710
static int do_commit(BDRVVVFATState* s)
2711
{
2712
    int ret = 0;
2713

    
2714
    /* the real meat are the commits. Nothing to do? Move along! */
2715
    if (s->commits.next == 0)
2716
        return 0;
2717

    
2718
    vvfat_close_current_file(s);
2719

    
2720
    ret = handle_renames_and_mkdirs(s);
2721
    if (ret) {
2722
        fprintf(stderr, "Error handling renames (%d)\n", ret);
2723
        abort();
2724
        return ret;
2725
    }
2726

    
2727
    /* copy FAT (with bdrv_read) */
2728
    memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
2729

    
2730
    /* recurse direntries from root (using bs->bdrv_read) */
2731
    ret = commit_direntries(s, 0, -1);
2732
    if (ret) {
2733
        fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
2734
        abort();
2735
        return ret;
2736
    }
2737

    
2738
    ret = handle_commits(s);
2739
    if (ret) {
2740
        fprintf(stderr, "Error handling commits (%d)\n", ret);
2741
        abort();
2742
        return ret;
2743
    }
2744

    
2745
    ret = handle_deletes(s);
2746
    if (ret) {
2747
        fprintf(stderr, "Error deleting\n");
2748
        abort();
2749
        return ret;
2750
    }
2751

    
2752
    if (s->qcow->drv->bdrv_make_empty) {
2753
        s->qcow->drv->bdrv_make_empty(s->qcow);
2754
    }
2755

    
2756
    memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
2757

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

    
2762
static int try_commit(BDRVVVFATState* s)
2763
{
2764
    vvfat_close_current_file(s);
2765
DLOG(checkpoint());
2766
    if(!is_consistent(s))
2767
        return -1;
2768
    return do_commit(s);
2769
}
2770

    
2771
static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
2772
                    const uint8_t *buf, int nb_sectors)
2773
{
2774
    BDRVVVFATState *s = bs->opaque;
2775
    int i, ret;
2776

    
2777
DLOG(checkpoint());
2778

    
2779
    /* Check if we're operating in read-only mode */
2780
    if (s->qcow == NULL) {
2781
        return -EACCES;
2782
    }
2783

    
2784
    vvfat_close_current_file(s);
2785

    
2786
    /*
2787
     * Some sanity checks:
2788
     * - do not allow writing to the boot sector
2789
     * - do not allow to write non-ASCII filenames
2790
     */
2791

    
2792
    if (sector_num < s->first_sectors_number)
2793
        return -1;
2794

    
2795
    for (i = sector2cluster(s, sector_num);
2796
            i <= sector2cluster(s, sector_num + nb_sectors - 1);) {
2797
        mapping_t* mapping = find_mapping_for_cluster(s, i);
2798
        if (mapping) {
2799
            if (mapping->read_only) {
2800
                fprintf(stderr, "Tried to write to write-protected file %s\n",
2801
                        mapping->path);
2802
                return -1;
2803
            }
2804

    
2805
            if (mapping->mode & MODE_DIRECTORY) {
2806
                int begin = cluster2sector(s, i);
2807
                int end = begin + s->sectors_per_cluster, k;
2808
                int dir_index;
2809
                const direntry_t* direntries;
2810
                long_file_name lfn;
2811

    
2812
                lfn_init(&lfn);
2813

    
2814
                if (begin < sector_num)
2815
                    begin = sector_num;
2816
                if (end > sector_num + nb_sectors)
2817
                    end = sector_num + nb_sectors;
2818
                dir_index  = mapping->dir_index +
2819
                    0x10 * (begin - mapping->begin * s->sectors_per_cluster);
2820
                direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
2821

    
2822
                for (k = 0; k < (end - begin) * 0x10; k++) {
2823
                    /* do not allow non-ASCII filenames */
2824
                    if (parse_long_name(&lfn, direntries + k) < 0) {
2825
                        fprintf(stderr, "Warning: non-ASCII filename\n");
2826
                        return -1;
2827
                    }
2828
                    /* no access to the direntry of a read-only file */
2829
                    else if (is_short_name(direntries+k) &&
2830
                            (direntries[k].attributes & 1)) {
2831
                        if (memcmp(direntries + k,
2832
                                    array_get(&(s->directory), dir_index + k),
2833
                                    sizeof(direntry_t))) {
2834
                            fprintf(stderr, "Warning: tried to write to write-protected file\n");
2835
                            return -1;
2836
                        }
2837
                    }
2838
                }
2839
            }
2840
            i = mapping->end;
2841
        } else
2842
            i++;
2843
    }
2844

    
2845
    /*
2846
     * Use qcow backend. Commit later.
2847
     */
2848
DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
2849
    ret = bdrv_write(s->qcow, sector_num, buf, nb_sectors);
2850
    if (ret < 0) {
2851
        fprintf(stderr, "Error writing to qcow backend\n");
2852
        return ret;
2853
    }
2854

    
2855
    for (i = sector2cluster(s, sector_num);
2856
            i <= sector2cluster(s, sector_num + nb_sectors - 1); i++)
2857
        if (i >= 0)
2858
            s->used_clusters[i] |= USED_ALLOCATED;
2859

    
2860
DLOG(checkpoint());
2861
    /* TODO: add timeout */
2862
    try_commit(s);
2863

    
2864
DLOG(checkpoint());
2865
    return 0;
2866
}
2867

    
2868
static coroutine_fn int vvfat_co_write(BlockDriverState *bs, int64_t sector_num,
2869
                                       const uint8_t *buf, int nb_sectors)
2870
{
2871
    int ret;
2872
    BDRVVVFATState *s = bs->opaque;
2873
    qemu_co_mutex_lock(&s->lock);
2874
    ret = vvfat_write(bs, sector_num, buf, nb_sectors);
2875
    qemu_co_mutex_unlock(&s->lock);
2876
    return ret;
2877
}
2878

    
2879
static int64_t coroutine_fn vvfat_co_get_block_status(BlockDriverState *bs,
2880
        int64_t sector_num, int nb_sectors, int* n)
2881
{
2882
    BDRVVVFATState* s = bs->opaque;
2883
    *n = s->sector_count - sector_num;
2884
    if (*n > nb_sectors) {
2885
        *n = nb_sectors;
2886
    } else if (*n < 0) {
2887
        return 0;
2888
    }
2889
    return BDRV_BLOCK_DATA;
2890
}
2891

    
2892
static int write_target_commit(BlockDriverState *bs, int64_t sector_num,
2893
        const uint8_t* buffer, int nb_sectors) {
2894
    BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
2895
    return try_commit(s);
2896
}
2897

    
2898
static void write_target_close(BlockDriverState *bs) {
2899
    BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
2900
    bdrv_unref(s->qcow);
2901
    g_free(s->qcow_filename);
2902
}
2903

    
2904
static BlockDriver vvfat_write_target = {
2905
    .format_name        = "vvfat_write_target",
2906
    .bdrv_write         = write_target_commit,
2907
    .bdrv_close         = write_target_close,
2908
};
2909

    
2910
static int enable_write_target(BDRVVVFATState *s)
2911
{
2912
    BlockDriver *bdrv_qcow;
2913
    QEMUOptionParameter *options;
2914
    Error *local_err = NULL;
2915
    int ret;
2916
    int size = sector2cluster(s, s->sector_count);
2917
    s->used_clusters = calloc(size, 1);
2918

    
2919
    array_init(&(s->commits), sizeof(commit_t));
2920

    
2921
    s->qcow_filename = g_malloc(1024);
2922
    ret = get_tmp_filename(s->qcow_filename, 1024);
2923
    if (ret < 0) {
2924
        goto err;
2925
    }
2926

    
2927
    bdrv_qcow = bdrv_find_format("qcow");
2928
    options = parse_option_parameters("", bdrv_qcow->create_options, NULL);
2929
    set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512);
2930
    set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:");
2931

    
2932
    ret = bdrv_create(bdrv_qcow, s->qcow_filename, options, &local_err);
2933
    if (ret < 0) {
2934
        qerror_report_err(local_err);
2935
        error_free(local_err);
2936
        goto err;
2937
    }
2938

    
2939
    s->qcow = NULL;
2940
    ret = bdrv_open(&s->qcow, s->qcow_filename, NULL,
2941
            BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, bdrv_qcow,
2942
            &local_err);
2943
    if (ret < 0) {
2944
        qerror_report_err(local_err);
2945
        error_free(local_err);
2946
        goto err;
2947
    }
2948

    
2949
#ifndef _WIN32
2950
    unlink(s->qcow_filename);
2951
#endif
2952

    
2953
    s->bs->backing_hd = bdrv_new("");
2954
    s->bs->backing_hd->drv = &vvfat_write_target;
2955
    s->bs->backing_hd->opaque = g_malloc(sizeof(void*));
2956
    *(void**)s->bs->backing_hd->opaque = s;
2957

    
2958
    return 0;
2959

    
2960
err:
2961
    g_free(s->qcow_filename);
2962
    s->qcow_filename = NULL;
2963
    return ret;
2964
}
2965

    
2966
static void vvfat_close(BlockDriverState *bs)
2967
{
2968
    BDRVVVFATState *s = bs->opaque;
2969

    
2970
    vvfat_close_current_file(s);
2971
    array_free(&(s->fat));
2972
    array_free(&(s->directory));
2973
    array_free(&(s->mapping));
2974
    g_free(s->cluster_buffer);
2975

    
2976
    if (s->qcow) {
2977
        migrate_del_blocker(s->migration_blocker);
2978
        error_free(s->migration_blocker);
2979
    }
2980
}
2981

    
2982
static BlockDriver bdrv_vvfat = {
2983
    .format_name            = "vvfat",
2984
    .protocol_name          = "fat",
2985
    .instance_size          = sizeof(BDRVVVFATState),
2986

    
2987
    .bdrv_parse_filename    = vvfat_parse_filename,
2988
    .bdrv_file_open         = vvfat_open,
2989
    .bdrv_close             = vvfat_close,
2990
    .bdrv_rebind            = vvfat_rebind,
2991

    
2992
    .bdrv_read              = vvfat_co_read,
2993
    .bdrv_write             = vvfat_co_write,
2994
    .bdrv_co_get_block_status = vvfat_co_get_block_status,
2995
};
2996

    
2997
static void bdrv_vvfat_init(void)
2998
{
2999
    bdrv_register(&bdrv_vvfat);
3000
}
3001

    
3002
block_init(bdrv_vvfat_init);
3003

    
3004
#ifdef DEBUG
3005
static void checkpoint(void) {
3006
    assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2);
3007
    check1(vvv);
3008
    check2(vvv);
3009
    assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY));
3010
#if 0
3011
    if (((direntry_t*)vvv->directory.pointer)[1].attributes != 0xf)
3012
        fprintf(stderr, "Nonono!\n");
3013
    mapping_t* mapping;
3014
    direntry_t* direntry;
3015
    assert(vvv->mapping.size >= vvv->mapping.item_size * vvv->mapping.next);
3016
    assert(vvv->directory.size >= vvv->directory.item_size * vvv->directory.next);
3017
    if (vvv->mapping.next<47)
3018
        return;
3019
    assert((mapping = array_get(&(vvv->mapping), 47)));
3020
    assert(mapping->dir_index < vvv->directory.next);
3021
    direntry = array_get(&(vvv->directory), mapping->dir_index);
3022
    assert(!memcmp(direntry->name, "USB     H  ", 11) || direntry->name[0]==0);
3023
#endif
3024
}
3025
#endif