Statistics
| Branch: | Revision:

root / block / vvfat.c @ 18ebcc86

History | View | Annotate | Download (80.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

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

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

    
46
/* #define DEBUG */
47

    
48
#ifdef DEBUG
49

    
50
#define DLOG(a) a
51

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

    
56
static void checkpoint(void);
57

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

    
67
#else
68

    
69
#define DLOG(a)
70

    
71
#endif
72

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

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

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

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

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

    
110
    return 0;
111
}
112

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

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

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

    
123
    return result;
124
}
125

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

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

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

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

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

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

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

    
171
    g_free(buf);
172

    
173
    return 0;
174
}
175

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
385
    memset(s->first_sectors,0,512);
386

    
387
    /* Win NT Disk Signature */
388
    real_mbr->nt_id= cpu_to_le32(0xbe1afdfa);
389

    
390
    partition->attributes=0x80; /* bootable */
391

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

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

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

    
407
    real_mbr->magic[0]=0x55; real_mbr->magic[1]=0xaa;
408
}
409

    
410
/* direntry functions */
411

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

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

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

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

    
458
static char is_volume_label(const direntry_t* direntry)
459
{
460
    return direntry->attributes == 0x28;
461
}
462

    
463
static char is_long_name(const direntry_t* direntry)
464
{
465
    return direntry->attributes == 0xf;
466
}
467

    
468
static char is_short_name(const direntry_t* direntry)
469
{
470
    return !is_volume_label(direntry) && !is_long_name(direntry)
471
        && !is_free(direntry);
472
}
473

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

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

    
484
static char is_file(const direntry_t* direntry)
485
{
486
    return is_short_name(direntry) && !is_directory(direntry);
487
}
488

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

    
494
static inline uint32_t filesize_of_direntry(const direntry_t* direntry)
495
{
496
    return le32_to_cpu(direntry->size);
497
}
498

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

    
505
/* fat functions */
506

    
507
static inline uint8_t fat_chksum(const direntry_t* entry)
508
{
509
    uint8_t chksum=0;
510
    int i;
511

    
512
    for(i=0;i<11;i++) {
513
        unsigned char c;
514

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

    
519
    return chksum;
520
}
521

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

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

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

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

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

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

    
602
}
603

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

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

    
620
    entry_long=create_long_filename(s,filename);
621

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

    
629
    entry=array_get_next(&(s->directory));
630
    memset(entry->name,0x20,11);
631
    memcpy(entry->name, filename, i);
632

    
633
    if(j > 0)
634
        for (i = 0; i < 3 && filename[j+1+i]; i++)
635
            entry->extension[i] = filename[j+1+i];
636

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

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

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

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

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

    
676
    /* calculate checksum; propagate to long name */
677
    if(entry_long) {
678
        uint8_t chksum=fat_chksum(entry);
679

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

    
688
    return entry;
689
}
690

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

    
705
    DIR* dir=opendir(dirname);
706
    struct dirent* entry;
707
    int i;
708

    
709
    assert(mapping->mode & MODE_DIRECTORY);
710

    
711
    if(!dir) {
712
        mapping->end = mapping->begin;
713
        return -1;
714
    }
715

    
716
    i = mapping->info.dir.first_dir_index =
717
            first_cluster == 0 ? 0 : s->directory.next;
718

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

    
728
        if(first_cluster == 0 && (is_dotdot || is_dot))
729
            continue;
730

    
731
        buffer=(char*)g_malloc(length);
732
        snprintf(buffer,length,"%s/%s",dirname,entry->d_name);
733

    
734
        if(stat(buffer,&st)<0) {
735
            g_free(buffer);
736
            continue;
737
        }
738

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

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

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

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

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

    
812
    direntry = (direntry_t*)array_get(&(s->directory), mapping->dir_index);
813
    set_begin_of_direntry(direntry, mapping->begin);
814

    
815
    return 0;
816
}
817

    
818
static inline uint32_t sector2cluster(BDRVVVFATState* s,off_t sector_num)
819
{
820
    return (sector_num-s->faked_sectors)/s->sectors_per_cluster;
821
}
822

    
823
static inline off_t cluster2sector(BDRVVVFATState* s, uint32_t cluster_num)
824
{
825
    return s->faked_sectors + s->sectors_per_cluster * cluster_num;
826
}
827

    
828
static int init_directories(BDRVVVFATState* s,
829
        const char* dirname)
830
{
831
    bootsector_t* bootsector;
832
    mapping_t* mapping;
833
    unsigned int i;
834
    unsigned int cluster;
835

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

    
838
    s->cluster_size=s->sectors_per_cluster*0x200;
839
    s->cluster_buffer=g_malloc(s->cluster_size);
840

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

    
851
    array_init(&(s->mapping),sizeof(mapping_t));
852
    array_init(&(s->directory),sizeof(direntry_t));
853

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

    
862
    /* Now build FAT, and write back information into directory */
863
    init_fat(s);
864

    
865
    s->faked_sectors=s->first_sectors_number+s->sectors_per_fat*2;
866
    s->cluster_count=sector2cluster(s, s->sector_count);
867

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

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

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

    
904
                mapping->end = cluster + 1 + (mapping->end-1)/s->cluster_size;
905
                set_begin_of_direntry(direntry, mapping->begin);
906
            } else {
907
                mapping->end = cluster + 1;
908
                fix_fat = 0;
909
            }
910
        }
911

    
912
        assert(mapping->begin < mapping->end);
913

    
914
        /* next free cluster */
915
        cluster = mapping->end;
916

    
917
        if(cluster > s->cluster_count) {
918
            fprintf(stderr,"Directory does not fit in FAT%d (capacity %s)\n",
919
                    s->fat_type,
920
                    s->fat_type == 12 ? s->sector_count == 2880 ? "1.44 MB"
921
                                                                : "2.88 MB"
922
                                      : "504MB");
923
            return -EINVAL;
924
        }
925

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

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

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

    
943
    s->current_mapping = NULL;
944

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

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

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

    
974
    return 0;
975
}
976

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

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

    
984
static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
985
{
986
    BDRVVVFATState *s = bs->opaque;
987
    int floppy = 0;
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
    s->fat_type=16;
1002
    /* LATER TODO: if FAT32, adjust */
1003
    s->sectors_per_cluster=0x10;
1004
    /* 504MB disk*/
1005
    bs->cyls=1024; bs->heads=16; bs->secs=63;
1006

    
1007
    s->current_cluster=0xffffffff;
1008

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

    
1017
    if (!strstart(dirname, "fat:", NULL))
1018
        return -1;
1019

    
1020
    if (strstr(dirname, ":floppy:")) {
1021
        floppy = 1;
1022
        s->fat_type = 12;
1023
        s->first_sectors_number = 1;
1024
        s->sectors_per_cluster=2;
1025
        bs->cyls = 80; bs->heads = 2; bs->secs = 36;
1026
    }
1027

    
1028
    s->sector_count=bs->cyls*bs->heads*bs->secs;
1029

    
1030
    if (strstr(dirname, ":32:")) {
1031
        fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. You are welcome to do so!\n");
1032
        s->fat_type = 32;
1033
    } else if (strstr(dirname, ":16:")) {
1034
        s->fat_type = 16;
1035
    } else if (strstr(dirname, ":12:")) {
1036
        s->fat_type = 12;
1037
        s->sector_count=2880;
1038
    }
1039

    
1040
    if (strstr(dirname, ":rw:")) {
1041
        if (enable_write_target(s))
1042
            return -1;
1043
        bs->read_only = 0;
1044
    }
1045

    
1046
    i = strrchr(dirname, ':') - dirname;
1047
    assert(i >= 3);
1048
    if (dirname[i-2] == ':' && qemu_isalpha(dirname[i-1]))
1049
        /* workaround for DOS drive names */
1050
        dirname += i-1;
1051
    else
1052
        dirname += i+1;
1053

    
1054
    bs->total_sectors=bs->cyls*bs->heads*bs->secs;
1055

    
1056
    if(init_directories(s, dirname))
1057
        return -1;
1058

    
1059
    s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
1060

    
1061
    if(s->first_sectors_number==0x40)
1062
        init_mbr(s);
1063

    
1064
    /* for some reason or other, MS-DOS does not like to know about CHS... */
1065
    if (floppy)
1066
        bs->heads = bs->cyls = bs->secs = 0;
1067

    
1068
    //    assert(is_consistent(s));
1069
    qemu_co_mutex_init(&s->lock);
1070
    return 0;
1071
}
1072

    
1073
static inline void vvfat_close_current_file(BDRVVVFATState *s)
1074
{
1075
    if(s->current_mapping) {
1076
        s->current_mapping = NULL;
1077
        if (s->current_fd) {
1078
                close(s->current_fd);
1079
                s->current_fd = 0;
1080
        }
1081
    }
1082
    s->current_cluster = -1;
1083
}
1084

    
1085
/* mappings between index1 and index2-1 are supposed to be ordered
1086
 * return value is the index of the last mapping for which end>cluster_num
1087
 */
1088
static inline int find_mapping_for_cluster_aux(BDRVVVFATState* s,int cluster_num,int index1,int index2)
1089
{
1090
    while(1) {
1091
        int index3;
1092
        mapping_t* mapping;
1093
        index3=(index1+index2)/2;
1094
        mapping=array_get(&(s->mapping),index3);
1095
        assert(mapping->begin < mapping->end);
1096
        if(mapping->begin>=cluster_num) {
1097
            assert(index2!=index3 || index2==0);
1098
            if(index2==index3)
1099
                return index1;
1100
            index2=index3;
1101
        } else {
1102
            if(index1==index3)
1103
                return mapping->end<=cluster_num ? index2 : index1;
1104
            index1=index3;
1105
        }
1106
        assert(index1<=index2);
1107
        DLOG(mapping=array_get(&(s->mapping),index1);
1108
        assert(mapping->begin<=cluster_num);
1109
        assert(index2 >= s->mapping.next ||
1110
                ((mapping = array_get(&(s->mapping),index2)) &&
1111
                mapping->end>cluster_num)));
1112
    }
1113
}
1114

    
1115
static inline mapping_t* find_mapping_for_cluster(BDRVVVFATState* s,int cluster_num)
1116
{
1117
    int index=find_mapping_for_cluster_aux(s,cluster_num,0,s->mapping.next);
1118
    mapping_t* mapping;
1119
    if(index>=s->mapping.next)
1120
        return NULL;
1121
    mapping=array_get(&(s->mapping),index);
1122
    if(mapping->begin>cluster_num)
1123
        return NULL;
1124
    assert(mapping->begin<=cluster_num && mapping->end>cluster_num);
1125
    return mapping;
1126
}
1127

    
1128
static int open_file(BDRVVVFATState* s,mapping_t* mapping)
1129
{
1130
    if(!mapping)
1131
        return -1;
1132
    if(!s->current_mapping ||
1133
            strcmp(s->current_mapping->path,mapping->path)) {
1134
        /* open file */
1135
        int fd = open(mapping->path, O_RDONLY | O_BINARY | O_LARGEFILE);
1136
        if(fd<0)
1137
            return -1;
1138
        vvfat_close_current_file(s);
1139
        s->current_fd = fd;
1140
        s->current_mapping = mapping;
1141
    }
1142
    return 0;
1143
}
1144

    
1145
static inline int read_cluster(BDRVVVFATState *s,int cluster_num)
1146
{
1147
    if(s->current_cluster != cluster_num) {
1148
        int result=0;
1149
        off_t offset;
1150
        assert(!s->current_mapping || s->current_fd || (s->current_mapping->mode & MODE_DIRECTORY));
1151
        if(!s->current_mapping
1152
                || s->current_mapping->begin>cluster_num
1153
                || s->current_mapping->end<=cluster_num) {
1154
            /* binary search of mappings for file */
1155
            mapping_t* mapping=find_mapping_for_cluster(s,cluster_num);
1156

    
1157
            assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
1158

    
1159
            if (mapping && mapping->mode & MODE_DIRECTORY) {
1160
                vvfat_close_current_file(s);
1161
                s->current_mapping = mapping;
1162
read_cluster_directory:
1163
                offset = s->cluster_size*(cluster_num-s->current_mapping->begin);
1164
                s->cluster = (unsigned char*)s->directory.pointer+offset
1165
                        + 0x20*s->current_mapping->info.dir.first_dir_index;
1166
                assert(((s->cluster-(unsigned char*)s->directory.pointer)%s->cluster_size)==0);
1167
                assert((char*)s->cluster+s->cluster_size <= s->directory.pointer+s->directory.next*s->directory.item_size);
1168
                s->current_cluster = cluster_num;
1169
                return 0;
1170
            }
1171

    
1172
            if(open_file(s,mapping))
1173
                return -2;
1174
        } else if (s->current_mapping->mode & MODE_DIRECTORY)
1175
            goto read_cluster_directory;
1176

    
1177
        assert(s->current_fd);
1178

    
1179
        offset=s->cluster_size*(cluster_num-s->current_mapping->begin)+s->current_mapping->info.file.offset;
1180
        if(lseek(s->current_fd, offset, SEEK_SET)!=offset)
1181
            return -3;
1182
        s->cluster=s->cluster_buffer;
1183
        result=read(s->current_fd,s->cluster,s->cluster_size);
1184
        if(result<0) {
1185
            s->current_cluster = -1;
1186
            return -1;
1187
        }
1188
        s->current_cluster = cluster_num;
1189
    }
1190
    return 0;
1191
}
1192

    
1193
#ifdef DEBUG
1194
static void print_direntry(const direntry_t* direntry)
1195
{
1196
    int j = 0;
1197
    char buffer[1024];
1198

    
1199
    fprintf(stderr, "direntry %p: ", direntry);
1200
    if(!direntry)
1201
        return;
1202
    if(is_long_name(direntry)) {
1203
        unsigned char* c=(unsigned char*)direntry;
1204
        int i;
1205
        for(i=1;i<11 && c[i] && c[i]!=0xff;i+=2)
1206
#define ADD_CHAR(c) {buffer[j] = (c); if (buffer[j] < ' ') buffer[j] = 0xb0; j++;}
1207
            ADD_CHAR(c[i]);
1208
        for(i=14;i<26 && c[i] && c[i]!=0xff;i+=2)
1209
            ADD_CHAR(c[i]);
1210
        for(i=28;i<32 && c[i] && c[i]!=0xff;i+=2)
1211
            ADD_CHAR(c[i]);
1212
        buffer[j] = 0;
1213
        fprintf(stderr, "%s\n", buffer);
1214
    } else {
1215
        int i;
1216
        for(i=0;i<11;i++)
1217
            ADD_CHAR(direntry->name[i]);
1218
        buffer[j] = 0;
1219
        fprintf(stderr,"%s attributes=0x%02x begin=%d size=%d\n",
1220
                buffer,
1221
                direntry->attributes,
1222
                begin_of_direntry(direntry),le32_to_cpu(direntry->size));
1223
    }
1224
}
1225

    
1226
static void print_mapping(const mapping_t* mapping)
1227
{
1228
    fprintf(stderr, "mapping (%p): begin, end = %d, %d, dir_index = %d, "
1229
        "first_mapping_index = %d, name = %s, mode = 0x%x, " ,
1230
        mapping, mapping->begin, mapping->end, mapping->dir_index,
1231
        mapping->first_mapping_index, mapping->path, mapping->mode);
1232

    
1233
    if (mapping->mode & MODE_DIRECTORY)
1234
        fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
1235
    else
1236
        fprintf(stderr, "offset = %d\n", mapping->info.file.offset);
1237
}
1238
#endif
1239

    
1240
static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
1241
                    uint8_t *buf, int nb_sectors)
1242
{
1243
    BDRVVVFATState *s = bs->opaque;
1244
    int i;
1245

    
1246
    for(i=0;i<nb_sectors;i++,sector_num++) {
1247
        if (sector_num >= s->sector_count)
1248
           return -1;
1249
        if (s->qcow) {
1250
            int n;
1251
            if (s->qcow->drv->bdrv_is_allocated(s->qcow,
1252
                        sector_num, nb_sectors-i, &n)) {
1253
DLOG(fprintf(stderr, "sectors %d+%d allocated\n", (int)sector_num, n));
1254
                if (s->qcow->drv->bdrv_read(s->qcow, sector_num, buf+i*0x200, n))
1255
                    return -1;
1256
                i += n - 1;
1257
                sector_num += n - 1;
1258
                continue;
1259
            }
1260
DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num));
1261
        }
1262
        if(sector_num<s->faked_sectors) {
1263
            if(sector_num<s->first_sectors_number)
1264
                memcpy(buf+i*0x200,&(s->first_sectors[sector_num*0x200]),0x200);
1265
            else if(sector_num-s->first_sectors_number<s->sectors_per_fat)
1266
                memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number)*0x200]),0x200);
1267
            else if(sector_num-s->first_sectors_number-s->sectors_per_fat<s->sectors_per_fat)
1268
                memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number-s->sectors_per_fat)*0x200]),0x200);
1269
        } else {
1270
            uint32_t sector=sector_num-s->faked_sectors,
1271
            sector_offset_in_cluster=(sector%s->sectors_per_cluster),
1272
            cluster_num=sector/s->sectors_per_cluster;
1273
            if(read_cluster(s, cluster_num) != 0) {
1274
                /* LATER TODO: strict: return -1; */
1275
                memset(buf+i*0x200,0,0x200);
1276
                continue;
1277
            }
1278
            memcpy(buf+i*0x200,s->cluster+sector_offset_in_cluster*0x200,0x200);
1279
        }
1280
    }
1281
    return 0;
1282
}
1283

    
1284
static coroutine_fn int vvfat_co_read(BlockDriverState *bs, int64_t sector_num,
1285
                                      uint8_t *buf, int nb_sectors)
1286
{
1287
    int ret;
1288
    BDRVVVFATState *s = bs->opaque;
1289
    qemu_co_mutex_lock(&s->lock);
1290
    ret = vvfat_read(bs, sector_num, buf, nb_sectors);
1291
    qemu_co_mutex_unlock(&s->lock);
1292
    return ret;
1293
}
1294

    
1295
/* LATER TODO: statify all functions */
1296

    
1297
/*
1298
 * Idea of the write support (use snapshot):
1299
 *
1300
 * 1. check if all data is consistent, recording renames, modifications,
1301
 *    new files and directories (in s->commits).
1302
 *
1303
 * 2. if the data is not consistent, stop committing
1304
 *
1305
 * 3. handle renames, and create new files and directories (do not yet
1306
 *    write their contents)
1307
 *
1308
 * 4. walk the directories, fixing the mapping and direntries, and marking
1309
 *    the handled mappings as not deleted
1310
 *
1311
 * 5. commit the contents of the files
1312
 *
1313
 * 6. handle deleted files and directories
1314
 *
1315
 */
1316

    
1317
typedef struct commit_t {
1318
    char* path;
1319
    union {
1320
        struct { uint32_t cluster; } rename;
1321
        struct { int dir_index; uint32_t modified_offset; } writeout;
1322
        struct { uint32_t first_cluster; } new_file;
1323
        struct { uint32_t cluster; } mkdir;
1324
    } param;
1325
    /* DELETEs and RMDIRs are handled differently: see handle_deletes() */
1326
    enum {
1327
        ACTION_RENAME, ACTION_WRITEOUT, ACTION_NEW_FILE, ACTION_MKDIR
1328
    } action;
1329
} commit_t;
1330

    
1331
static void clear_commits(BDRVVVFATState* s)
1332
{
1333
    int i;
1334
DLOG(fprintf(stderr, "clear_commits (%d commits)\n", s->commits.next));
1335
    for (i = 0; i < s->commits.next; i++) {
1336
        commit_t* commit = array_get(&(s->commits), i);
1337
        assert(commit->path || commit->action == ACTION_WRITEOUT);
1338
        if (commit->action != ACTION_WRITEOUT) {
1339
            assert(commit->path);
1340
            g_free(commit->path);
1341
        } else
1342
            assert(commit->path == NULL);
1343
    }
1344
    s->commits.next = 0;
1345
}
1346

    
1347
static void schedule_rename(BDRVVVFATState* s,
1348
        uint32_t cluster, char* new_path)
1349
{
1350
    commit_t* commit = array_get_next(&(s->commits));
1351
    commit->path = new_path;
1352
    commit->param.rename.cluster = cluster;
1353
    commit->action = ACTION_RENAME;
1354
}
1355

    
1356
static void schedule_writeout(BDRVVVFATState* s,
1357
        int dir_index, uint32_t modified_offset)
1358
{
1359
    commit_t* commit = array_get_next(&(s->commits));
1360
    commit->path = NULL;
1361
    commit->param.writeout.dir_index = dir_index;
1362
    commit->param.writeout.modified_offset = modified_offset;
1363
    commit->action = ACTION_WRITEOUT;
1364
}
1365

    
1366
static void schedule_new_file(BDRVVVFATState* s,
1367
        char* path, uint32_t first_cluster)
1368
{
1369
    commit_t* commit = array_get_next(&(s->commits));
1370
    commit->path = path;
1371
    commit->param.new_file.first_cluster = first_cluster;
1372
    commit->action = ACTION_NEW_FILE;
1373
}
1374

    
1375
static void schedule_mkdir(BDRVVVFATState* s, uint32_t cluster, char* path)
1376
{
1377
    commit_t* commit = array_get_next(&(s->commits));
1378
    commit->path = path;
1379
    commit->param.mkdir.cluster = cluster;
1380
    commit->action = ACTION_MKDIR;
1381
}
1382

    
1383
typedef struct {
1384
    /*
1385
     * Since the sequence number is at most 0x3f, and the filename
1386
     * length is at most 13 times the sequence number, the maximal
1387
     * filename length is 0x3f * 13 bytes.
1388
     */
1389
    unsigned char name[0x3f * 13 + 1];
1390
    int checksum, len;
1391
    int sequence_number;
1392
} long_file_name;
1393

    
1394
static void lfn_init(long_file_name* lfn)
1395
{
1396
   lfn->sequence_number = lfn->len = 0;
1397
   lfn->checksum = 0x100;
1398
}
1399

    
1400
/* return 0 if parsed successfully, > 0 if no long name, < 0 if error */
1401
static int parse_long_name(long_file_name* lfn,
1402
        const direntry_t* direntry)
1403
{
1404
    int i, j, offset;
1405
    const unsigned char* pointer = (const unsigned char*)direntry;
1406

    
1407
    if (!is_long_name(direntry))
1408
        return 1;
1409

    
1410
    if (pointer[0] & 0x40) {
1411
        lfn->sequence_number = pointer[0] & 0x3f;
1412
        lfn->checksum = pointer[13];
1413
        lfn->name[0] = 0;
1414
        lfn->name[lfn->sequence_number * 13] = 0;
1415
    } else if ((pointer[0] & 0x3f) != --lfn->sequence_number)
1416
        return -1;
1417
    else if (pointer[13] != lfn->checksum)
1418
        return -2;
1419
    else if (pointer[12] || pointer[26] || pointer[27])
1420
        return -3;
1421

    
1422
    offset = 13 * (lfn->sequence_number - 1);
1423
    for (i = 0, j = 1; i < 13; i++, j+=2) {
1424
        if (j == 11)
1425
            j = 14;
1426
        else if (j == 26)
1427
            j = 28;
1428

    
1429
        if (pointer[j+1] == 0)
1430
            lfn->name[offset + i] = pointer[j];
1431
        else if (pointer[j+1] != 0xff || (pointer[0] & 0x40) == 0)
1432
            return -4;
1433
        else
1434
            lfn->name[offset + i] = 0;
1435
    }
1436

    
1437
    if (pointer[0] & 0x40)
1438
        lfn->len = offset + strlen((char*)lfn->name + offset);
1439

    
1440
    return 0;
1441
}
1442

    
1443
/* returns 0 if successful, >0 if no short_name, and <0 on error */
1444
static int parse_short_name(BDRVVVFATState* s,
1445
        long_file_name* lfn, direntry_t* direntry)
1446
{
1447
    int i, j;
1448

    
1449
    if (!is_short_name(direntry))
1450
        return 1;
1451

    
1452
    for (j = 7; j >= 0 && direntry->name[j] == ' '; j--);
1453
    for (i = 0; i <= j; i++) {
1454
        if (direntry->name[i] <= ' ' || direntry->name[i] > 0x7f)
1455
            return -1;
1456
        else if (s->downcase_short_names)
1457
            lfn->name[i] = qemu_tolower(direntry->name[i]);
1458
        else
1459
            lfn->name[i] = direntry->name[i];
1460
    }
1461

    
1462
    for (j = 2; j >= 0 && direntry->extension[j] == ' '; j--);
1463
    if (j >= 0) {
1464
        lfn->name[i++] = '.';
1465
        lfn->name[i + j + 1] = '\0';
1466
        for (;j >= 0; j--) {
1467
            if (direntry->extension[j] <= ' ' || direntry->extension[j] > 0x7f)
1468
                return -2;
1469
            else if (s->downcase_short_names)
1470
                lfn->name[i + j] = qemu_tolower(direntry->extension[j]);
1471
            else
1472
                lfn->name[i + j] = direntry->extension[j];
1473
        }
1474
    } else
1475
        lfn->name[i + j + 1] = '\0';
1476

    
1477
    lfn->len = strlen((char*)lfn->name);
1478

    
1479
    return 0;
1480
}
1481

    
1482
static inline uint32_t modified_fat_get(BDRVVVFATState* s,
1483
        unsigned int cluster)
1484
{
1485
    if (cluster < s->last_cluster_of_root_directory) {
1486
        if (cluster + 1 == s->last_cluster_of_root_directory)
1487
            return s->max_fat_value;
1488
        else
1489
            return cluster + 1;
1490
    }
1491

    
1492
    if (s->fat_type==32) {
1493
        uint32_t* entry=((uint32_t*)s->fat2)+cluster;
1494
        return le32_to_cpu(*entry);
1495
    } else if (s->fat_type==16) {
1496
        uint16_t* entry=((uint16_t*)s->fat2)+cluster;
1497
        return le16_to_cpu(*entry);
1498
    } else {
1499
        const uint8_t* x=s->fat2+cluster*3/2;
1500
        return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
1501
    }
1502
}
1503

    
1504
static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num)
1505
{
1506
    int was_modified = 0;
1507
    int i, dummy;
1508

    
1509
    if (s->qcow == NULL)
1510
        return 0;
1511

    
1512
    for (i = 0; !was_modified && i < s->sectors_per_cluster; i++)
1513
        was_modified = s->qcow->drv->bdrv_is_allocated(s->qcow,
1514
                cluster2sector(s, cluster_num) + i, 1, &dummy);
1515

    
1516
    return was_modified;
1517
}
1518

    
1519
static const char* get_basename(const char* path)
1520
{
1521
    char* basename = strrchr(path, '/');
1522
    if (basename == NULL)
1523
        return path;
1524
    else
1525
        return basename + 1; /* strip '/' */
1526
}
1527

    
1528
/*
1529
 * The array s->used_clusters holds the states of the clusters. If it is
1530
 * part of a file, it has bit 2 set, in case of a directory, bit 1. If it
1531
 * was modified, bit 3 is set.
1532
 * If any cluster is allocated, but not part of a file or directory, this
1533
 * driver refuses to commit.
1534
 */
1535
typedef enum {
1536
     USED_DIRECTORY = 1, USED_FILE = 2, USED_ANY = 3, USED_ALLOCATED = 4
1537
} used_t;
1538

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

    
1573
    uint32_t cluster_num = begin_of_direntry(direntry);
1574
    uint32_t offset = 0;
1575
    int first_mapping_index = -1;
1576
    mapping_t* mapping = NULL;
1577
    const char* basename2 = NULL;
1578

    
1579
    vvfat_close_current_file(s);
1580

    
1581
    /* the root directory */
1582
    if (cluster_num == 0)
1583
        return 0;
1584

    
1585
    /* write support */
1586
    if (s->qcow) {
1587
        basename2 = get_basename(path);
1588

    
1589
        mapping = find_mapping_for_cluster(s, cluster_num);
1590

    
1591
        if (mapping) {
1592
            const char* basename;
1593

    
1594
            assert(mapping->mode & MODE_DELETED);
1595
            mapping->mode &= ~MODE_DELETED;
1596

    
1597
            basename = get_basename(mapping->path);
1598

    
1599
            assert(mapping->mode & MODE_NORMAL);
1600

    
1601
            /* rename */
1602
            if (strcmp(basename, basename2))
1603
                schedule_rename(s, cluster_num, g_strdup(path));
1604
        } else if (is_file(direntry))
1605
            /* new file */
1606
            schedule_new_file(s, g_strdup(path), cluster_num);
1607
        else {
1608
            abort();
1609
            return 0;
1610
        }
1611
    }
1612

    
1613
    while(1) {
1614
        if (s->qcow) {
1615
            if (!copy_it && cluster_was_modified(s, cluster_num)) {
1616
                if (mapping == NULL ||
1617
                        mapping->begin > cluster_num ||
1618
                        mapping->end <= cluster_num)
1619
                mapping = find_mapping_for_cluster(s, cluster_num);
1620

    
1621

    
1622
                if (mapping &&
1623
                        (mapping->mode & MODE_DIRECTORY) == 0) {
1624

    
1625
                    /* was modified in qcow */
1626
                    if (offset != mapping->info.file.offset + s->cluster_size
1627
                            * (cluster_num - mapping->begin)) {
1628
                        /* offset of this cluster in file chain has changed */
1629
                        abort();
1630
                        copy_it = 1;
1631
                    } else if (offset == 0) {
1632
                        const char* basename = get_basename(mapping->path);
1633

    
1634
                        if (strcmp(basename, basename2))
1635
                            copy_it = 1;
1636
                        first_mapping_index = array_index(&(s->mapping), mapping);
1637
                    }
1638

    
1639
                    if (mapping->first_mapping_index != first_mapping_index
1640
                            && mapping->info.file.offset > 0) {
1641
                        abort();
1642
                        copy_it = 1;
1643
                    }
1644

    
1645
                    /* need to write out? */
1646
                    if (!was_modified && is_file(direntry)) {
1647
                        was_modified = 1;
1648
                        schedule_writeout(s, mapping->dir_index, offset);
1649
                    }
1650
                }
1651
            }
1652

    
1653
            if (copy_it) {
1654
                int i, dummy;
1655
                /*
1656
                 * This is horribly inefficient, but that is okay, since
1657
                 * it is rarely executed, if at all.
1658
                 */
1659
                int64_t offset = cluster2sector(s, cluster_num);
1660

    
1661
                vvfat_close_current_file(s);
1662
                for (i = 0; i < s->sectors_per_cluster; i++)
1663
                    if (!s->qcow->drv->bdrv_is_allocated(s->qcow,
1664
                                offset + i, 1, &dummy)) {
1665
                        if (vvfat_read(s->bs,
1666
                                    offset, s->cluster_buffer, 1))
1667
                            return -1;
1668
                        if (s->qcow->drv->bdrv_write(s->qcow,
1669
                                    offset, s->cluster_buffer, 1))
1670
                            return -2;
1671
                    }
1672
            }
1673
        }
1674

    
1675
        ret++;
1676
        if (s->used_clusters[cluster_num] & USED_ANY)
1677
            return 0;
1678
        s->used_clusters[cluster_num] = USED_FILE;
1679

    
1680
        cluster_num = modified_fat_get(s, cluster_num);
1681

    
1682
        if (fat_eof(s, cluster_num))
1683
            return ret;
1684
        else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
1685
            return -1;
1686

    
1687
        offset += s->cluster_size;
1688
    }
1689
}
1690

    
1691
/*
1692
 * This function looks at the modified data (qcow).
1693
 * It returns 0 upon inconsistency or error, and the number of clusters
1694
 * used by the directory, its subdirectories and their files.
1695
 */
1696
static int check_directory_consistency(BDRVVVFATState *s,
1697
        int cluster_num, const char* path)
1698
{
1699
    int ret = 0;
1700
    unsigned char* cluster = g_malloc(s->cluster_size);
1701
    direntry_t* direntries = (direntry_t*)cluster;
1702
    mapping_t* mapping = find_mapping_for_cluster(s, cluster_num);
1703

    
1704
    long_file_name lfn;
1705
    int path_len = strlen(path);
1706
    char path2[PATH_MAX + 1];
1707

    
1708
    assert(path_len < PATH_MAX); /* len was tested before! */
1709
    pstrcpy(path2, sizeof(path2), path);
1710
    path2[path_len] = '/';
1711
    path2[path_len + 1] = '\0';
1712

    
1713
    if (mapping) {
1714
        const char* basename = get_basename(mapping->path);
1715
        const char* basename2 = get_basename(path);
1716

    
1717
        assert(mapping->mode & MODE_DIRECTORY);
1718

    
1719
        assert(mapping->mode & MODE_DELETED);
1720
        mapping->mode &= ~MODE_DELETED;
1721

    
1722
        if (strcmp(basename, basename2))
1723
            schedule_rename(s, cluster_num, g_strdup(path));
1724
    } else
1725
        /* new directory */
1726
        schedule_mkdir(s, cluster_num, g_strdup(path));
1727

    
1728
    lfn_init(&lfn);
1729
    do {
1730
        int i;
1731
        int subret = 0;
1732

    
1733
        ret++;
1734

    
1735
        if (s->used_clusters[cluster_num] & USED_ANY) {
1736
            fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
1737
            return 0;
1738
        }
1739
        s->used_clusters[cluster_num] = USED_DIRECTORY;
1740

    
1741
DLOG(fprintf(stderr, "read cluster %d (sector %d)\n", (int)cluster_num, (int)cluster2sector(s, cluster_num)));
1742
        subret = vvfat_read(s->bs, cluster2sector(s, cluster_num), cluster,
1743
                s->sectors_per_cluster);
1744
        if (subret) {
1745
            fprintf(stderr, "Error fetching direntries\n");
1746
        fail:
1747
            g_free(cluster);
1748
            return 0;
1749
        }
1750

    
1751
        for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
1752
            int cluster_count = 0;
1753

    
1754
DLOG(fprintf(stderr, "check direntry %d:\n", i); print_direntry(direntries + i));
1755
            if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
1756
                    is_free(direntries + i))
1757
                continue;
1758

    
1759
            subret = parse_long_name(&lfn, direntries + i);
1760
            if (subret < 0) {
1761
                fprintf(stderr, "Error in long name\n");
1762
                goto fail;
1763
            }
1764
            if (subret == 0 || is_free(direntries + i))
1765
                continue;
1766

    
1767
            if (fat_chksum(direntries+i) != lfn.checksum) {
1768
                subret = parse_short_name(s, &lfn, direntries + i);
1769
                if (subret < 0) {
1770
                    fprintf(stderr, "Error in short name (%d)\n", subret);
1771
                    goto fail;
1772
                }
1773
                if (subret > 0 || !strcmp((char*)lfn.name, ".")
1774
                        || !strcmp((char*)lfn.name, ".."))
1775
                    continue;
1776
            }
1777
            lfn.checksum = 0x100; /* cannot use long name twice */
1778

    
1779
            if (path_len + 1 + lfn.len >= PATH_MAX) {
1780
                fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
1781
                goto fail;
1782
            }
1783
            pstrcpy(path2 + path_len + 1, sizeof(path2) - path_len - 1,
1784
                    (char*)lfn.name);
1785

    
1786
            if (is_directory(direntries + i)) {
1787
                if (begin_of_direntry(direntries + i) == 0) {
1788
                    DLOG(fprintf(stderr, "invalid begin for directory: %s\n", path2); print_direntry(direntries + i));
1789
                    goto fail;
1790
                }
1791
                cluster_count = check_directory_consistency(s,
1792
                        begin_of_direntry(direntries + i), path2);
1793
                if (cluster_count == 0) {
1794
                    DLOG(fprintf(stderr, "problem in directory %s:\n", path2); print_direntry(direntries + i));
1795
                    goto fail;
1796
                }
1797
            } else if (is_file(direntries + i)) {
1798
                /* check file size with FAT */
1799
                cluster_count = get_cluster_count_for_direntry(s, direntries + i, path2);
1800
                if (cluster_count !=
1801
                        (le32_to_cpu(direntries[i].size) + s->cluster_size
1802
                         - 1) / s->cluster_size) {
1803
                    DLOG(fprintf(stderr, "Cluster count mismatch\n"));
1804
                    goto fail;
1805
                }
1806
            } else
1807
                abort(); /* cluster_count = 0; */
1808

    
1809
            ret += cluster_count;
1810
        }
1811

    
1812
        cluster_num = modified_fat_get(s, cluster_num);
1813
    } while(!fat_eof(s, cluster_num));
1814

    
1815
    g_free(cluster);
1816
    return ret;
1817
}
1818

    
1819
/* returns 1 on success */
1820
static int is_consistent(BDRVVVFATState* s)
1821
{
1822
    int i, check;
1823
    int used_clusters_count = 0;
1824

    
1825
DLOG(checkpoint());
1826
    /*
1827
     * - get modified FAT
1828
     * - compare the two FATs (TODO)
1829
     * - get buffer for marking used clusters
1830
     * - recurse direntries from root (using bs->bdrv_read to make
1831
     *    sure to get the new data)
1832
     *   - check that the FAT agrees with the size
1833
     *   - count the number of clusters occupied by this directory and
1834
     *     its files
1835
     * - check that the cumulative used cluster count agrees with the
1836
     *   FAT
1837
     * - if all is fine, return number of used clusters
1838
     */
1839
    if (s->fat2 == NULL) {
1840
        int size = 0x200 * s->sectors_per_fat;
1841
        s->fat2 = g_malloc(size);
1842
        memcpy(s->fat2, s->fat.pointer, size);
1843
    }
1844
    check = vvfat_read(s->bs,
1845
            s->first_sectors_number, s->fat2, s->sectors_per_fat);
1846
    if (check) {
1847
        fprintf(stderr, "Could not copy fat\n");
1848
        return 0;
1849
    }
1850
    assert (s->used_clusters);
1851
    for (i = 0; i < sector2cluster(s, s->sector_count); i++)
1852
        s->used_clusters[i] &= ~USED_ANY;
1853

    
1854
    clear_commits(s);
1855

    
1856
    /* mark every mapped file/directory as deleted.
1857
     * (check_directory_consistency() will unmark those still present). */
1858
    if (s->qcow)
1859
        for (i = 0; i < s->mapping.next; i++) {
1860
            mapping_t* mapping = array_get(&(s->mapping), i);
1861
            if (mapping->first_mapping_index < 0)
1862
                mapping->mode |= MODE_DELETED;
1863
        }
1864

    
1865
    used_clusters_count = check_directory_consistency(s, 0, s->path);
1866
    if (used_clusters_count <= 0) {
1867
        DLOG(fprintf(stderr, "problem in directory\n"));
1868
        return 0;
1869
    }
1870

    
1871
    check = s->last_cluster_of_root_directory;
1872
    for (i = check; i < sector2cluster(s, s->sector_count); i++) {
1873
        if (modified_fat_get(s, i)) {
1874
            if(!s->used_clusters[i]) {
1875
                DLOG(fprintf(stderr, "FAT was modified (%d), but cluster is not used?\n", i));
1876
                return 0;
1877
            }
1878
            check++;
1879
        }
1880

    
1881
        if (s->used_clusters[i] == USED_ALLOCATED) {
1882
            /* allocated, but not used... */
1883
            DLOG(fprintf(stderr, "unused, modified cluster: %d\n", i));
1884
            return 0;
1885
        }
1886
    }
1887

    
1888
    if (check != used_clusters_count)
1889
        return 0;
1890

    
1891
    return used_clusters_count;
1892
}
1893

    
1894
static inline void adjust_mapping_indices(BDRVVVFATState* s,
1895
        int offset, int adjust)
1896
{
1897
    int i;
1898

    
1899
    for (i = 0; i < s->mapping.next; i++) {
1900
        mapping_t* mapping = array_get(&(s->mapping), i);
1901

    
1902
#define ADJUST_MAPPING_INDEX(name) \
1903
        if (mapping->name >= offset) \
1904
            mapping->name += adjust
1905

    
1906
        ADJUST_MAPPING_INDEX(first_mapping_index);
1907
        if (mapping->mode & MODE_DIRECTORY)
1908
            ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
1909
    }
1910
}
1911

    
1912
/* insert or update mapping */
1913
static mapping_t* insert_mapping(BDRVVVFATState* s,
1914
        uint32_t begin, uint32_t end)
1915
{
1916
    /*
1917
     * - find mapping where mapping->begin >= begin,
1918
     * - if mapping->begin > begin: insert
1919
     *   - adjust all references to mappings!
1920
     * - else: adjust
1921
     * - replace name
1922
     */
1923
    int index = find_mapping_for_cluster_aux(s, begin, 0, s->mapping.next);
1924
    mapping_t* mapping = NULL;
1925
    mapping_t* first_mapping = array_get(&(s->mapping), 0);
1926

    
1927
    if (index < s->mapping.next && (mapping = array_get(&(s->mapping), index))
1928
            && mapping->begin < begin) {
1929
        mapping->end = begin;
1930
        index++;
1931
        mapping = array_get(&(s->mapping), index);
1932
    }
1933
    if (index >= s->mapping.next || mapping->begin > begin) {
1934
        mapping = array_insert(&(s->mapping), index, 1);
1935
        mapping->path = NULL;
1936
        adjust_mapping_indices(s, index, +1);
1937
    }
1938

    
1939
    mapping->begin = begin;
1940
    mapping->end = end;
1941

    
1942
DLOG(mapping_t* next_mapping;
1943
assert(index + 1 >= s->mapping.next ||
1944
((next_mapping = array_get(&(s->mapping), index + 1)) &&
1945
 next_mapping->begin >= end)));
1946

    
1947
    if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1948
        s->current_mapping = array_get(&(s->mapping),
1949
                s->current_mapping - first_mapping);
1950

    
1951
    return mapping;
1952
}
1953

    
1954
static int remove_mapping(BDRVVVFATState* s, int mapping_index)
1955
{
1956
    mapping_t* mapping = array_get(&(s->mapping), mapping_index);
1957
    mapping_t* first_mapping = array_get(&(s->mapping), 0);
1958

    
1959
    /* free mapping */
1960
    if (mapping->first_mapping_index < 0) {
1961
        g_free(mapping->path);
1962
    }
1963

    
1964
    /* remove from s->mapping */
1965
    array_remove(&(s->mapping), mapping_index);
1966

    
1967
    /* adjust all references to mappings */
1968
    adjust_mapping_indices(s, mapping_index, -1);
1969

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

    
1974
    return 0;
1975
}
1976

    
1977
static void adjust_dirindices(BDRVVVFATState* s, int offset, int adjust)
1978
{
1979
    int i;
1980
    for (i = 0; i < s->mapping.next; i++) {
1981
        mapping_t* mapping = array_get(&(s->mapping), i);
1982
        if (mapping->dir_index >= offset)
1983
            mapping->dir_index += adjust;
1984
        if ((mapping->mode & MODE_DIRECTORY) &&
1985
                mapping->info.dir.first_dir_index >= offset)
1986
            mapping->info.dir.first_dir_index += adjust;
1987
    }
1988
}
1989

    
1990
static direntry_t* insert_direntries(BDRVVVFATState* s,
1991
        int dir_index, int count)
1992
{
1993
    /*
1994
     * make room in s->directory,
1995
     * adjust_dirindices
1996
     */
1997
    direntry_t* result = array_insert(&(s->directory), dir_index, count);
1998
    if (result == NULL)
1999
        return NULL;
2000
    adjust_dirindices(s, dir_index, count);
2001
    return result;
2002
}
2003

    
2004
static int remove_direntries(BDRVVVFATState* s, int dir_index, int count)
2005
{
2006
    int ret = array_remove_slice(&(s->directory), dir_index, count);
2007
    if (ret)
2008
        return ret;
2009
    adjust_dirindices(s, dir_index, -count);
2010
    return 0;
2011
}
2012

    
2013
/*
2014
 * Adapt the mappings of the cluster chain starting at first cluster
2015
 * (i.e. if a file starts at first_cluster, the chain is followed according
2016
 * to the modified fat, and the corresponding entries in s->mapping are
2017
 * adjusted)
2018
 */
2019
static int commit_mappings(BDRVVVFATState* s,
2020
        uint32_t first_cluster, int dir_index)
2021
{
2022
    mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2023
    direntry_t* direntry = array_get(&(s->directory), dir_index);
2024
    uint32_t cluster = first_cluster;
2025

    
2026
    vvfat_close_current_file(s);
2027

    
2028
    assert(mapping);
2029
    assert(mapping->begin == first_cluster);
2030
    mapping->first_mapping_index = -1;
2031
    mapping->dir_index = dir_index;
2032
    mapping->mode = (dir_index <= 0 || is_directory(direntry)) ?
2033
        MODE_DIRECTORY : MODE_NORMAL;
2034

    
2035
    while (!fat_eof(s, cluster)) {
2036
        uint32_t c, c1;
2037

    
2038
        for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
2039
                c = c1, c1 = modified_fat_get(s, c1));
2040

    
2041
        c++;
2042
        if (c > mapping->end) {
2043
            int index = array_index(&(s->mapping), mapping);
2044
            int i, max_i = s->mapping.next - index;
2045
            for (i = 1; i < max_i && mapping[i].begin < c; i++);
2046
            while (--i > 0)
2047
                remove_mapping(s, index + 1);
2048
        }
2049
        assert(mapping == array_get(&(s->mapping), s->mapping.next - 1)
2050
                || mapping[1].begin >= c);
2051
        mapping->end = c;
2052

    
2053
        if (!fat_eof(s, c1)) {
2054
            int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next);
2055
            mapping_t* next_mapping = i >= s->mapping.next ? NULL :
2056
                array_get(&(s->mapping), i);
2057

    
2058
            if (next_mapping == NULL || next_mapping->begin > c1) {
2059
                int i1 = array_index(&(s->mapping), mapping);
2060

    
2061
                next_mapping = insert_mapping(s, c1, c1+1);
2062

    
2063
                if (c1 < c)
2064
                    i1++;
2065
                mapping = array_get(&(s->mapping), i1);
2066
            }
2067

    
2068
            next_mapping->dir_index = mapping->dir_index;
2069
            next_mapping->first_mapping_index =
2070
                mapping->first_mapping_index < 0 ?
2071
                array_index(&(s->mapping), mapping) :
2072
                mapping->first_mapping_index;
2073
            next_mapping->path = mapping->path;
2074
            next_mapping->mode = mapping->mode;
2075
            next_mapping->read_only = mapping->read_only;
2076
            if (mapping->mode & MODE_DIRECTORY) {
2077
                next_mapping->info.dir.parent_mapping_index =
2078
                        mapping->info.dir.parent_mapping_index;
2079
                next_mapping->info.dir.first_dir_index =
2080
                        mapping->info.dir.first_dir_index +
2081
                        0x10 * s->sectors_per_cluster *
2082
                        (mapping->end - mapping->begin);
2083
            } else
2084
                next_mapping->info.file.offset = mapping->info.file.offset +
2085
                        mapping->end - mapping->begin;
2086

    
2087
            mapping = next_mapping;
2088
        }
2089

    
2090
        cluster = c1;
2091
    }
2092

    
2093
    return 0;
2094
}
2095

    
2096
static int commit_direntries(BDRVVVFATState* s,
2097
        int dir_index, int parent_mapping_index)
2098
{
2099
    direntry_t* direntry = array_get(&(s->directory), dir_index);
2100
    uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
2101
    mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2102

    
2103
    int factor = 0x10 * s->sectors_per_cluster;
2104
    int old_cluster_count, new_cluster_count;
2105
    int current_dir_index = mapping->info.dir.first_dir_index;
2106
    int first_dir_index = current_dir_index;
2107
    int ret, i;
2108
    uint32_t c;
2109

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

    
2112
    assert(direntry);
2113
    assert(mapping);
2114
    assert(mapping->begin == first_cluster);
2115
    assert(mapping->info.dir.first_dir_index < s->directory.next);
2116
    assert(mapping->mode & MODE_DIRECTORY);
2117
    assert(dir_index == 0 || is_directory(direntry));
2118

    
2119
    mapping->info.dir.parent_mapping_index = parent_mapping_index;
2120

    
2121
    if (first_cluster == 0) {
2122
        old_cluster_count = new_cluster_count =
2123
            s->last_cluster_of_root_directory;
2124
    } else {
2125
        for (old_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2126
                c = fat_get(s, c))
2127
            old_cluster_count++;
2128

    
2129
        for (new_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2130
                c = modified_fat_get(s, c))
2131
            new_cluster_count++;
2132
    }
2133

    
2134
    if (new_cluster_count > old_cluster_count) {
2135
        if (insert_direntries(s,
2136
                current_dir_index + factor * old_cluster_count,
2137
                factor * (new_cluster_count - old_cluster_count)) == NULL)
2138
            return -1;
2139
    } else if (new_cluster_count < old_cluster_count)
2140
        remove_direntries(s,
2141
                current_dir_index + factor * new_cluster_count,
2142
                factor * (old_cluster_count - new_cluster_count));
2143

    
2144
    for (c = first_cluster; !fat_eof(s, c); c = modified_fat_get(s, c)) {
2145
        void* direntry = array_get(&(s->directory), current_dir_index);
2146
        int ret = vvfat_read(s->bs, cluster2sector(s, c), direntry,
2147
                s->sectors_per_cluster);
2148
        if (ret)
2149
            return ret;
2150
        assert(!strncmp(s->directory.pointer, "QEMU", 4));
2151
        current_dir_index += factor;
2152
    }
2153

    
2154
    ret = commit_mappings(s, first_cluster, dir_index);
2155
    if (ret)
2156
        return ret;
2157

    
2158
    /* recurse */
2159
    for (i = 0; i < factor * new_cluster_count; i++) {
2160
        direntry = array_get(&(s->directory), first_dir_index + i);
2161
        if (is_directory(direntry) && !is_dot(direntry)) {
2162
            mapping = find_mapping_for_cluster(s, first_cluster);
2163
            assert(mapping->mode & MODE_DIRECTORY);
2164
            ret = commit_direntries(s, first_dir_index + i,
2165
                array_index(&(s->mapping), mapping));
2166
            if (ret)
2167
                return ret;
2168
        }
2169
    }
2170

    
2171
    return 0;
2172
}
2173

    
2174
/* commit one file (adjust contents, adjust mapping),
2175
   return first_mapping_index */
2176
static int commit_one_file(BDRVVVFATState* s,
2177
        int dir_index, uint32_t offset)
2178
{
2179
    direntry_t* direntry = array_get(&(s->directory), dir_index);
2180
    uint32_t c = begin_of_direntry(direntry);
2181
    uint32_t first_cluster = c;
2182
    mapping_t* mapping = find_mapping_for_cluster(s, c);
2183
    uint32_t size = filesize_of_direntry(direntry);
2184
    char* cluster = g_malloc(s->cluster_size);
2185
    uint32_t i;
2186
    int fd = 0;
2187

    
2188
    assert(offset < size);
2189
    assert((offset % s->cluster_size) == 0);
2190

    
2191
    for (i = s->cluster_size; i < offset; i += s->cluster_size)
2192
        c = modified_fat_get(s, c);
2193

    
2194
    fd = open(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666);
2195
    if (fd < 0) {
2196
        fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path,
2197
                strerror(errno), errno);
2198
        g_free(cluster);
2199
        return fd;
2200
    }
2201
    if (offset > 0) {
2202
        if (lseek(fd, offset, SEEK_SET) != offset) {
2203
            g_free(cluster);
2204
            return -3;
2205
        }
2206
    }
2207

    
2208
    while (offset < size) {
2209
        uint32_t c1;
2210
        int rest_size = (size - offset > s->cluster_size ?
2211
                s->cluster_size : size - offset);
2212
        int ret;
2213

    
2214
        c1 = modified_fat_get(s, c);
2215

    
2216
        assert((size - offset == 0 && fat_eof(s, c)) ||
2217
                (size > offset && c >=2 && !fat_eof(s, c)));
2218

    
2219
        ret = vvfat_read(s->bs, cluster2sector(s, c),
2220
            (uint8_t*)cluster, (rest_size + 0x1ff) / 0x200);
2221

    
2222
        if (ret < 0) {
2223
            g_free(cluster);
2224
            return ret;
2225
        }
2226

    
2227
        if (write(fd, cluster, rest_size) < 0) {
2228
            g_free(cluster);
2229
            return -2;
2230
        }
2231

    
2232
        offset += rest_size;
2233
        c = c1;
2234
    }
2235

    
2236
    if (ftruncate(fd, size)) {
2237
        perror("ftruncate()");
2238
        close(fd);
2239
        g_free(cluster);
2240
        return -4;
2241
    }
2242
    close(fd);
2243
    g_free(cluster);
2244

    
2245
    return commit_mappings(s, first_cluster, dir_index);
2246
}
2247

    
2248
#ifdef DEBUG
2249
/* test, if all mappings point to valid direntries */
2250
static void check1(BDRVVVFATState* s)
2251
{
2252
    int i;
2253
    for (i = 0; i < s->mapping.next; i++) {
2254
        mapping_t* mapping = array_get(&(s->mapping), i);
2255
        if (mapping->mode & MODE_DELETED) {
2256
            fprintf(stderr, "deleted\n");
2257
            continue;
2258
        }
2259
        assert(mapping->dir_index < s->directory.next);
2260
        direntry_t* direntry = array_get(&(s->directory), mapping->dir_index);
2261
        assert(mapping->begin == begin_of_direntry(direntry) || mapping->first_mapping_index >= 0);
2262
        if (mapping->mode & MODE_DIRECTORY) {
2263
            assert(mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster * (mapping->end - mapping->begin) <= s->directory.next);
2264
            assert((mapping->info.dir.first_dir_index % (0x10 * s->sectors_per_cluster)) == 0);
2265
        }
2266
    }
2267
}
2268

    
2269
/* test, if all direntries have mappings */
2270
static void check2(BDRVVVFATState* s)
2271
{
2272
    int i;
2273
    int first_mapping = -1;
2274

    
2275
    for (i = 0; i < s->directory.next; i++) {
2276
        direntry_t* direntry = array_get(&(s->directory), i);
2277

    
2278
        if (is_short_name(direntry) && begin_of_direntry(direntry)) {
2279
            mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
2280
            assert(mapping);
2281
            assert(mapping->dir_index == i || is_dot(direntry));
2282
            assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry));
2283
        }
2284

    
2285
        if ((i % (0x10 * s->sectors_per_cluster)) == 0) {
2286
            /* cluster start */
2287
            int j, count = 0;
2288

    
2289
            for (j = 0; j < s->mapping.next; j++) {
2290
                mapping_t* mapping = array_get(&(s->mapping), j);
2291
                if (mapping->mode & MODE_DELETED)
2292
                    continue;
2293
                if (mapping->mode & MODE_DIRECTORY) {
2294
                    if (mapping->info.dir.first_dir_index <= i && mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster > i) {
2295
                        assert(++count == 1);
2296
                        if (mapping->first_mapping_index == -1)
2297
                            first_mapping = array_index(&(s->mapping), mapping);
2298
                        else
2299
                            assert(first_mapping == mapping->first_mapping_index);
2300
                        if (mapping->info.dir.parent_mapping_index < 0)
2301
                            assert(j == 0);
2302
                        else {
2303
                            mapping_t* parent = array_get(&(s->mapping), mapping->info.dir.parent_mapping_index);
2304
                            assert(parent->mode & MODE_DIRECTORY);
2305
                            assert(parent->info.dir.first_dir_index < mapping->info.dir.first_dir_index);
2306
                        }
2307
                    }
2308
                }
2309
            }
2310
            if (count == 0)
2311
                first_mapping = -1;
2312
        }
2313
    }
2314
}
2315
#endif
2316

    
2317
static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2318
{
2319
    int i;
2320

    
2321
#ifdef DEBUG
2322
    fprintf(stderr, "handle_renames\n");
2323
    for (i = 0; i < s->commits.next; i++) {
2324
        commit_t* commit = array_get(&(s->commits), i);
2325
        fprintf(stderr, "%d, %s (%d, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action);
2326
    }
2327
#endif
2328

    
2329
    for (i = 0; i < s->commits.next;) {
2330
        commit_t* commit = array_get(&(s->commits), i);
2331
        if (commit->action == ACTION_RENAME) {
2332
            mapping_t* mapping = find_mapping_for_cluster(s,
2333
                    commit->param.rename.cluster);
2334
            char* old_path = mapping->path;
2335

    
2336
            assert(commit->path);
2337
            mapping->path = commit->path;
2338
            if (rename(old_path, mapping->path))
2339
                return -2;
2340

    
2341
            if (mapping->mode & MODE_DIRECTORY) {
2342
                int l1 = strlen(mapping->path);
2343
                int l2 = strlen(old_path);
2344
                int diff = l1 - l2;
2345
                direntry_t* direntry = array_get(&(s->directory),
2346
                        mapping->info.dir.first_dir_index);
2347
                uint32_t c = mapping->begin;
2348
                int i = 0;
2349

    
2350
                /* recurse */
2351
                while (!fat_eof(s, c)) {
2352
                    do {
2353
                        direntry_t* d = direntry + i;
2354

    
2355
                        if (is_file(d) || (is_directory(d) && !is_dot(d))) {
2356
                            mapping_t* m = find_mapping_for_cluster(s,
2357
                                    begin_of_direntry(d));
2358
                            int l = strlen(m->path);
2359
                            char* new_path = g_malloc(l + diff + 1);
2360

    
2361
                            assert(!strncmp(m->path, mapping->path, l2));
2362

    
2363
                            pstrcpy(new_path, l + diff + 1, mapping->path);
2364
                            pstrcpy(new_path + l1, l + diff + 1 - l1,
2365
                                    m->path + l2);
2366

    
2367
                            schedule_rename(s, m->begin, new_path);
2368
                        }
2369
                        i++;
2370
                    } while((i % (0x10 * s->sectors_per_cluster)) != 0);
2371
                    c = fat_get(s, c);
2372
                }
2373
            }
2374

    
2375
            g_free(old_path);
2376
            array_remove(&(s->commits), i);
2377
            continue;
2378
        } else if (commit->action == ACTION_MKDIR) {
2379
            mapping_t* mapping;
2380
            int j, parent_path_len;
2381

    
2382
#ifdef __MINGW32__
2383
            if (mkdir(commit->path))
2384
                return -5;
2385
#else
2386
            if (mkdir(commit->path, 0755))
2387
                return -5;
2388
#endif
2389

    
2390
            mapping = insert_mapping(s, commit->param.mkdir.cluster,
2391
                    commit->param.mkdir.cluster + 1);
2392
            if (mapping == NULL)
2393
                return -6;
2394

    
2395
            mapping->mode = MODE_DIRECTORY;
2396
            mapping->read_only = 0;
2397
            mapping->path = commit->path;
2398
            j = s->directory.next;
2399
            assert(j);
2400
            insert_direntries(s, s->directory.next,
2401
                    0x10 * s->sectors_per_cluster);
2402
            mapping->info.dir.first_dir_index = j;
2403

    
2404
            parent_path_len = strlen(commit->path)
2405
                - strlen(get_basename(commit->path)) - 1;
2406
            for (j = 0; j < s->mapping.next; j++) {
2407
                mapping_t* m = array_get(&(s->mapping), j);
2408
                if (m->first_mapping_index < 0 && m != mapping &&
2409
                        !strncmp(m->path, mapping->path, parent_path_len) &&
2410
                        strlen(m->path) == parent_path_len)
2411
                    break;
2412
            }
2413
            assert(j < s->mapping.next);
2414
            mapping->info.dir.parent_mapping_index = j;
2415

    
2416
            array_remove(&(s->commits), i);
2417
            continue;
2418
        }
2419

    
2420
        i++;
2421
    }
2422
    return 0;
2423
}
2424

    
2425
/*
2426
 * TODO: make sure that the short name is not matching *another* file
2427
 */
2428
static int handle_commits(BDRVVVFATState* s)
2429
{
2430
    int i, fail = 0;
2431

    
2432
    vvfat_close_current_file(s);
2433

    
2434
    for (i = 0; !fail && i < s->commits.next; i++) {
2435
        commit_t* commit = array_get(&(s->commits), i);
2436
        switch(commit->action) {
2437
        case ACTION_RENAME: case ACTION_MKDIR:
2438
            abort();
2439
            fail = -2;
2440
            break;
2441
        case ACTION_WRITEOUT: {
2442
#ifndef NDEBUG
2443
            /* these variables are only used by assert() below */
2444
            direntry_t* entry = array_get(&(s->directory),
2445
                    commit->param.writeout.dir_index);
2446
            uint32_t begin = begin_of_direntry(entry);
2447
            mapping_t* mapping = find_mapping_for_cluster(s, begin);
2448
#endif
2449

    
2450
            assert(mapping);
2451
            assert(mapping->begin == begin);
2452
            assert(commit->path == NULL);
2453

    
2454
            if (commit_one_file(s, commit->param.writeout.dir_index,
2455
                        commit->param.writeout.modified_offset))
2456
                fail = -3;
2457

    
2458
            break;
2459
        }
2460
        case ACTION_NEW_FILE: {
2461
            int begin = commit->param.new_file.first_cluster;
2462
            mapping_t* mapping = find_mapping_for_cluster(s, begin);
2463
            direntry_t* entry;
2464
            int i;
2465

    
2466
            /* find direntry */
2467
            for (i = 0; i < s->directory.next; i++) {
2468
                entry = array_get(&(s->directory), i);
2469
                if (is_file(entry) && begin_of_direntry(entry) == begin)
2470
                    break;
2471
            }
2472

    
2473
            if (i >= s->directory.next) {
2474
                fail = -6;
2475
                continue;
2476
            }
2477

    
2478
            /* make sure there exists an initial mapping */
2479
            if (mapping && mapping->begin != begin) {
2480
                mapping->end = begin;
2481
                mapping = NULL;
2482
            }
2483
            if (mapping == NULL) {
2484
                mapping = insert_mapping(s, begin, begin+1);
2485
            }
2486
            /* most members will be fixed in commit_mappings() */
2487
            assert(commit->path);
2488
            mapping->path = commit->path;
2489
            mapping->read_only = 0;
2490
            mapping->mode = MODE_NORMAL;
2491
            mapping->info.file.offset = 0;
2492

    
2493
            if (commit_one_file(s, i, 0))
2494
                fail = -7;
2495

    
2496
            break;
2497
        }
2498
        default:
2499
            abort();
2500
        }
2501
    }
2502
    if (i > 0 && array_remove_slice(&(s->commits), 0, i))
2503
        return -1;
2504
    return fail;
2505
}
2506

    
2507
static int handle_deletes(BDRVVVFATState* s)
2508
{
2509
    int i, deferred = 1, deleted = 1;
2510

    
2511
    /* delete files corresponding to mappings marked as deleted */
2512
    /* handle DELETEs and unused mappings (modified_fat_get(s, mapping->begin) == 0) */
2513
    while (deferred && deleted) {
2514
        deferred = 0;
2515
        deleted = 0;
2516

    
2517
        for (i = 1; i < s->mapping.next; i++) {
2518
            mapping_t* mapping = array_get(&(s->mapping), i);
2519
            if (mapping->mode & MODE_DELETED) {
2520
                direntry_t* entry = array_get(&(s->directory),
2521
                        mapping->dir_index);
2522

    
2523
                if (is_free(entry)) {
2524
                    /* remove file/directory */
2525
                    if (mapping->mode & MODE_DIRECTORY) {
2526
                        int j, next_dir_index = s->directory.next,
2527
                        first_dir_index = mapping->info.dir.first_dir_index;
2528

    
2529
                        if (rmdir(mapping->path) < 0) {
2530
                            if (errno == ENOTEMPTY) {
2531
                                deferred++;
2532
                                continue;
2533
                            } else
2534
                                return -5;
2535
                        }
2536

    
2537
                        for (j = 1; j < s->mapping.next; j++) {
2538
                            mapping_t* m = array_get(&(s->mapping), j);
2539
                            if (m->mode & MODE_DIRECTORY &&
2540
                                    m->info.dir.first_dir_index >
2541
                                    first_dir_index &&
2542
                                    m->info.dir.first_dir_index <
2543
                                    next_dir_index)
2544
                                next_dir_index =
2545
                                    m->info.dir.first_dir_index;
2546
                        }
2547
                        remove_direntries(s, first_dir_index,
2548
                                next_dir_index - first_dir_index);
2549

    
2550
                        deleted++;
2551
                    }
2552
                } else {
2553
                    if (unlink(mapping->path))
2554
                        return -4;
2555
                    deleted++;
2556
                }
2557
                DLOG(fprintf(stderr, "DELETE (%d)\n", i); print_mapping(mapping); print_direntry(entry));
2558
                remove_mapping(s, i);
2559
            }
2560
        }
2561
    }
2562

    
2563
    return 0;
2564
}
2565

    
2566
/*
2567
 * synchronize mapping with new state:
2568
 *
2569
 * - copy FAT (with bdrv_read)
2570
 * - mark all filenames corresponding to mappings as deleted
2571
 * - recurse direntries from root (using bs->bdrv_read)
2572
 * - delete files corresponding to mappings marked as deleted
2573
 */
2574
static int do_commit(BDRVVVFATState* s)
2575
{
2576
    int ret = 0;
2577

    
2578
    /* the real meat are the commits. Nothing to do? Move along! */
2579
    if (s->commits.next == 0)
2580
        return 0;
2581

    
2582
    vvfat_close_current_file(s);
2583

    
2584
    ret = handle_renames_and_mkdirs(s);
2585
    if (ret) {
2586
        fprintf(stderr, "Error handling renames (%d)\n", ret);
2587
        abort();
2588
        return ret;
2589
    }
2590

    
2591
    /* copy FAT (with bdrv_read) */
2592
    memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
2593

    
2594
    /* recurse direntries from root (using bs->bdrv_read) */
2595
    ret = commit_direntries(s, 0, -1);
2596
    if (ret) {
2597
        fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
2598
        abort();
2599
        return ret;
2600
    }
2601

    
2602
    ret = handle_commits(s);
2603
    if (ret) {
2604
        fprintf(stderr, "Error handling commits (%d)\n", ret);
2605
        abort();
2606
        return ret;
2607
    }
2608

    
2609
    ret = handle_deletes(s);
2610
    if (ret) {
2611
        fprintf(stderr, "Error deleting\n");
2612
        abort();
2613
        return ret;
2614
    }
2615

    
2616
    s->qcow->drv->bdrv_make_empty(s->qcow);
2617

    
2618
    memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
2619

    
2620
DLOG(checkpoint());
2621
    return 0;
2622
}
2623

    
2624
static int try_commit(BDRVVVFATState* s)
2625
{
2626
    vvfat_close_current_file(s);
2627
DLOG(checkpoint());
2628
    if(!is_consistent(s))
2629
        return -1;
2630
    return do_commit(s);
2631
}
2632

    
2633
static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
2634
                    const uint8_t *buf, int nb_sectors)
2635
{
2636
    BDRVVVFATState *s = bs->opaque;
2637
    int i, ret;
2638

    
2639
DLOG(checkpoint());
2640

    
2641
    /* Check if we're operating in read-only mode */
2642
    if (s->qcow == NULL) {
2643
        return -EACCES;
2644
    }
2645

    
2646
    vvfat_close_current_file(s);
2647

    
2648
    /*
2649
     * Some sanity checks:
2650
     * - do not allow writing to the boot sector
2651
     * - do not allow to write non-ASCII filenames
2652
     */
2653

    
2654
    if (sector_num < s->first_sectors_number)
2655
        return -1;
2656

    
2657
    for (i = sector2cluster(s, sector_num);
2658
            i <= sector2cluster(s, sector_num + nb_sectors - 1);) {
2659
        mapping_t* mapping = find_mapping_for_cluster(s, i);
2660
        if (mapping) {
2661
            if (mapping->read_only) {
2662
                fprintf(stderr, "Tried to write to write-protected file %s\n",
2663
                        mapping->path);
2664
                return -1;
2665
            }
2666

    
2667
            if (mapping->mode & MODE_DIRECTORY) {
2668
                int begin = cluster2sector(s, i);
2669
                int end = begin + s->sectors_per_cluster, k;
2670
                int dir_index;
2671
                const direntry_t* direntries;
2672
                long_file_name lfn;
2673

    
2674
                lfn_init(&lfn);
2675

    
2676
                if (begin < sector_num)
2677
                    begin = sector_num;
2678
                if (end > sector_num + nb_sectors)
2679
                    end = sector_num + nb_sectors;
2680
                dir_index  = mapping->dir_index +
2681
                    0x10 * (begin - mapping->begin * s->sectors_per_cluster);
2682
                direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
2683

    
2684
                for (k = 0; k < (end - begin) * 0x10; k++) {
2685
                    /* do not allow non-ASCII filenames */
2686
                    if (parse_long_name(&lfn, direntries + k) < 0) {
2687
                        fprintf(stderr, "Warning: non-ASCII filename\n");
2688
                        return -1;
2689
                    }
2690
                    /* no access to the direntry of a read-only file */
2691
                    else if (is_short_name(direntries+k) &&
2692
                            (direntries[k].attributes & 1)) {
2693
                        if (memcmp(direntries + k,
2694
                                    array_get(&(s->directory), dir_index + k),
2695
                                    sizeof(direntry_t))) {
2696
                            fprintf(stderr, "Warning: tried to write to write-protected file\n");
2697
                            return -1;
2698
                        }
2699
                    }
2700
                }
2701
            }
2702
            i = mapping->end;
2703
        } else
2704
            i++;
2705
    }
2706

    
2707
    /*
2708
     * Use qcow backend. Commit later.
2709
     */
2710
DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
2711
    ret = s->qcow->drv->bdrv_write(s->qcow, sector_num, buf, nb_sectors);
2712
    if (ret < 0) {
2713
        fprintf(stderr, "Error writing to qcow backend\n");
2714
        return ret;
2715
    }
2716

    
2717
    for (i = sector2cluster(s, sector_num);
2718
            i <= sector2cluster(s, sector_num + nb_sectors - 1); i++)
2719
        if (i >= 0)
2720
            s->used_clusters[i] |= USED_ALLOCATED;
2721

    
2722
DLOG(checkpoint());
2723
    /* TODO: add timeout */
2724
    try_commit(s);
2725

    
2726
DLOG(checkpoint());
2727
    return 0;
2728
}
2729

    
2730
static coroutine_fn int vvfat_co_write(BlockDriverState *bs, int64_t sector_num,
2731
                                       const uint8_t *buf, int nb_sectors)
2732
{
2733
    int ret;
2734
    BDRVVVFATState *s = bs->opaque;
2735
    qemu_co_mutex_lock(&s->lock);
2736
    ret = vvfat_write(bs, sector_num, buf, nb_sectors);
2737
    qemu_co_mutex_unlock(&s->lock);
2738
    return ret;
2739
}
2740

    
2741
static int vvfat_is_allocated(BlockDriverState *bs,
2742
        int64_t sector_num, int nb_sectors, int* n)
2743
{
2744
    BDRVVVFATState* s = bs->opaque;
2745
    *n = s->sector_count - sector_num;
2746
    if (*n > nb_sectors)
2747
        *n = nb_sectors;
2748
    else if (*n < 0)
2749
        return 0;
2750
    return 1;
2751
}
2752

    
2753
static int write_target_commit(BlockDriverState *bs, int64_t sector_num,
2754
        const uint8_t* buffer, int nb_sectors) {
2755
    BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
2756
    return try_commit(s);
2757
}
2758

    
2759
static void write_target_close(BlockDriverState *bs) {
2760
    BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
2761
    bdrv_delete(s->qcow);
2762
    g_free(s->qcow_filename);
2763
}
2764

    
2765
static BlockDriver vvfat_write_target = {
2766
    .format_name        = "vvfat_write_target",
2767
    .bdrv_write         = write_target_commit,
2768
    .bdrv_close         = write_target_close,
2769
};
2770

    
2771
static int enable_write_target(BDRVVVFATState *s)
2772
{
2773
    BlockDriver *bdrv_qcow;
2774
    QEMUOptionParameter *options;
2775
    int ret;
2776
    int size = sector2cluster(s, s->sector_count);
2777
    s->used_clusters = calloc(size, 1);
2778

    
2779
    array_init(&(s->commits), sizeof(commit_t));
2780

    
2781
    s->qcow_filename = g_malloc(1024);
2782
    get_tmp_filename(s->qcow_filename, 1024);
2783

    
2784
    bdrv_qcow = bdrv_find_format("qcow");
2785
    options = parse_option_parameters("", bdrv_qcow->create_options, NULL);
2786
    set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512);
2787
    set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:");
2788

    
2789
    if (bdrv_create(bdrv_qcow, s->qcow_filename, options) < 0)
2790
        return -1;
2791

    
2792
    s->qcow = bdrv_new("");
2793
    if (s->qcow == NULL) {
2794
        return -1;
2795
    }
2796

    
2797
    ret = bdrv_open(s->qcow, s->qcow_filename,
2798
            BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, bdrv_qcow);
2799
    if (ret < 0) {
2800
        return ret;
2801
    }
2802

    
2803
#ifndef _WIN32
2804
    unlink(s->qcow_filename);
2805
#endif
2806

    
2807
    s->bs->backing_hd = calloc(sizeof(BlockDriverState), 1);
2808
    s->bs->backing_hd->drv = &vvfat_write_target;
2809
    s->bs->backing_hd->opaque = g_malloc(sizeof(void*));
2810
    *(void**)s->bs->backing_hd->opaque = s;
2811

    
2812
    return 0;
2813
}
2814

    
2815
static void vvfat_close(BlockDriverState *bs)
2816
{
2817
    BDRVVVFATState *s = bs->opaque;
2818

    
2819
    vvfat_close_current_file(s);
2820
    array_free(&(s->fat));
2821
    array_free(&(s->directory));
2822
    array_free(&(s->mapping));
2823
    g_free(s->cluster_buffer);
2824
}
2825

    
2826
static BlockDriver bdrv_vvfat = {
2827
    .format_name        = "vvfat",
2828
    .instance_size        = sizeof(BDRVVVFATState),
2829
    .bdrv_file_open        = vvfat_open,
2830
    .bdrv_read          = vvfat_co_read,
2831
    .bdrv_write         = vvfat_co_write,
2832
    .bdrv_close                = vvfat_close,
2833
    .bdrv_is_allocated        = vvfat_is_allocated,
2834
    .protocol_name        = "fat",
2835
};
2836

    
2837
static void bdrv_vvfat_init(void)
2838
{
2839
    bdrv_register(&bdrv_vvfat);
2840
}
2841

    
2842
block_init(bdrv_vvfat_init);
2843

    
2844
#ifdef DEBUG
2845
static void checkpoint(void) {
2846
    assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2);
2847
    check1(vvv);
2848
    check2(vvv);
2849
    assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY));
2850
#if 0
2851
    if (((direntry_t*)vvv->directory.pointer)[1].attributes != 0xf)
2852
        fprintf(stderr, "Nonono!\n");
2853
    mapping_t* mapping;
2854
    direntry_t* direntry;
2855
    assert(vvv->mapping.size >= vvv->mapping.item_size * vvv->mapping.next);
2856
    assert(vvv->directory.size >= vvv->directory.item_size * vvv->directory.next);
2857
    if (vvv->mapping.next<47)
2858
        return;
2859
    assert((mapping = array_get(&(vvv->mapping), 47)));
2860
    assert(mapping->dir_index < vvv->directory.next);
2861
    direntry = array_get(&(vvv->directory), mapping->dir_index);
2862
    assert(!memcmp(direntry->name, "USB     H  ", 11) || direntry->name[0]==0);
2863
#endif
2864
}
2865
#endif