Statistics
| Branch: | Revision:

root / block / vvfat.c @ e24e49e6

History | View | Annotate | Download (81.1 kB)

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

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

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

    
47
/* #define DEBUG */
48

    
49
#ifdef DEBUG
50

    
51
#define DLOG(a) a
52

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

    
57
static void checkpoint(void);
58

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

    
68
#else
69

    
70
#define DLOG(a)
71

    
72
#endif
73

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

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

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

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

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

    
111
    return 0;
112
}
113

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

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

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

    
124
    return result;
125
}
126

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

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

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

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

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

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

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

    
172
    g_free(buf);
173

    
174
    return 0;
175
}
176

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
355
    Error *migration_blocker;
356
} BDRVVVFATState;
357

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

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

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

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

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

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

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

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

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

    
413
/* direntry functions */
414

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

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

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

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

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

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

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

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

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

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

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

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

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

    
508
/* fat functions */
509

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

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

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

    
522
    return chksum;
523
}
524

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

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

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

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

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

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

    
605
}
606

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

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

    
623
    entry_long=create_long_filename(s,filename);
624

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

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

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

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

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

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

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

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

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

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

    
691
    return entry;
692
}
693

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
819
    return 0;
820
}
821

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
944
    s->current_mapping = NULL;
945

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

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

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

    
975
    return 0;
976
}
977

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

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

    
985
static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
986
{
987
    BDRVVVFATState *s = bs->opaque;
988
    int i;
989

    
990
#ifdef DEBUG
991
    vvv = s;
992
#endif
993

    
994
DLOG(if (stderr == NULL) {
995
    stderr = fopen("vvfat.log", "a");
996
    setbuf(stderr, NULL);
997
})
998

    
999
    s->bs = bs;
1000

    
1001
    /* LATER TODO: if FAT32, adjust */
1002
    s->sectors_per_cluster=0x10;
1003

    
1004
    s->current_cluster=0xffffffff;
1005

    
1006
    s->first_sectors_number=0x40;
1007
    /* read only is the default for safety */
1008
    bs->read_only = 1;
1009
    s->qcow = s->write_target = NULL;
1010
    s->qcow_filename = NULL;
1011
    s->fat2 = NULL;
1012
    s->downcase_short_names = 1;
1013

    
1014
    if (!strstart(dirname, "fat:", NULL))
1015
        return -1;
1016

    
1017
    if (strstr(dirname, ":32:")) {
1018
        fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. You are welcome to do so!\n");
1019
        s->fat_type = 32;
1020
    } else if (strstr(dirname, ":16:")) {
1021
        s->fat_type = 16;
1022
    } else if (strstr(dirname, ":12:")) {
1023
        s->fat_type = 12;
1024
    }
1025

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

    
1047
    s->sector_count=bs->cyls*bs->heads*bs->secs-(s->first_sectors_number-1);
1048

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

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

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

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

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

    
1070
    if(s->first_sectors_number==0x40)
1071
        init_mbr(s);
1072
    else {
1073
        /* MS-DOS does not like to know about CHS (?). */
1074
        bs->heads = bs->cyls = bs->secs = 0;
1075
    }
1076

    
1077
    //    assert(is_consistent(s));
1078
    qemu_co_mutex_init(&s->lock);
1079

    
1080
    /* Disable migration when vvfat is used rw */
1081
    if (s->qcow) {
1082
        error_set(&s->migration_blocker,
1083
                  QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
1084
                  "vvfat (rw)", bs->device_name, "live migration");
1085
        migrate_add_blocker(s->migration_blocker);
1086
    }
1087

    
1088
    return 0;
1089
}
1090

    
1091
static inline void vvfat_close_current_file(BDRVVVFATState *s)
1092
{
1093
    if(s->current_mapping) {
1094
        s->current_mapping = NULL;
1095
        if (s->current_fd) {
1096
                close(s->current_fd);
1097
                s->current_fd = 0;
1098
        }
1099
    }
1100
    s->current_cluster = -1;
1101
}
1102

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

    
1133
static inline mapping_t* find_mapping_for_cluster(BDRVVVFATState* s,int cluster_num)
1134
{
1135
    int index=find_mapping_for_cluster_aux(s,cluster_num,0,s->mapping.next);
1136
    mapping_t* mapping;
1137
    if(index>=s->mapping.next)
1138
        return NULL;
1139
    mapping=array_get(&(s->mapping),index);
1140
    if(mapping->begin>cluster_num)
1141
        return NULL;
1142
    assert(mapping->begin<=cluster_num && mapping->end>cluster_num);
1143
    return mapping;
1144
}
1145

    
1146
static int open_file(BDRVVVFATState* s,mapping_t* mapping)
1147
{
1148
    if(!mapping)
1149
        return -1;
1150
    if(!s->current_mapping ||
1151
            strcmp(s->current_mapping->path,mapping->path)) {
1152
        /* open file */
1153
        int fd = open(mapping->path, O_RDONLY | O_BINARY | O_LARGEFILE);
1154
        if(fd<0)
1155
            return -1;
1156
        vvfat_close_current_file(s);
1157
        s->current_fd = fd;
1158
        s->current_mapping = mapping;
1159
    }
1160
    return 0;
1161
}
1162

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

    
1175
            assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
1176

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

    
1190
            if(open_file(s,mapping))
1191
                return -2;
1192
        } else if (s->current_mapping->mode & MODE_DIRECTORY)
1193
            goto read_cluster_directory;
1194

    
1195
        assert(s->current_fd);
1196

    
1197
        offset=s->cluster_size*(cluster_num-s->current_mapping->begin)+s->current_mapping->info.file.offset;
1198
        if(lseek(s->current_fd, offset, SEEK_SET)!=offset)
1199
            return -3;
1200
        s->cluster=s->cluster_buffer;
1201
        result=read(s->current_fd,s->cluster,s->cluster_size);
1202
        if(result<0) {
1203
            s->current_cluster = -1;
1204
            return -1;
1205
        }
1206
        s->current_cluster = cluster_num;
1207
    }
1208
    return 0;
1209
}
1210

    
1211
#ifdef DEBUG
1212
static void print_direntry(const direntry_t* direntry)
1213
{
1214
    int j = 0;
1215
    char buffer[1024];
1216

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

    
1244
static void print_mapping(const mapping_t* mapping)
1245
{
1246
    fprintf(stderr, "mapping (%p): begin, end = %d, %d, dir_index = %d, "
1247
        "first_mapping_index = %d, name = %s, mode = 0x%x, " ,
1248
        mapping, mapping->begin, mapping->end, mapping->dir_index,
1249
        mapping->first_mapping_index, mapping->path, mapping->mode);
1250

    
1251
    if (mapping->mode & MODE_DIRECTORY)
1252
        fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
1253
    else
1254
        fprintf(stderr, "offset = %d\n", mapping->info.file.offset);
1255
}
1256
#endif
1257

    
1258
static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
1259
                    uint8_t *buf, int nb_sectors)
1260
{
1261
    BDRVVVFATState *s = bs->opaque;
1262
    int i;
1263

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

    
1302
static coroutine_fn int vvfat_co_read(BlockDriverState *bs, int64_t sector_num,
1303
                                      uint8_t *buf, int nb_sectors)
1304
{
1305
    int ret;
1306
    BDRVVVFATState *s = bs->opaque;
1307
    qemu_co_mutex_lock(&s->lock);
1308
    ret = vvfat_read(bs, sector_num, buf, nb_sectors);
1309
    qemu_co_mutex_unlock(&s->lock);
1310
    return ret;
1311
}
1312

    
1313
/* LATER TODO: statify all functions */
1314

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

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

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

    
1365
static void schedule_rename(BDRVVVFATState* s,
1366
        uint32_t cluster, char* new_path)
1367
{
1368
    commit_t* commit = array_get_next(&(s->commits));
1369
    commit->path = new_path;
1370
    commit->param.rename.cluster = cluster;
1371
    commit->action = ACTION_RENAME;
1372
}
1373

    
1374
static void schedule_writeout(BDRVVVFATState* s,
1375
        int dir_index, uint32_t modified_offset)
1376
{
1377
    commit_t* commit = array_get_next(&(s->commits));
1378
    commit->path = NULL;
1379
    commit->param.writeout.dir_index = dir_index;
1380
    commit->param.writeout.modified_offset = modified_offset;
1381
    commit->action = ACTION_WRITEOUT;
1382
}
1383

    
1384
static void schedule_new_file(BDRVVVFATState* s,
1385
        char* path, uint32_t first_cluster)
1386
{
1387
    commit_t* commit = array_get_next(&(s->commits));
1388
    commit->path = path;
1389
    commit->param.new_file.first_cluster = first_cluster;
1390
    commit->action = ACTION_NEW_FILE;
1391
}
1392

    
1393
static void schedule_mkdir(BDRVVVFATState* s, uint32_t cluster, char* path)
1394
{
1395
    commit_t* commit = array_get_next(&(s->commits));
1396
    commit->path = path;
1397
    commit->param.mkdir.cluster = cluster;
1398
    commit->action = ACTION_MKDIR;
1399
}
1400

    
1401
typedef struct {
1402
    /*
1403
     * Since the sequence number is at most 0x3f, and the filename
1404
     * length is at most 13 times the sequence number, the maximal
1405
     * filename length is 0x3f * 13 bytes.
1406
     */
1407
    unsigned char name[0x3f * 13 + 1];
1408
    int checksum, len;
1409
    int sequence_number;
1410
} long_file_name;
1411

    
1412
static void lfn_init(long_file_name* lfn)
1413
{
1414
   lfn->sequence_number = lfn->len = 0;
1415
   lfn->checksum = 0x100;
1416
}
1417

    
1418
/* return 0 if parsed successfully, > 0 if no long name, < 0 if error */
1419
static int parse_long_name(long_file_name* lfn,
1420
        const direntry_t* direntry)
1421
{
1422
    int i, j, offset;
1423
    const unsigned char* pointer = (const unsigned char*)direntry;
1424

    
1425
    if (!is_long_name(direntry))
1426
        return 1;
1427

    
1428
    if (pointer[0] & 0x40) {
1429
        lfn->sequence_number = pointer[0] & 0x3f;
1430
        lfn->checksum = pointer[13];
1431
        lfn->name[0] = 0;
1432
        lfn->name[lfn->sequence_number * 13] = 0;
1433
    } else if ((pointer[0] & 0x3f) != --lfn->sequence_number)
1434
        return -1;
1435
    else if (pointer[13] != lfn->checksum)
1436
        return -2;
1437
    else if (pointer[12] || pointer[26] || pointer[27])
1438
        return -3;
1439

    
1440
    offset = 13 * (lfn->sequence_number - 1);
1441
    for (i = 0, j = 1; i < 13; i++, j+=2) {
1442
        if (j == 11)
1443
            j = 14;
1444
        else if (j == 26)
1445
            j = 28;
1446

    
1447
        if (pointer[j+1] == 0)
1448
            lfn->name[offset + i] = pointer[j];
1449
        else if (pointer[j+1] != 0xff || (pointer[0] & 0x40) == 0)
1450
            return -4;
1451
        else
1452
            lfn->name[offset + i] = 0;
1453
    }
1454

    
1455
    if (pointer[0] & 0x40)
1456
        lfn->len = offset + strlen((char*)lfn->name + offset);
1457

    
1458
    return 0;
1459
}
1460

    
1461
/* returns 0 if successful, >0 if no short_name, and <0 on error */
1462
static int parse_short_name(BDRVVVFATState* s,
1463
        long_file_name* lfn, direntry_t* direntry)
1464
{
1465
    int i, j;
1466

    
1467
    if (!is_short_name(direntry))
1468
        return 1;
1469

    
1470
    for (j = 7; j >= 0 && direntry->name[j] == ' '; j--);
1471
    for (i = 0; i <= j; i++) {
1472
        if (direntry->name[i] <= ' ' || direntry->name[i] > 0x7f)
1473
            return -1;
1474
        else if (s->downcase_short_names)
1475
            lfn->name[i] = qemu_tolower(direntry->name[i]);
1476
        else
1477
            lfn->name[i] = direntry->name[i];
1478
    }
1479

    
1480
    for (j = 2; j >= 0 && direntry->extension[j] == ' '; j--);
1481
    if (j >= 0) {
1482
        lfn->name[i++] = '.';
1483
        lfn->name[i + j + 1] = '\0';
1484
        for (;j >= 0; j--) {
1485
            if (direntry->extension[j] <= ' ' || direntry->extension[j] > 0x7f)
1486
                return -2;
1487
            else if (s->downcase_short_names)
1488
                lfn->name[i + j] = qemu_tolower(direntry->extension[j]);
1489
            else
1490
                lfn->name[i + j] = direntry->extension[j];
1491
        }
1492
    } else
1493
        lfn->name[i + j + 1] = '\0';
1494

    
1495
    lfn->len = strlen((char*)lfn->name);
1496

    
1497
    return 0;
1498
}
1499

    
1500
static inline uint32_t modified_fat_get(BDRVVVFATState* s,
1501
        unsigned int cluster)
1502
{
1503
    if (cluster < s->last_cluster_of_root_directory) {
1504
        if (cluster + 1 == s->last_cluster_of_root_directory)
1505
            return s->max_fat_value;
1506
        else
1507
            return cluster + 1;
1508
    }
1509

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

    
1522
static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num)
1523
{
1524
    int was_modified = 0;
1525
    int i, dummy;
1526

    
1527
    if (s->qcow == NULL)
1528
        return 0;
1529

    
1530
    for (i = 0; !was_modified && i < s->sectors_per_cluster; i++)
1531
        was_modified = bdrv_is_allocated(s->qcow,
1532
                cluster2sector(s, cluster_num) + i, 1, &dummy);
1533

    
1534
    return was_modified;
1535
}
1536

    
1537
static const char* get_basename(const char* path)
1538
{
1539
    char* basename = strrchr(path, '/');
1540
    if (basename == NULL)
1541
        return path;
1542
    else
1543
        return basename + 1; /* strip '/' */
1544
}
1545

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

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

    
1591
    uint32_t cluster_num = begin_of_direntry(direntry);
1592
    uint32_t offset = 0;
1593
    int first_mapping_index = -1;
1594
    mapping_t* mapping = NULL;
1595
    const char* basename2 = NULL;
1596

    
1597
    vvfat_close_current_file(s);
1598

    
1599
    /* the root directory */
1600
    if (cluster_num == 0)
1601
        return 0;
1602

    
1603
    /* write support */
1604
    if (s->qcow) {
1605
        basename2 = get_basename(path);
1606

    
1607
        mapping = find_mapping_for_cluster(s, cluster_num);
1608

    
1609
        if (mapping) {
1610
            const char* basename;
1611

    
1612
            assert(mapping->mode & MODE_DELETED);
1613
            mapping->mode &= ~MODE_DELETED;
1614

    
1615
            basename = get_basename(mapping->path);
1616

    
1617
            assert(mapping->mode & MODE_NORMAL);
1618

    
1619
            /* rename */
1620
            if (strcmp(basename, basename2))
1621
                schedule_rename(s, cluster_num, g_strdup(path));
1622
        } else if (is_file(direntry))
1623
            /* new file */
1624
            schedule_new_file(s, g_strdup(path), cluster_num);
1625
        else {
1626
            abort();
1627
            return 0;
1628
        }
1629
    }
1630

    
1631
    while(1) {
1632
        if (s->qcow) {
1633
            if (!copy_it && cluster_was_modified(s, cluster_num)) {
1634
                if (mapping == NULL ||
1635
                        mapping->begin > cluster_num ||
1636
                        mapping->end <= cluster_num)
1637
                mapping = find_mapping_for_cluster(s, cluster_num);
1638

    
1639

    
1640
                if (mapping &&
1641
                        (mapping->mode & MODE_DIRECTORY) == 0) {
1642

    
1643
                    /* was modified in qcow */
1644
                    if (offset != mapping->info.file.offset + s->cluster_size
1645
                            * (cluster_num - mapping->begin)) {
1646
                        /* offset of this cluster in file chain has changed */
1647
                        abort();
1648
                        copy_it = 1;
1649
                    } else if (offset == 0) {
1650
                        const char* basename = get_basename(mapping->path);
1651

    
1652
                        if (strcmp(basename, basename2))
1653
                            copy_it = 1;
1654
                        first_mapping_index = array_index(&(s->mapping), mapping);
1655
                    }
1656

    
1657
                    if (mapping->first_mapping_index != first_mapping_index
1658
                            && mapping->info.file.offset > 0) {
1659
                        abort();
1660
                        copy_it = 1;
1661
                    }
1662

    
1663
                    /* need to write out? */
1664
                    if (!was_modified && is_file(direntry)) {
1665
                        was_modified = 1;
1666
                        schedule_writeout(s, mapping->dir_index, offset);
1667
                    }
1668
                }
1669
            }
1670

    
1671
            if (copy_it) {
1672
                int i, dummy;
1673
                /*
1674
                 * This is horribly inefficient, but that is okay, since
1675
                 * it is rarely executed, if at all.
1676
                 */
1677
                int64_t offset = cluster2sector(s, cluster_num);
1678

    
1679
                vvfat_close_current_file(s);
1680
                for (i = 0; i < s->sectors_per_cluster; i++) {
1681
                    if (!bdrv_is_allocated(s->qcow, offset + i, 1, &dummy)) {
1682
                        if (vvfat_read(s->bs, offset, s->cluster_buffer, 1)) {
1683
                            return -1;
1684
                        }
1685
                        if (bdrv_write(s->qcow, offset, s->cluster_buffer, 1)) {
1686
                            return -2;
1687
                        }
1688
                    }
1689
                }
1690
            }
1691
        }
1692

    
1693
        ret++;
1694
        if (s->used_clusters[cluster_num] & USED_ANY)
1695
            return 0;
1696
        s->used_clusters[cluster_num] = USED_FILE;
1697

    
1698
        cluster_num = modified_fat_get(s, cluster_num);
1699

    
1700
        if (fat_eof(s, cluster_num))
1701
            return ret;
1702
        else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
1703
            return -1;
1704

    
1705
        offset += s->cluster_size;
1706
    }
1707
}
1708

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

    
1722
    long_file_name lfn;
1723
    int path_len = strlen(path);
1724
    char path2[PATH_MAX + 1];
1725

    
1726
    assert(path_len < PATH_MAX); /* len was tested before! */
1727
    pstrcpy(path2, sizeof(path2), path);
1728
    path2[path_len] = '/';
1729
    path2[path_len + 1] = '\0';
1730

    
1731
    if (mapping) {
1732
        const char* basename = get_basename(mapping->path);
1733
        const char* basename2 = get_basename(path);
1734

    
1735
        assert(mapping->mode & MODE_DIRECTORY);
1736

    
1737
        assert(mapping->mode & MODE_DELETED);
1738
        mapping->mode &= ~MODE_DELETED;
1739

    
1740
        if (strcmp(basename, basename2))
1741
            schedule_rename(s, cluster_num, g_strdup(path));
1742
    } else
1743
        /* new directory */
1744
        schedule_mkdir(s, cluster_num, g_strdup(path));
1745

    
1746
    lfn_init(&lfn);
1747
    do {
1748
        int i;
1749
        int subret = 0;
1750

    
1751
        ret++;
1752

    
1753
        if (s->used_clusters[cluster_num] & USED_ANY) {
1754
            fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
1755
            return 0;
1756
        }
1757
        s->used_clusters[cluster_num] = USED_DIRECTORY;
1758

    
1759
DLOG(fprintf(stderr, "read cluster %d (sector %d)\n", (int)cluster_num, (int)cluster2sector(s, cluster_num)));
1760
        subret = vvfat_read(s->bs, cluster2sector(s, cluster_num), cluster,
1761
                s->sectors_per_cluster);
1762
        if (subret) {
1763
            fprintf(stderr, "Error fetching direntries\n");
1764
        fail:
1765
            g_free(cluster);
1766
            return 0;
1767
        }
1768

    
1769
        for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
1770
            int cluster_count = 0;
1771

    
1772
DLOG(fprintf(stderr, "check direntry %d:\n", i); print_direntry(direntries + i));
1773
            if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
1774
                    is_free(direntries + i))
1775
                continue;
1776

    
1777
            subret = parse_long_name(&lfn, direntries + i);
1778
            if (subret < 0) {
1779
                fprintf(stderr, "Error in long name\n");
1780
                goto fail;
1781
            }
1782
            if (subret == 0 || is_free(direntries + i))
1783
                continue;
1784

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

    
1797
            if (path_len + 1 + lfn.len >= PATH_MAX) {
1798
                fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
1799
                goto fail;
1800
            }
1801
            pstrcpy(path2 + path_len + 1, sizeof(path2) - path_len - 1,
1802
                    (char*)lfn.name);
1803

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

    
1827
            ret += cluster_count;
1828
        }
1829

    
1830
        cluster_num = modified_fat_get(s, cluster_num);
1831
    } while(!fat_eof(s, cluster_num));
1832

    
1833
    g_free(cluster);
1834
    return ret;
1835
}
1836

    
1837
/* returns 1 on success */
1838
static int is_consistent(BDRVVVFATState* s)
1839
{
1840
    int i, check;
1841
    int used_clusters_count = 0;
1842

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

    
1872
    clear_commits(s);
1873

    
1874
    /* mark every mapped file/directory as deleted.
1875
     * (check_directory_consistency() will unmark those still present). */
1876
    if (s->qcow)
1877
        for (i = 0; i < s->mapping.next; i++) {
1878
            mapping_t* mapping = array_get(&(s->mapping), i);
1879
            if (mapping->first_mapping_index < 0)
1880
                mapping->mode |= MODE_DELETED;
1881
        }
1882

    
1883
    used_clusters_count = check_directory_consistency(s, 0, s->path);
1884
    if (used_clusters_count <= 0) {
1885
        DLOG(fprintf(stderr, "problem in directory\n"));
1886
        return 0;
1887
    }
1888

    
1889
    check = s->last_cluster_of_root_directory;
1890
    for (i = check; i < sector2cluster(s, s->sector_count); i++) {
1891
        if (modified_fat_get(s, i)) {
1892
            if(!s->used_clusters[i]) {
1893
                DLOG(fprintf(stderr, "FAT was modified (%d), but cluster is not used?\n", i));
1894
                return 0;
1895
            }
1896
            check++;
1897
        }
1898

    
1899
        if (s->used_clusters[i] == USED_ALLOCATED) {
1900
            /* allocated, but not used... */
1901
            DLOG(fprintf(stderr, "unused, modified cluster: %d\n", i));
1902
            return 0;
1903
        }
1904
    }
1905

    
1906
    if (check != used_clusters_count)
1907
        return 0;
1908

    
1909
    return used_clusters_count;
1910
}
1911

    
1912
static inline void adjust_mapping_indices(BDRVVVFATState* s,
1913
        int offset, int adjust)
1914
{
1915
    int i;
1916

    
1917
    for (i = 0; i < s->mapping.next; i++) {
1918
        mapping_t* mapping = array_get(&(s->mapping), i);
1919

    
1920
#define ADJUST_MAPPING_INDEX(name) \
1921
        if (mapping->name >= offset) \
1922
            mapping->name += adjust
1923

    
1924
        ADJUST_MAPPING_INDEX(first_mapping_index);
1925
        if (mapping->mode & MODE_DIRECTORY)
1926
            ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
1927
    }
1928
}
1929

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

    
1945
    if (index < s->mapping.next && (mapping = array_get(&(s->mapping), index))
1946
            && mapping->begin < begin) {
1947
        mapping->end = begin;
1948
        index++;
1949
        mapping = array_get(&(s->mapping), index);
1950
    }
1951
    if (index >= s->mapping.next || mapping->begin > begin) {
1952
        mapping = array_insert(&(s->mapping), index, 1);
1953
        mapping->path = NULL;
1954
        adjust_mapping_indices(s, index, +1);
1955
    }
1956

    
1957
    mapping->begin = begin;
1958
    mapping->end = end;
1959

    
1960
DLOG(mapping_t* next_mapping;
1961
assert(index + 1 >= s->mapping.next ||
1962
((next_mapping = array_get(&(s->mapping), index + 1)) &&
1963
 next_mapping->begin >= end)));
1964

    
1965
    if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1966
        s->current_mapping = array_get(&(s->mapping),
1967
                s->current_mapping - first_mapping);
1968

    
1969
    return mapping;
1970
}
1971

    
1972
static int remove_mapping(BDRVVVFATState* s, int mapping_index)
1973
{
1974
    mapping_t* mapping = array_get(&(s->mapping), mapping_index);
1975
    mapping_t* first_mapping = array_get(&(s->mapping), 0);
1976

    
1977
    /* free mapping */
1978
    if (mapping->first_mapping_index < 0) {
1979
        g_free(mapping->path);
1980
    }
1981

    
1982
    /* remove from s->mapping */
1983
    array_remove(&(s->mapping), mapping_index);
1984

    
1985
    /* adjust all references to mappings */
1986
    adjust_mapping_indices(s, mapping_index, -1);
1987

    
1988
    if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1989
        s->current_mapping = array_get(&(s->mapping),
1990
                s->current_mapping - first_mapping);
1991

    
1992
    return 0;
1993
}
1994

    
1995
static void adjust_dirindices(BDRVVVFATState* s, int offset, int adjust)
1996
{
1997
    int i;
1998
    for (i = 0; i < s->mapping.next; i++) {
1999
        mapping_t* mapping = array_get(&(s->mapping), i);
2000
        if (mapping->dir_index >= offset)
2001
            mapping->dir_index += adjust;
2002
        if ((mapping->mode & MODE_DIRECTORY) &&
2003
                mapping->info.dir.first_dir_index >= offset)
2004
            mapping->info.dir.first_dir_index += adjust;
2005
    }
2006
}
2007

    
2008
static direntry_t* insert_direntries(BDRVVVFATState* s,
2009
        int dir_index, int count)
2010
{
2011
    /*
2012
     * make room in s->directory,
2013
     * adjust_dirindices
2014
     */
2015
    direntry_t* result = array_insert(&(s->directory), dir_index, count);
2016
    if (result == NULL)
2017
        return NULL;
2018
    adjust_dirindices(s, dir_index, count);
2019
    return result;
2020
}
2021

    
2022
static int remove_direntries(BDRVVVFATState* s, int dir_index, int count)
2023
{
2024
    int ret = array_remove_slice(&(s->directory), dir_index, count);
2025
    if (ret)
2026
        return ret;
2027
    adjust_dirindices(s, dir_index, -count);
2028
    return 0;
2029
}
2030

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

    
2044
    vvfat_close_current_file(s);
2045

    
2046
    assert(mapping);
2047
    assert(mapping->begin == first_cluster);
2048
    mapping->first_mapping_index = -1;
2049
    mapping->dir_index = dir_index;
2050
    mapping->mode = (dir_index <= 0 || is_directory(direntry)) ?
2051
        MODE_DIRECTORY : MODE_NORMAL;
2052

    
2053
    while (!fat_eof(s, cluster)) {
2054
        uint32_t c, c1;
2055

    
2056
        for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
2057
                c = c1, c1 = modified_fat_get(s, c1));
2058

    
2059
        c++;
2060
        if (c > mapping->end) {
2061
            int index = array_index(&(s->mapping), mapping);
2062
            int i, max_i = s->mapping.next - index;
2063
            for (i = 1; i < max_i && mapping[i].begin < c; i++);
2064
            while (--i > 0)
2065
                remove_mapping(s, index + 1);
2066
        }
2067
        assert(mapping == array_get(&(s->mapping), s->mapping.next - 1)
2068
                || mapping[1].begin >= c);
2069
        mapping->end = c;
2070

    
2071
        if (!fat_eof(s, c1)) {
2072
            int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next);
2073
            mapping_t* next_mapping = i >= s->mapping.next ? NULL :
2074
                array_get(&(s->mapping), i);
2075

    
2076
            if (next_mapping == NULL || next_mapping->begin > c1) {
2077
                int i1 = array_index(&(s->mapping), mapping);
2078

    
2079
                next_mapping = insert_mapping(s, c1, c1+1);
2080

    
2081
                if (c1 < c)
2082
                    i1++;
2083
                mapping = array_get(&(s->mapping), i1);
2084
            }
2085

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

    
2105
            mapping = next_mapping;
2106
        }
2107

    
2108
        cluster = c1;
2109
    }
2110

    
2111
    return 0;
2112
}
2113

    
2114
static int commit_direntries(BDRVVVFATState* s,
2115
        int dir_index, int parent_mapping_index)
2116
{
2117
    direntry_t* direntry = array_get(&(s->directory), dir_index);
2118
    uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
2119
    mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2120

    
2121
    int factor = 0x10 * s->sectors_per_cluster;
2122
    int old_cluster_count, new_cluster_count;
2123
    int current_dir_index = mapping->info.dir.first_dir_index;
2124
    int first_dir_index = current_dir_index;
2125
    int ret, i;
2126
    uint32_t c;
2127

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

    
2130
    assert(direntry);
2131
    assert(mapping);
2132
    assert(mapping->begin == first_cluster);
2133
    assert(mapping->info.dir.first_dir_index < s->directory.next);
2134
    assert(mapping->mode & MODE_DIRECTORY);
2135
    assert(dir_index == 0 || is_directory(direntry));
2136

    
2137
    mapping->info.dir.parent_mapping_index = parent_mapping_index;
2138

    
2139
    if (first_cluster == 0) {
2140
        old_cluster_count = new_cluster_count =
2141
            s->last_cluster_of_root_directory;
2142
    } else {
2143
        for (old_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2144
                c = fat_get(s, c))
2145
            old_cluster_count++;
2146

    
2147
        for (new_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2148
                c = modified_fat_get(s, c))
2149
            new_cluster_count++;
2150
    }
2151

    
2152
    if (new_cluster_count > old_cluster_count) {
2153
        if (insert_direntries(s,
2154
                current_dir_index + factor * old_cluster_count,
2155
                factor * (new_cluster_count - old_cluster_count)) == NULL)
2156
            return -1;
2157
    } else if (new_cluster_count < old_cluster_count)
2158
        remove_direntries(s,
2159
                current_dir_index + factor * new_cluster_count,
2160
                factor * (old_cluster_count - new_cluster_count));
2161

    
2162
    for (c = first_cluster; !fat_eof(s, c); c = modified_fat_get(s, c)) {
2163
        void* direntry = array_get(&(s->directory), current_dir_index);
2164
        int ret = vvfat_read(s->bs, cluster2sector(s, c), direntry,
2165
                s->sectors_per_cluster);
2166
        if (ret)
2167
            return ret;
2168
        assert(!strncmp(s->directory.pointer, "QEMU", 4));
2169
        current_dir_index += factor;
2170
    }
2171

    
2172
    ret = commit_mappings(s, first_cluster, dir_index);
2173
    if (ret)
2174
        return ret;
2175

    
2176
    /* recurse */
2177
    for (i = 0; i < factor * new_cluster_count; i++) {
2178
        direntry = array_get(&(s->directory), first_dir_index + i);
2179
        if (is_directory(direntry) && !is_dot(direntry)) {
2180
            mapping = find_mapping_for_cluster(s, first_cluster);
2181
            assert(mapping->mode & MODE_DIRECTORY);
2182
            ret = commit_direntries(s, first_dir_index + i,
2183
                array_index(&(s->mapping), mapping));
2184
            if (ret)
2185
                return ret;
2186
        }
2187
    }
2188

    
2189
    return 0;
2190
}
2191

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

    
2206
    assert(offset < size);
2207
    assert((offset % s->cluster_size) == 0);
2208

    
2209
    for (i = s->cluster_size; i < offset; i += s->cluster_size)
2210
        c = modified_fat_get(s, c);
2211

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

    
2227
    while (offset < size) {
2228
        uint32_t c1;
2229
        int rest_size = (size - offset > s->cluster_size ?
2230
                s->cluster_size : size - offset);
2231
        int ret;
2232

    
2233
        c1 = modified_fat_get(s, c);
2234

    
2235
        assert((size - offset == 0 && fat_eof(s, c)) ||
2236
                (size > offset && c >=2 && !fat_eof(s, c)));
2237

    
2238
        ret = vvfat_read(s->bs, cluster2sector(s, c),
2239
            (uint8_t*)cluster, (rest_size + 0x1ff) / 0x200);
2240

    
2241
        if (ret < 0) {
2242
            close(fd);
2243
            g_free(cluster);
2244
            return ret;
2245
        }
2246

    
2247
        if (write(fd, cluster, rest_size) < 0) {
2248
            close(fd);
2249
            g_free(cluster);
2250
            return -2;
2251
        }
2252

    
2253
        offset += rest_size;
2254
        c = c1;
2255
    }
2256

    
2257
    if (ftruncate(fd, size)) {
2258
        perror("ftruncate()");
2259
        close(fd);
2260
        g_free(cluster);
2261
        return -4;
2262
    }
2263
    close(fd);
2264
    g_free(cluster);
2265

    
2266
    return commit_mappings(s, first_cluster, dir_index);
2267
}
2268

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

    
2290
/* test, if all direntries have mappings */
2291
static void check2(BDRVVVFATState* s)
2292
{
2293
    int i;
2294
    int first_mapping = -1;
2295

    
2296
    for (i = 0; i < s->directory.next; i++) {
2297
        direntry_t* direntry = array_get(&(s->directory), i);
2298

    
2299
        if (is_short_name(direntry) && begin_of_direntry(direntry)) {
2300
            mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
2301
            assert(mapping);
2302
            assert(mapping->dir_index == i || is_dot(direntry));
2303
            assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry));
2304
        }
2305

    
2306
        if ((i % (0x10 * s->sectors_per_cluster)) == 0) {
2307
            /* cluster start */
2308
            int j, count = 0;
2309

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

    
2338
static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2339
{
2340
    int i;
2341

    
2342
#ifdef DEBUG
2343
    fprintf(stderr, "handle_renames\n");
2344
    for (i = 0; i < s->commits.next; i++) {
2345
        commit_t* commit = array_get(&(s->commits), i);
2346
        fprintf(stderr, "%d, %s (%d, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action);
2347
    }
2348
#endif
2349

    
2350
    for (i = 0; i < s->commits.next;) {
2351
        commit_t* commit = array_get(&(s->commits), i);
2352
        if (commit->action == ACTION_RENAME) {
2353
            mapping_t* mapping = find_mapping_for_cluster(s,
2354
                    commit->param.rename.cluster);
2355
            char* old_path = mapping->path;
2356

    
2357
            assert(commit->path);
2358
            mapping->path = commit->path;
2359
            if (rename(old_path, mapping->path))
2360
                return -2;
2361

    
2362
            if (mapping->mode & MODE_DIRECTORY) {
2363
                int l1 = strlen(mapping->path);
2364
                int l2 = strlen(old_path);
2365
                int diff = l1 - l2;
2366
                direntry_t* direntry = array_get(&(s->directory),
2367
                        mapping->info.dir.first_dir_index);
2368
                uint32_t c = mapping->begin;
2369
                int i = 0;
2370

    
2371
                /* recurse */
2372
                while (!fat_eof(s, c)) {
2373
                    do {
2374
                        direntry_t* d = direntry + i;
2375

    
2376
                        if (is_file(d) || (is_directory(d) && !is_dot(d))) {
2377
                            mapping_t* m = find_mapping_for_cluster(s,
2378
                                    begin_of_direntry(d));
2379
                            int l = strlen(m->path);
2380
                            char* new_path = g_malloc(l + diff + 1);
2381

    
2382
                            assert(!strncmp(m->path, mapping->path, l2));
2383

    
2384
                            pstrcpy(new_path, l + diff + 1, mapping->path);
2385
                            pstrcpy(new_path + l1, l + diff + 1 - l1,
2386
                                    m->path + l2);
2387

    
2388
                            schedule_rename(s, m->begin, new_path);
2389
                        }
2390
                        i++;
2391
                    } while((i % (0x10 * s->sectors_per_cluster)) != 0);
2392
                    c = fat_get(s, c);
2393
                }
2394
            }
2395

    
2396
            g_free(old_path);
2397
            array_remove(&(s->commits), i);
2398
            continue;
2399
        } else if (commit->action == ACTION_MKDIR) {
2400
            mapping_t* mapping;
2401
            int j, parent_path_len;
2402

    
2403
#ifdef __MINGW32__
2404
            if (mkdir(commit->path))
2405
                return -5;
2406
#else
2407
            if (mkdir(commit->path, 0755))
2408
                return -5;
2409
#endif
2410

    
2411
            mapping = insert_mapping(s, commit->param.mkdir.cluster,
2412
                    commit->param.mkdir.cluster + 1);
2413
            if (mapping == NULL)
2414
                return -6;
2415

    
2416
            mapping->mode = MODE_DIRECTORY;
2417
            mapping->read_only = 0;
2418
            mapping->path = commit->path;
2419
            j = s->directory.next;
2420
            assert(j);
2421
            insert_direntries(s, s->directory.next,
2422
                    0x10 * s->sectors_per_cluster);
2423
            mapping->info.dir.first_dir_index = j;
2424

    
2425
            parent_path_len = strlen(commit->path)
2426
                - strlen(get_basename(commit->path)) - 1;
2427
            for (j = 0; j < s->mapping.next; j++) {
2428
                mapping_t* m = array_get(&(s->mapping), j);
2429
                if (m->first_mapping_index < 0 && m != mapping &&
2430
                        !strncmp(m->path, mapping->path, parent_path_len) &&
2431
                        strlen(m->path) == parent_path_len)
2432
                    break;
2433
            }
2434
            assert(j < s->mapping.next);
2435
            mapping->info.dir.parent_mapping_index = j;
2436

    
2437
            array_remove(&(s->commits), i);
2438
            continue;
2439
        }
2440

    
2441
        i++;
2442
    }
2443
    return 0;
2444
}
2445

    
2446
/*
2447
 * TODO: make sure that the short name is not matching *another* file
2448
 */
2449
static int handle_commits(BDRVVVFATState* s)
2450
{
2451
    int i, fail = 0;
2452

    
2453
    vvfat_close_current_file(s);
2454

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

    
2471
            assert(mapping);
2472
            assert(mapping->begin == begin);
2473
            assert(commit->path == NULL);
2474

    
2475
            if (commit_one_file(s, commit->param.writeout.dir_index,
2476
                        commit->param.writeout.modified_offset))
2477
                fail = -3;
2478

    
2479
            break;
2480
        }
2481
        case ACTION_NEW_FILE: {
2482
            int begin = commit->param.new_file.first_cluster;
2483
            mapping_t* mapping = find_mapping_for_cluster(s, begin);
2484
            direntry_t* entry;
2485
            int i;
2486

    
2487
            /* find direntry */
2488
            for (i = 0; i < s->directory.next; i++) {
2489
                entry = array_get(&(s->directory), i);
2490
                if (is_file(entry) && begin_of_direntry(entry) == begin)
2491
                    break;
2492
            }
2493

    
2494
            if (i >= s->directory.next) {
2495
                fail = -6;
2496
                continue;
2497
            }
2498

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

    
2514
            if (commit_one_file(s, i, 0))
2515
                fail = -7;
2516

    
2517
            break;
2518
        }
2519
        default:
2520
            abort();
2521
        }
2522
    }
2523
    if (i > 0 && array_remove_slice(&(s->commits), 0, i))
2524
        return -1;
2525
    return fail;
2526
}
2527

    
2528
static int handle_deletes(BDRVVVFATState* s)
2529
{
2530
    int i, deferred = 1, deleted = 1;
2531

    
2532
    /* delete files corresponding to mappings marked as deleted */
2533
    /* handle DELETEs and unused mappings (modified_fat_get(s, mapping->begin) == 0) */
2534
    while (deferred && deleted) {
2535
        deferred = 0;
2536
        deleted = 0;
2537

    
2538
        for (i = 1; i < s->mapping.next; i++) {
2539
            mapping_t* mapping = array_get(&(s->mapping), i);
2540
            if (mapping->mode & MODE_DELETED) {
2541
                direntry_t* entry = array_get(&(s->directory),
2542
                        mapping->dir_index);
2543

    
2544
                if (is_free(entry)) {
2545
                    /* remove file/directory */
2546
                    if (mapping->mode & MODE_DIRECTORY) {
2547
                        int j, next_dir_index = s->directory.next,
2548
                        first_dir_index = mapping->info.dir.first_dir_index;
2549

    
2550
                        if (rmdir(mapping->path) < 0) {
2551
                            if (errno == ENOTEMPTY) {
2552
                                deferred++;
2553
                                continue;
2554
                            } else
2555
                                return -5;
2556
                        }
2557

    
2558
                        for (j = 1; j < s->mapping.next; j++) {
2559
                            mapping_t* m = array_get(&(s->mapping), j);
2560
                            if (m->mode & MODE_DIRECTORY &&
2561
                                    m->info.dir.first_dir_index >
2562
                                    first_dir_index &&
2563
                                    m->info.dir.first_dir_index <
2564
                                    next_dir_index)
2565
                                next_dir_index =
2566
                                    m->info.dir.first_dir_index;
2567
                        }
2568
                        remove_direntries(s, first_dir_index,
2569
                                next_dir_index - first_dir_index);
2570

    
2571
                        deleted++;
2572
                    }
2573
                } else {
2574
                    if (unlink(mapping->path))
2575
                        return -4;
2576
                    deleted++;
2577
                }
2578
                DLOG(fprintf(stderr, "DELETE (%d)\n", i); print_mapping(mapping); print_direntry(entry));
2579
                remove_mapping(s, i);
2580
            }
2581
        }
2582
    }
2583

    
2584
    return 0;
2585
}
2586

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

    
2599
    /* the real meat are the commits. Nothing to do? Move along! */
2600
    if (s->commits.next == 0)
2601
        return 0;
2602

    
2603
    vvfat_close_current_file(s);
2604

    
2605
    ret = handle_renames_and_mkdirs(s);
2606
    if (ret) {
2607
        fprintf(stderr, "Error handling renames (%d)\n", ret);
2608
        abort();
2609
        return ret;
2610
    }
2611

    
2612
    /* copy FAT (with bdrv_read) */
2613
    memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
2614

    
2615
    /* recurse direntries from root (using bs->bdrv_read) */
2616
    ret = commit_direntries(s, 0, -1);
2617
    if (ret) {
2618
        fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
2619
        abort();
2620
        return ret;
2621
    }
2622

    
2623
    ret = handle_commits(s);
2624
    if (ret) {
2625
        fprintf(stderr, "Error handling commits (%d)\n", ret);
2626
        abort();
2627
        return ret;
2628
    }
2629

    
2630
    ret = handle_deletes(s);
2631
    if (ret) {
2632
        fprintf(stderr, "Error deleting\n");
2633
        abort();
2634
        return ret;
2635
    }
2636

    
2637
    if (s->qcow->drv->bdrv_make_empty) {
2638
        s->qcow->drv->bdrv_make_empty(s->qcow);
2639
    }
2640

    
2641
    memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
2642

    
2643
DLOG(checkpoint());
2644
    return 0;
2645
}
2646

    
2647
static int try_commit(BDRVVVFATState* s)
2648
{
2649
    vvfat_close_current_file(s);
2650
DLOG(checkpoint());
2651
    if(!is_consistent(s))
2652
        return -1;
2653
    return do_commit(s);
2654
}
2655

    
2656
static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
2657
                    const uint8_t *buf, int nb_sectors)
2658
{
2659
    BDRVVVFATState *s = bs->opaque;
2660
    int i, ret;
2661

    
2662
DLOG(checkpoint());
2663

    
2664
    /* Check if we're operating in read-only mode */
2665
    if (s->qcow == NULL) {
2666
        return -EACCES;
2667
    }
2668

    
2669
    vvfat_close_current_file(s);
2670

    
2671
    /*
2672
     * Some sanity checks:
2673
     * - do not allow writing to the boot sector
2674
     * - do not allow to write non-ASCII filenames
2675
     */
2676

    
2677
    if (sector_num < s->first_sectors_number)
2678
        return -1;
2679

    
2680
    for (i = sector2cluster(s, sector_num);
2681
            i <= sector2cluster(s, sector_num + nb_sectors - 1);) {
2682
        mapping_t* mapping = find_mapping_for_cluster(s, i);
2683
        if (mapping) {
2684
            if (mapping->read_only) {
2685
                fprintf(stderr, "Tried to write to write-protected file %s\n",
2686
                        mapping->path);
2687
                return -1;
2688
            }
2689

    
2690
            if (mapping->mode & MODE_DIRECTORY) {
2691
                int begin = cluster2sector(s, i);
2692
                int end = begin + s->sectors_per_cluster, k;
2693
                int dir_index;
2694
                const direntry_t* direntries;
2695
                long_file_name lfn;
2696

    
2697
                lfn_init(&lfn);
2698

    
2699
                if (begin < sector_num)
2700
                    begin = sector_num;
2701
                if (end > sector_num + nb_sectors)
2702
                    end = sector_num + nb_sectors;
2703
                dir_index  = mapping->dir_index +
2704
                    0x10 * (begin - mapping->begin * s->sectors_per_cluster);
2705
                direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
2706

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

    
2730
    /*
2731
     * Use qcow backend. Commit later.
2732
     */
2733
DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
2734
    ret = bdrv_write(s->qcow, sector_num, buf, nb_sectors);
2735
    if (ret < 0) {
2736
        fprintf(stderr, "Error writing to qcow backend\n");
2737
        return ret;
2738
    }
2739

    
2740
    for (i = sector2cluster(s, sector_num);
2741
            i <= sector2cluster(s, sector_num + nb_sectors - 1); i++)
2742
        if (i >= 0)
2743
            s->used_clusters[i] |= USED_ALLOCATED;
2744

    
2745
DLOG(checkpoint());
2746
    /* TODO: add timeout */
2747
    try_commit(s);
2748

    
2749
DLOG(checkpoint());
2750
    return 0;
2751
}
2752

    
2753
static coroutine_fn int vvfat_co_write(BlockDriverState *bs, int64_t sector_num,
2754
                                       const uint8_t *buf, int nb_sectors)
2755
{
2756
    int ret;
2757
    BDRVVVFATState *s = bs->opaque;
2758
    qemu_co_mutex_lock(&s->lock);
2759
    ret = vvfat_write(bs, sector_num, buf, nb_sectors);
2760
    qemu_co_mutex_unlock(&s->lock);
2761
    return ret;
2762
}
2763

    
2764
static int coroutine_fn vvfat_co_is_allocated(BlockDriverState *bs,
2765
        int64_t sector_num, int nb_sectors, int* n)
2766
{
2767
    BDRVVVFATState* s = bs->opaque;
2768
    *n = s->sector_count - sector_num;
2769
    if (*n > nb_sectors)
2770
        *n = nb_sectors;
2771
    else if (*n < 0)
2772
        return 0;
2773
    return 1;
2774
}
2775

    
2776
static int write_target_commit(BlockDriverState *bs, int64_t sector_num,
2777
        const uint8_t* buffer, int nb_sectors) {
2778
    BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
2779
    return try_commit(s);
2780
}
2781

    
2782
static void write_target_close(BlockDriverState *bs) {
2783
    BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
2784
    bdrv_delete(s->qcow);
2785
    g_free(s->qcow_filename);
2786
}
2787

    
2788
static BlockDriver vvfat_write_target = {
2789
    .format_name        = "vvfat_write_target",
2790
    .bdrv_write         = write_target_commit,
2791
    .bdrv_close         = write_target_close,
2792
};
2793

    
2794
static int enable_write_target(BDRVVVFATState *s)
2795
{
2796
    BlockDriver *bdrv_qcow;
2797
    QEMUOptionParameter *options;
2798
    int ret;
2799
    int size = sector2cluster(s, s->sector_count);
2800
    s->used_clusters = calloc(size, 1);
2801

    
2802
    array_init(&(s->commits), sizeof(commit_t));
2803

    
2804
    s->qcow_filename = g_malloc(1024);
2805
    get_tmp_filename(s->qcow_filename, 1024);
2806

    
2807
    bdrv_qcow = bdrv_find_format("qcow");
2808
    options = parse_option_parameters("", bdrv_qcow->create_options, NULL);
2809
    set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512);
2810
    set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:");
2811

    
2812
    if (bdrv_create(bdrv_qcow, s->qcow_filename, options) < 0)
2813
        return -1;
2814

    
2815
    s->qcow = bdrv_new("");
2816
    if (s->qcow == NULL) {
2817
        return -1;
2818
    }
2819

    
2820
    ret = bdrv_open(s->qcow, s->qcow_filename,
2821
            BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, bdrv_qcow);
2822
    if (ret < 0) {
2823
        return ret;
2824
    }
2825

    
2826
#ifndef _WIN32
2827
    unlink(s->qcow_filename);
2828
#endif
2829

    
2830
    s->bs->backing_hd = calloc(sizeof(BlockDriverState), 1);
2831
    s->bs->backing_hd->drv = &vvfat_write_target;
2832
    s->bs->backing_hd->opaque = g_malloc(sizeof(void*));
2833
    *(void**)s->bs->backing_hd->opaque = s;
2834

    
2835
    return 0;
2836
}
2837

    
2838
static void vvfat_close(BlockDriverState *bs)
2839
{
2840
    BDRVVVFATState *s = bs->opaque;
2841

    
2842
    vvfat_close_current_file(s);
2843
    array_free(&(s->fat));
2844
    array_free(&(s->directory));
2845
    array_free(&(s->mapping));
2846
    g_free(s->cluster_buffer);
2847

    
2848
    if (s->qcow) {
2849
        migrate_del_blocker(s->migration_blocker);
2850
        error_free(s->migration_blocker);
2851
    }
2852
}
2853

    
2854
static BlockDriver bdrv_vvfat = {
2855
    .format_name        = "vvfat",
2856
    .instance_size        = sizeof(BDRVVVFATState),
2857
    .bdrv_file_open        = vvfat_open,
2858
    .bdrv_read          = vvfat_co_read,
2859
    .bdrv_write         = vvfat_co_write,
2860
    .bdrv_close                = vvfat_close,
2861
    .bdrv_co_is_allocated = vvfat_co_is_allocated,
2862
    .protocol_name        = "fat",
2863
};
2864

    
2865
static void bdrv_vvfat_init(void)
2866
{
2867
    bdrv_register(&bdrv_vvfat);
2868
}
2869

    
2870
block_init(bdrv_vvfat_init);
2871

    
2872
#ifdef DEBUG
2873
static void checkpoint(void) {
2874
    assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2);
2875
    check1(vvv);
2876
    check2(vvv);
2877
    assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY));
2878
#if 0
2879
    if (((direntry_t*)vvv->directory.pointer)[1].attributes != 0xf)
2880
        fprintf(stderr, "Nonono!\n");
2881
    mapping_t* mapping;
2882
    direntry_t* direntry;
2883
    assert(vvv->mapping.size >= vvv->mapping.item_size * vvv->mapping.next);
2884
    assert(vvv->directory.size >= vvv->directory.item_size * vvv->directory.next);
2885
    if (vvv->mapping.next<47)
2886
        return;
2887
    assert((mapping = array_get(&(vvv->mapping), 47)));
2888
    assert(mapping->dir_index < vvv->directory.next);
2889
    direntry = array_get(&(vvv->directory), mapping->dir_index);
2890
    assert(!memcmp(direntry->name, "USB     H  ", 11) || direntry->name[0]==0);
2891
#endif
2892
}
2893
#endif