Statistics
| Branch: | Revision:

root / block / vvfat.c @ cc84d90f

History | View | Annotate | Download (84.7 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];
270
    uint8_t extension[3];
271
    uint8_t attributes;
272
    uint8_t reserved[2];
273
    uint16_t ctime;
274
    uint16_t cdate;
275
    uint16_t adate;
276
    uint16_t begin_hi;
277
    uint16_t mtime;
278
    uint16_t mdate;
279
    uint16_t begin;
280
    uint32_t size;
281
} QEMU_PACKED direntry_t;
282

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

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

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

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

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

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

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

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

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

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

    
357
    Error *migration_blocker;
358
} BDRVVVFATState;
359

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

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

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

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

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

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

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

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

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

    
419
/* direntry functions */
420

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

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

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

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

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

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

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

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

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

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

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

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

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

    
514
/* fat functions */
515

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

    
521
    for(i=0;i<11;i++) {
522
        unsigned char c;
523

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

    
528
    return chksum;
529
}
530

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

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

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

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

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

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

    
607
}
608

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

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

    
625
    entry_long=create_long_filename(s,filename);
626

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

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

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

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

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

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

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

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

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

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

    
693
    return entry;
694
}
695

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
821
    return 0;
822
}
823

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
918
        assert(mapping->begin < mapping->end);
919

    
920
        /* next free cluster */
921
        cluster = mapping->end;
922

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

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

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

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

    
946
    s->current_mapping = NULL;
947

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

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

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

    
977
    return 0;
978
}
979

    
980
#ifdef DEBUG
981
static BDRVVVFATState *vvv = NULL;
982
#endif
983

    
984
static int enable_write_target(BDRVVVFATState *s);
985
static int is_consistent(BDRVVVFATState *s);
986

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

    
993
static QemuOptsList runtime_opts = {
994
    .name = "vvfat",
995
    .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
996
    .desc = {
997
        {
998
            .name = "dir",
999
            .type = QEMU_OPT_STRING,
1000
            .help = "Host directory to map to the vvfat device",
1001
        },
1002
        {
1003
            .name = "fat-type",
1004
            .type = QEMU_OPT_NUMBER,
1005
            .help = "FAT type (12, 16 or 32)",
1006
        },
1007
        {
1008
            .name = "floppy",
1009
            .type = QEMU_OPT_BOOL,
1010
            .help = "Create a floppy rather than a hard disk image",
1011
        },
1012
        {
1013
            .name = "rw",
1014
            .type = QEMU_OPT_BOOL,
1015
            .help = "Make the image writable",
1016
        },
1017
        { /* end of list */ }
1018
    },
1019
};
1020

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

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

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

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

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

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

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

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

    
1079
#ifdef DEBUG
1080
    vvv = s;
1081
#endif
1082

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

    
1088
    opts = qemu_opts_create_nofail(&runtime_opts);
1089
    qemu_opts_absorb_qdict(opts, options, &local_err);
1090
    if (error_is_set(&local_err)) {
1091
        qerror_report_err(local_err);
1092
        error_free(local_err);
1093
        ret = -EINVAL;
1094
        goto fail;
1095
    }
1096

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

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

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

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

    
1146

    
1147
    s->bs = bs;
1148

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

    
1152
    s->current_cluster=0xffffffff;
1153

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

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

    
1165
    s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1);
1166

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

    
1175
    bs->total_sectors = cyls * heads * secs;
1176

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

    
1182
    s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
1183

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

    
1188
    //    assert(is_consistent(s));
1189
    qemu_co_mutex_init(&s->lock);
1190

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

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

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

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

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

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

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

    
1289
            assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
1290

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

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

    
1309
        assert(s->current_fd);
1310

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

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

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

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

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

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

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

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

    
1427
/* LATER TODO: statify all functions */
1428

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

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

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

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

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

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

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

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

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

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

    
1539
    if (!is_long_name(direntry))
1540
        return 1;
1541

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

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

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

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

    
1572
    return 0;
1573
}
1574

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

    
1581
    if (!is_short_name(direntry))
1582
        return 1;
1583

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

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

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

    
1611
    return 0;
1612
}
1613

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

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

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

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

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

    
1648
    return was_modified;
1649
}
1650

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

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

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

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

    
1711
    vvfat_close_current_file(s);
1712

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

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

    
1721
        mapping = find_mapping_for_cluster(s, cluster_num);
1722

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

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

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

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

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

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

    
1753

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

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

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

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

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

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

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

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

    
1812
        cluster_num = modified_fat_get(s, cluster_num);
1813

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

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

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

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

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

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

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

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

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

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

    
1865
        ret++;
1866

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

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

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

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

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

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

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

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

    
1941
            ret += cluster_count;
1942
        }
1943

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

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

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

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

    
1986
    clear_commits(s);
1987

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

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

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

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

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

    
2023
    return used_clusters_count;
2024
}
2025

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

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

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

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

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

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

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

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

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

    
2083
    return mapping;
2084
}
2085

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

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

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

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

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

    
2106
    return 0;
2107
}
2108

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

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

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

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

    
2158
    vvfat_close_current_file(s);
2159

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

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

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

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

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

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

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

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

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

    
2219
            mapping = next_mapping;
2220
        }
2221

    
2222
        cluster = c1;
2223
    }
2224

    
2225
    return 0;
2226
}
2227

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

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

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

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

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

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

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

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

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

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

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

    
2303
    return 0;
2304
}
2305

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

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

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

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

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

    
2347
        c1 = modified_fat_get(s, c);
2348

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2567
    vvfat_close_current_file(s);
2568

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2698
    return 0;
2699
}
2700

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

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

    
2717
    vvfat_close_current_file(s);
2718

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

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

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

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

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

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

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

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

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

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

    
2776
DLOG(checkpoint());
2777

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

    
2783
    vvfat_close_current_file(s);
2784

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

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

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

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

    
2811
                lfn_init(&lfn);
2812

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2938
    s->qcow = bdrv_new("");
2939

    
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
        bdrv_unref(s->qcow);
2947
        goto err;
2948
    }
2949

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

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

    
2959
    return 0;
2960

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

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

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

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

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

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

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

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

    
3003
block_init(bdrv_vvfat_init);
3004

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