Statistics
| Branch: | Revision:

root / block / vvfat.c @ 273e4e03

History | View | Annotate | Download (80.3 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
        s->directory.next = ROOT_ENTRIES;
803
        memset(array_get(&(s->directory), cur), 0,
804
                (ROOT_ENTRIES - cur) * sizeof(direntry_t));
805
    }
806

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

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

    
816
    return 0;
817
}
818

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
941
    s->current_mapping = NULL;
942

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

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

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

    
972
    return 0;
973
}
974

    
975
#ifdef DEBUG
976
static BDRVVVFATState *vvv = NULL;
977
#endif
978

    
979
static int enable_write_target(BDRVVVFATState *s);
980
static int is_consistent(BDRVVVFATState *s);
981

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

    
987
#ifdef DEBUG
988
    vvv = s;
989
#endif
990

    
991
DLOG(if (stderr == NULL) {
992
    stderr = fopen("vvfat.log", "a");
993
    setbuf(stderr, NULL);
994
})
995

    
996
    s->bs = bs;
997

    
998
    /* LATER TODO: if FAT32, adjust */
999
    s->sectors_per_cluster=0x10;
1000

    
1001
    s->current_cluster=0xffffffff;
1002

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

    
1011
    if (!strstart(dirname, "fat:", NULL))
1012
        return -1;
1013

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

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

    
1044
    s->sector_count=bs->cyls*bs->heads*bs->secs-(s->first_sectors_number-1);
1045

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

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

    
1060
    bs->total_sectors=bs->cyls*bs->heads*bs->secs;
1061

    
1062
    if(init_directories(s, dirname))
1063
        return -1;
1064

    
1065
    s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
1066

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

    
1074
    //    assert(is_consistent(s));
1075
    qemu_co_mutex_init(&s->lock);
1076
    return 0;
1077
}
1078

    
1079
static inline void vvfat_close_current_file(BDRVVVFATState *s)
1080
{
1081
    if(s->current_mapping) {
1082
        s->current_mapping = NULL;
1083
        if (s->current_fd) {
1084
                close(s->current_fd);
1085
                s->current_fd = 0;
1086
        }
1087
    }
1088
    s->current_cluster = -1;
1089
}
1090

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

    
1121
static inline mapping_t* find_mapping_for_cluster(BDRVVVFATState* s,int cluster_num)
1122
{
1123
    int index=find_mapping_for_cluster_aux(s,cluster_num,0,s->mapping.next);
1124
    mapping_t* mapping;
1125
    if(index>=s->mapping.next)
1126
        return NULL;
1127
    mapping=array_get(&(s->mapping),index);
1128
    if(mapping->begin>cluster_num)
1129
        return NULL;
1130
    assert(mapping->begin<=cluster_num && mapping->end>cluster_num);
1131
    return mapping;
1132
}
1133

    
1134
static int open_file(BDRVVVFATState* s,mapping_t* mapping)
1135
{
1136
    if(!mapping)
1137
        return -1;
1138
    if(!s->current_mapping ||
1139
            strcmp(s->current_mapping->path,mapping->path)) {
1140
        /* open file */
1141
        int fd = open(mapping->path, O_RDONLY | O_BINARY | O_LARGEFILE);
1142
        if(fd<0)
1143
            return -1;
1144
        vvfat_close_current_file(s);
1145
        s->current_fd = fd;
1146
        s->current_mapping = mapping;
1147
    }
1148
    return 0;
1149
}
1150

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

    
1163
            assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
1164

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

    
1178
            if(open_file(s,mapping))
1179
                return -2;
1180
        } else if (s->current_mapping->mode & MODE_DIRECTORY)
1181
            goto read_cluster_directory;
1182

    
1183
        assert(s->current_fd);
1184

    
1185
        offset=s->cluster_size*(cluster_num-s->current_mapping->begin)+s->current_mapping->info.file.offset;
1186
        if(lseek(s->current_fd, offset, SEEK_SET)!=offset)
1187
            return -3;
1188
        s->cluster=s->cluster_buffer;
1189
        result=read(s->current_fd,s->cluster,s->cluster_size);
1190
        if(result<0) {
1191
            s->current_cluster = -1;
1192
            return -1;
1193
        }
1194
        s->current_cluster = cluster_num;
1195
    }
1196
    return 0;
1197
}
1198

    
1199
#ifdef DEBUG
1200
static void print_direntry(const direntry_t* direntry)
1201
{
1202
    int j = 0;
1203
    char buffer[1024];
1204

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

    
1232
static void print_mapping(const mapping_t* mapping)
1233
{
1234
    fprintf(stderr, "mapping (%p): begin, end = %d, %d, dir_index = %d, "
1235
        "first_mapping_index = %d, name = %s, mode = 0x%x, " ,
1236
        mapping, mapping->begin, mapping->end, mapping->dir_index,
1237
        mapping->first_mapping_index, mapping->path, mapping->mode);
1238

    
1239
    if (mapping->mode & MODE_DIRECTORY)
1240
        fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
1241
    else
1242
        fprintf(stderr, "offset = %d\n", mapping->info.file.offset);
1243
}
1244
#endif
1245

    
1246
static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
1247
                    uint8_t *buf, int nb_sectors)
1248
{
1249
    BDRVVVFATState *s = bs->opaque;
1250
    int i;
1251

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

    
1290
static coroutine_fn int vvfat_co_read(BlockDriverState *bs, int64_t sector_num,
1291
                                      uint8_t *buf, int nb_sectors)
1292
{
1293
    int ret;
1294
    BDRVVVFATState *s = bs->opaque;
1295
    qemu_co_mutex_lock(&s->lock);
1296
    ret = vvfat_read(bs, sector_num, buf, nb_sectors);
1297
    qemu_co_mutex_unlock(&s->lock);
1298
    return ret;
1299
}
1300

    
1301
/* LATER TODO: statify all functions */
1302

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

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

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

    
1353
static void schedule_rename(BDRVVVFATState* s,
1354
        uint32_t cluster, char* new_path)
1355
{
1356
    commit_t* commit = array_get_next(&(s->commits));
1357
    commit->path = new_path;
1358
    commit->param.rename.cluster = cluster;
1359
    commit->action = ACTION_RENAME;
1360
}
1361

    
1362
static void schedule_writeout(BDRVVVFATState* s,
1363
        int dir_index, uint32_t modified_offset)
1364
{
1365
    commit_t* commit = array_get_next(&(s->commits));
1366
    commit->path = NULL;
1367
    commit->param.writeout.dir_index = dir_index;
1368
    commit->param.writeout.modified_offset = modified_offset;
1369
    commit->action = ACTION_WRITEOUT;
1370
}
1371

    
1372
static void schedule_new_file(BDRVVVFATState* s,
1373
        char* path, uint32_t first_cluster)
1374
{
1375
    commit_t* commit = array_get_next(&(s->commits));
1376
    commit->path = path;
1377
    commit->param.new_file.first_cluster = first_cluster;
1378
    commit->action = ACTION_NEW_FILE;
1379
}
1380

    
1381
static void schedule_mkdir(BDRVVVFATState* s, uint32_t cluster, char* path)
1382
{
1383
    commit_t* commit = array_get_next(&(s->commits));
1384
    commit->path = path;
1385
    commit->param.mkdir.cluster = cluster;
1386
    commit->action = ACTION_MKDIR;
1387
}
1388

    
1389
typedef struct {
1390
    /*
1391
     * Since the sequence number is at most 0x3f, and the filename
1392
     * length is at most 13 times the sequence number, the maximal
1393
     * filename length is 0x3f * 13 bytes.
1394
     */
1395
    unsigned char name[0x3f * 13 + 1];
1396
    int checksum, len;
1397
    int sequence_number;
1398
} long_file_name;
1399

    
1400
static void lfn_init(long_file_name* lfn)
1401
{
1402
   lfn->sequence_number = lfn->len = 0;
1403
   lfn->checksum = 0x100;
1404
}
1405

    
1406
/* return 0 if parsed successfully, > 0 if no long name, < 0 if error */
1407
static int parse_long_name(long_file_name* lfn,
1408
        const direntry_t* direntry)
1409
{
1410
    int i, j, offset;
1411
    const unsigned char* pointer = (const unsigned char*)direntry;
1412

    
1413
    if (!is_long_name(direntry))
1414
        return 1;
1415

    
1416
    if (pointer[0] & 0x40) {
1417
        lfn->sequence_number = pointer[0] & 0x3f;
1418
        lfn->checksum = pointer[13];
1419
        lfn->name[0] = 0;
1420
        lfn->name[lfn->sequence_number * 13] = 0;
1421
    } else if ((pointer[0] & 0x3f) != --lfn->sequence_number)
1422
        return -1;
1423
    else if (pointer[13] != lfn->checksum)
1424
        return -2;
1425
    else if (pointer[12] || pointer[26] || pointer[27])
1426
        return -3;
1427

    
1428
    offset = 13 * (lfn->sequence_number - 1);
1429
    for (i = 0, j = 1; i < 13; i++, j+=2) {
1430
        if (j == 11)
1431
            j = 14;
1432
        else if (j == 26)
1433
            j = 28;
1434

    
1435
        if (pointer[j+1] == 0)
1436
            lfn->name[offset + i] = pointer[j];
1437
        else if (pointer[j+1] != 0xff || (pointer[0] & 0x40) == 0)
1438
            return -4;
1439
        else
1440
            lfn->name[offset + i] = 0;
1441
    }
1442

    
1443
    if (pointer[0] & 0x40)
1444
        lfn->len = offset + strlen((char*)lfn->name + offset);
1445

    
1446
    return 0;
1447
}
1448

    
1449
/* returns 0 if successful, >0 if no short_name, and <0 on error */
1450
static int parse_short_name(BDRVVVFATState* s,
1451
        long_file_name* lfn, direntry_t* direntry)
1452
{
1453
    int i, j;
1454

    
1455
    if (!is_short_name(direntry))
1456
        return 1;
1457

    
1458
    for (j = 7; j >= 0 && direntry->name[j] == ' '; j--);
1459
    for (i = 0; i <= j; i++) {
1460
        if (direntry->name[i] <= ' ' || direntry->name[i] > 0x7f)
1461
            return -1;
1462
        else if (s->downcase_short_names)
1463
            lfn->name[i] = qemu_tolower(direntry->name[i]);
1464
        else
1465
            lfn->name[i] = direntry->name[i];
1466
    }
1467

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

    
1483
    lfn->len = strlen((char*)lfn->name);
1484

    
1485
    return 0;
1486
}
1487

    
1488
static inline uint32_t modified_fat_get(BDRVVVFATState* s,
1489
        unsigned int cluster)
1490
{
1491
    if (cluster < s->last_cluster_of_root_directory) {
1492
        if (cluster + 1 == s->last_cluster_of_root_directory)
1493
            return s->max_fat_value;
1494
        else
1495
            return cluster + 1;
1496
    }
1497

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

    
1510
static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num)
1511
{
1512
    int was_modified = 0;
1513
    int i, dummy;
1514

    
1515
    if (s->qcow == NULL)
1516
        return 0;
1517

    
1518
    for (i = 0; !was_modified && i < s->sectors_per_cluster; i++)
1519
        was_modified = s->qcow->drv->bdrv_is_allocated(s->qcow,
1520
                cluster2sector(s, cluster_num) + i, 1, &dummy);
1521

    
1522
    return was_modified;
1523
}
1524

    
1525
static const char* get_basename(const char* path)
1526
{
1527
    char* basename = strrchr(path, '/');
1528
    if (basename == NULL)
1529
        return path;
1530
    else
1531
        return basename + 1; /* strip '/' */
1532
}
1533

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

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

    
1579
    uint32_t cluster_num = begin_of_direntry(direntry);
1580
    uint32_t offset = 0;
1581
    int first_mapping_index = -1;
1582
    mapping_t* mapping = NULL;
1583
    const char* basename2 = NULL;
1584

    
1585
    vvfat_close_current_file(s);
1586

    
1587
    /* the root directory */
1588
    if (cluster_num == 0)
1589
        return 0;
1590

    
1591
    /* write support */
1592
    if (s->qcow) {
1593
        basename2 = get_basename(path);
1594

    
1595
        mapping = find_mapping_for_cluster(s, cluster_num);
1596

    
1597
        if (mapping) {
1598
            const char* basename;
1599

    
1600
            assert(mapping->mode & MODE_DELETED);
1601
            mapping->mode &= ~MODE_DELETED;
1602

    
1603
            basename = get_basename(mapping->path);
1604

    
1605
            assert(mapping->mode & MODE_NORMAL);
1606

    
1607
            /* rename */
1608
            if (strcmp(basename, basename2))
1609
                schedule_rename(s, cluster_num, g_strdup(path));
1610
        } else if (is_file(direntry))
1611
            /* new file */
1612
            schedule_new_file(s, g_strdup(path), cluster_num);
1613
        else {
1614
            abort();
1615
            return 0;
1616
        }
1617
    }
1618

    
1619
    while(1) {
1620
        if (s->qcow) {
1621
            if (!copy_it && cluster_was_modified(s, cluster_num)) {
1622
                if (mapping == NULL ||
1623
                        mapping->begin > cluster_num ||
1624
                        mapping->end <= cluster_num)
1625
                mapping = find_mapping_for_cluster(s, cluster_num);
1626

    
1627

    
1628
                if (mapping &&
1629
                        (mapping->mode & MODE_DIRECTORY) == 0) {
1630

    
1631
                    /* was modified in qcow */
1632
                    if (offset != mapping->info.file.offset + s->cluster_size
1633
                            * (cluster_num - mapping->begin)) {
1634
                        /* offset of this cluster in file chain has changed */
1635
                        abort();
1636
                        copy_it = 1;
1637
                    } else if (offset == 0) {
1638
                        const char* basename = get_basename(mapping->path);
1639

    
1640
                        if (strcmp(basename, basename2))
1641
                            copy_it = 1;
1642
                        first_mapping_index = array_index(&(s->mapping), mapping);
1643
                    }
1644

    
1645
                    if (mapping->first_mapping_index != first_mapping_index
1646
                            && mapping->info.file.offset > 0) {
1647
                        abort();
1648
                        copy_it = 1;
1649
                    }
1650

    
1651
                    /* need to write out? */
1652
                    if (!was_modified && is_file(direntry)) {
1653
                        was_modified = 1;
1654
                        schedule_writeout(s, mapping->dir_index, offset);
1655
                    }
1656
                }
1657
            }
1658

    
1659
            if (copy_it) {
1660
                int i, dummy;
1661
                /*
1662
                 * This is horribly inefficient, but that is okay, since
1663
                 * it is rarely executed, if at all.
1664
                 */
1665
                int64_t offset = cluster2sector(s, cluster_num);
1666

    
1667
                vvfat_close_current_file(s);
1668
                for (i = 0; i < s->sectors_per_cluster; i++)
1669
                    if (!s->qcow->drv->bdrv_is_allocated(s->qcow,
1670
                                offset + i, 1, &dummy)) {
1671
                        if (vvfat_read(s->bs,
1672
                                    offset, s->cluster_buffer, 1))
1673
                            return -1;
1674
                        if (s->qcow->drv->bdrv_write(s->qcow,
1675
                                    offset, s->cluster_buffer, 1))
1676
                            return -2;
1677
                    }
1678
            }
1679
        }
1680

    
1681
        ret++;
1682
        if (s->used_clusters[cluster_num] & USED_ANY)
1683
            return 0;
1684
        s->used_clusters[cluster_num] = USED_FILE;
1685

    
1686
        cluster_num = modified_fat_get(s, cluster_num);
1687

    
1688
        if (fat_eof(s, cluster_num))
1689
            return ret;
1690
        else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
1691
            return -1;
1692

    
1693
        offset += s->cluster_size;
1694
    }
1695
}
1696

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

    
1710
    long_file_name lfn;
1711
    int path_len = strlen(path);
1712
    char path2[PATH_MAX + 1];
1713

    
1714
    assert(path_len < PATH_MAX); /* len was tested before! */
1715
    pstrcpy(path2, sizeof(path2), path);
1716
    path2[path_len] = '/';
1717
    path2[path_len + 1] = '\0';
1718

    
1719
    if (mapping) {
1720
        const char* basename = get_basename(mapping->path);
1721
        const char* basename2 = get_basename(path);
1722

    
1723
        assert(mapping->mode & MODE_DIRECTORY);
1724

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

    
1728
        if (strcmp(basename, basename2))
1729
            schedule_rename(s, cluster_num, g_strdup(path));
1730
    } else
1731
        /* new directory */
1732
        schedule_mkdir(s, cluster_num, g_strdup(path));
1733

    
1734
    lfn_init(&lfn);
1735
    do {
1736
        int i;
1737
        int subret = 0;
1738

    
1739
        ret++;
1740

    
1741
        if (s->used_clusters[cluster_num] & USED_ANY) {
1742
            fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
1743
            return 0;
1744
        }
1745
        s->used_clusters[cluster_num] = USED_DIRECTORY;
1746

    
1747
DLOG(fprintf(stderr, "read cluster %d (sector %d)\n", (int)cluster_num, (int)cluster2sector(s, cluster_num)));
1748
        subret = vvfat_read(s->bs, cluster2sector(s, cluster_num), cluster,
1749
                s->sectors_per_cluster);
1750
        if (subret) {
1751
            fprintf(stderr, "Error fetching direntries\n");
1752
        fail:
1753
            g_free(cluster);
1754
            return 0;
1755
        }
1756

    
1757
        for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
1758
            int cluster_count = 0;
1759

    
1760
DLOG(fprintf(stderr, "check direntry %d:\n", i); print_direntry(direntries + i));
1761
            if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
1762
                    is_free(direntries + i))
1763
                continue;
1764

    
1765
            subret = parse_long_name(&lfn, direntries + i);
1766
            if (subret < 0) {
1767
                fprintf(stderr, "Error in long name\n");
1768
                goto fail;
1769
            }
1770
            if (subret == 0 || is_free(direntries + i))
1771
                continue;
1772

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

    
1785
            if (path_len + 1 + lfn.len >= PATH_MAX) {
1786
                fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
1787
                goto fail;
1788
            }
1789
            pstrcpy(path2 + path_len + 1, sizeof(path2) - path_len - 1,
1790
                    (char*)lfn.name);
1791

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

    
1815
            ret += cluster_count;
1816
        }
1817

    
1818
        cluster_num = modified_fat_get(s, cluster_num);
1819
    } while(!fat_eof(s, cluster_num));
1820

    
1821
    g_free(cluster);
1822
    return ret;
1823
}
1824

    
1825
/* returns 1 on success */
1826
static int is_consistent(BDRVVVFATState* s)
1827
{
1828
    int i, check;
1829
    int used_clusters_count = 0;
1830

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

    
1860
    clear_commits(s);
1861

    
1862
    /* mark every mapped file/directory as deleted.
1863
     * (check_directory_consistency() will unmark those still present). */
1864
    if (s->qcow)
1865
        for (i = 0; i < s->mapping.next; i++) {
1866
            mapping_t* mapping = array_get(&(s->mapping), i);
1867
            if (mapping->first_mapping_index < 0)
1868
                mapping->mode |= MODE_DELETED;
1869
        }
1870

    
1871
    used_clusters_count = check_directory_consistency(s, 0, s->path);
1872
    if (used_clusters_count <= 0) {
1873
        DLOG(fprintf(stderr, "problem in directory\n"));
1874
        return 0;
1875
    }
1876

    
1877
    check = s->last_cluster_of_root_directory;
1878
    for (i = check; i < sector2cluster(s, s->sector_count); i++) {
1879
        if (modified_fat_get(s, i)) {
1880
            if(!s->used_clusters[i]) {
1881
                DLOG(fprintf(stderr, "FAT was modified (%d), but cluster is not used?\n", i));
1882
                return 0;
1883
            }
1884
            check++;
1885
        }
1886

    
1887
        if (s->used_clusters[i] == USED_ALLOCATED) {
1888
            /* allocated, but not used... */
1889
            DLOG(fprintf(stderr, "unused, modified cluster: %d\n", i));
1890
            return 0;
1891
        }
1892
    }
1893

    
1894
    if (check != used_clusters_count)
1895
        return 0;
1896

    
1897
    return used_clusters_count;
1898
}
1899

    
1900
static inline void adjust_mapping_indices(BDRVVVFATState* s,
1901
        int offset, int adjust)
1902
{
1903
    int i;
1904

    
1905
    for (i = 0; i < s->mapping.next; i++) {
1906
        mapping_t* mapping = array_get(&(s->mapping), i);
1907

    
1908
#define ADJUST_MAPPING_INDEX(name) \
1909
        if (mapping->name >= offset) \
1910
            mapping->name += adjust
1911

    
1912
        ADJUST_MAPPING_INDEX(first_mapping_index);
1913
        if (mapping->mode & MODE_DIRECTORY)
1914
            ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
1915
    }
1916
}
1917

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

    
1933
    if (index < s->mapping.next && (mapping = array_get(&(s->mapping), index))
1934
            && mapping->begin < begin) {
1935
        mapping->end = begin;
1936
        index++;
1937
        mapping = array_get(&(s->mapping), index);
1938
    }
1939
    if (index >= s->mapping.next || mapping->begin > begin) {
1940
        mapping = array_insert(&(s->mapping), index, 1);
1941
        mapping->path = NULL;
1942
        adjust_mapping_indices(s, index, +1);
1943
    }
1944

    
1945
    mapping->begin = begin;
1946
    mapping->end = end;
1947

    
1948
DLOG(mapping_t* next_mapping;
1949
assert(index + 1 >= s->mapping.next ||
1950
((next_mapping = array_get(&(s->mapping), index + 1)) &&
1951
 next_mapping->begin >= end)));
1952

    
1953
    if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1954
        s->current_mapping = array_get(&(s->mapping),
1955
                s->current_mapping - first_mapping);
1956

    
1957
    return mapping;
1958
}
1959

    
1960
static int remove_mapping(BDRVVVFATState* s, int mapping_index)
1961
{
1962
    mapping_t* mapping = array_get(&(s->mapping), mapping_index);
1963
    mapping_t* first_mapping = array_get(&(s->mapping), 0);
1964

    
1965
    /* free mapping */
1966
    if (mapping->first_mapping_index < 0) {
1967
        g_free(mapping->path);
1968
    }
1969

    
1970
    /* remove from s->mapping */
1971
    array_remove(&(s->mapping), mapping_index);
1972

    
1973
    /* adjust all references to mappings */
1974
    adjust_mapping_indices(s, mapping_index, -1);
1975

    
1976
    if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1977
        s->current_mapping = array_get(&(s->mapping),
1978
                s->current_mapping - first_mapping);
1979

    
1980
    return 0;
1981
}
1982

    
1983
static void adjust_dirindices(BDRVVVFATState* s, int offset, int adjust)
1984
{
1985
    int i;
1986
    for (i = 0; i < s->mapping.next; i++) {
1987
        mapping_t* mapping = array_get(&(s->mapping), i);
1988
        if (mapping->dir_index >= offset)
1989
            mapping->dir_index += adjust;
1990
        if ((mapping->mode & MODE_DIRECTORY) &&
1991
                mapping->info.dir.first_dir_index >= offset)
1992
            mapping->info.dir.first_dir_index += adjust;
1993
    }
1994
}
1995

    
1996
static direntry_t* insert_direntries(BDRVVVFATState* s,
1997
        int dir_index, int count)
1998
{
1999
    /*
2000
     * make room in s->directory,
2001
     * adjust_dirindices
2002
     */
2003
    direntry_t* result = array_insert(&(s->directory), dir_index, count);
2004
    if (result == NULL)
2005
        return NULL;
2006
    adjust_dirindices(s, dir_index, count);
2007
    return result;
2008
}
2009

    
2010
static int remove_direntries(BDRVVVFATState* s, int dir_index, int count)
2011
{
2012
    int ret = array_remove_slice(&(s->directory), dir_index, count);
2013
    if (ret)
2014
        return ret;
2015
    adjust_dirindices(s, dir_index, -count);
2016
    return 0;
2017
}
2018

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

    
2032
    vvfat_close_current_file(s);
2033

    
2034
    assert(mapping);
2035
    assert(mapping->begin == first_cluster);
2036
    mapping->first_mapping_index = -1;
2037
    mapping->dir_index = dir_index;
2038
    mapping->mode = (dir_index <= 0 || is_directory(direntry)) ?
2039
        MODE_DIRECTORY : MODE_NORMAL;
2040

    
2041
    while (!fat_eof(s, cluster)) {
2042
        uint32_t c, c1;
2043

    
2044
        for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
2045
                c = c1, c1 = modified_fat_get(s, c1));
2046

    
2047
        c++;
2048
        if (c > mapping->end) {
2049
            int index = array_index(&(s->mapping), mapping);
2050
            int i, max_i = s->mapping.next - index;
2051
            for (i = 1; i < max_i && mapping[i].begin < c; i++);
2052
            while (--i > 0)
2053
                remove_mapping(s, index + 1);
2054
        }
2055
        assert(mapping == array_get(&(s->mapping), s->mapping.next - 1)
2056
                || mapping[1].begin >= c);
2057
        mapping->end = c;
2058

    
2059
        if (!fat_eof(s, c1)) {
2060
            int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next);
2061
            mapping_t* next_mapping = i >= s->mapping.next ? NULL :
2062
                array_get(&(s->mapping), i);
2063

    
2064
            if (next_mapping == NULL || next_mapping->begin > c1) {
2065
                int i1 = array_index(&(s->mapping), mapping);
2066

    
2067
                next_mapping = insert_mapping(s, c1, c1+1);
2068

    
2069
                if (c1 < c)
2070
                    i1++;
2071
                mapping = array_get(&(s->mapping), i1);
2072
            }
2073

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

    
2093
            mapping = next_mapping;
2094
        }
2095

    
2096
        cluster = c1;
2097
    }
2098

    
2099
    return 0;
2100
}
2101

    
2102
static int commit_direntries(BDRVVVFATState* s,
2103
        int dir_index, int parent_mapping_index)
2104
{
2105
    direntry_t* direntry = array_get(&(s->directory), dir_index);
2106
    uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
2107
    mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2108

    
2109
    int factor = 0x10 * s->sectors_per_cluster;
2110
    int old_cluster_count, new_cluster_count;
2111
    int current_dir_index = mapping->info.dir.first_dir_index;
2112
    int first_dir_index = current_dir_index;
2113
    int ret, i;
2114
    uint32_t c;
2115

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

    
2118
    assert(direntry);
2119
    assert(mapping);
2120
    assert(mapping->begin == first_cluster);
2121
    assert(mapping->info.dir.first_dir_index < s->directory.next);
2122
    assert(mapping->mode & MODE_DIRECTORY);
2123
    assert(dir_index == 0 || is_directory(direntry));
2124

    
2125
    mapping->info.dir.parent_mapping_index = parent_mapping_index;
2126

    
2127
    if (first_cluster == 0) {
2128
        old_cluster_count = new_cluster_count =
2129
            s->last_cluster_of_root_directory;
2130
    } else {
2131
        for (old_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2132
                c = fat_get(s, c))
2133
            old_cluster_count++;
2134

    
2135
        for (new_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2136
                c = modified_fat_get(s, c))
2137
            new_cluster_count++;
2138
    }
2139

    
2140
    if (new_cluster_count > old_cluster_count) {
2141
        if (insert_direntries(s,
2142
                current_dir_index + factor * old_cluster_count,
2143
                factor * (new_cluster_count - old_cluster_count)) == NULL)
2144
            return -1;
2145
    } else if (new_cluster_count < old_cluster_count)
2146
        remove_direntries(s,
2147
                current_dir_index + factor * new_cluster_count,
2148
                factor * (old_cluster_count - new_cluster_count));
2149

    
2150
    for (c = first_cluster; !fat_eof(s, c); c = modified_fat_get(s, c)) {
2151
        void* direntry = array_get(&(s->directory), current_dir_index);
2152
        int ret = vvfat_read(s->bs, cluster2sector(s, c), direntry,
2153
                s->sectors_per_cluster);
2154
        if (ret)
2155
            return ret;
2156
        assert(!strncmp(s->directory.pointer, "QEMU", 4));
2157
        current_dir_index += factor;
2158
    }
2159

    
2160
    ret = commit_mappings(s, first_cluster, dir_index);
2161
    if (ret)
2162
        return ret;
2163

    
2164
    /* recurse */
2165
    for (i = 0; i < factor * new_cluster_count; i++) {
2166
        direntry = array_get(&(s->directory), first_dir_index + i);
2167
        if (is_directory(direntry) && !is_dot(direntry)) {
2168
            mapping = find_mapping_for_cluster(s, first_cluster);
2169
            assert(mapping->mode & MODE_DIRECTORY);
2170
            ret = commit_direntries(s, first_dir_index + i,
2171
                array_index(&(s->mapping), mapping));
2172
            if (ret)
2173
                return ret;
2174
        }
2175
    }
2176

    
2177
    return 0;
2178
}
2179

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

    
2194
    assert(offset < size);
2195
    assert((offset % s->cluster_size) == 0);
2196

    
2197
    for (i = s->cluster_size; i < offset; i += s->cluster_size)
2198
        c = modified_fat_get(s, c);
2199

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

    
2214
    while (offset < size) {
2215
        uint32_t c1;
2216
        int rest_size = (size - offset > s->cluster_size ?
2217
                s->cluster_size : size - offset);
2218
        int ret;
2219

    
2220
        c1 = modified_fat_get(s, c);
2221

    
2222
        assert((size - offset == 0 && fat_eof(s, c)) ||
2223
                (size > offset && c >=2 && !fat_eof(s, c)));
2224

    
2225
        ret = vvfat_read(s->bs, cluster2sector(s, c),
2226
            (uint8_t*)cluster, (rest_size + 0x1ff) / 0x200);
2227

    
2228
        if (ret < 0) {
2229
            g_free(cluster);
2230
            return ret;
2231
        }
2232

    
2233
        if (write(fd, cluster, rest_size) < 0) {
2234
            g_free(cluster);
2235
            return -2;
2236
        }
2237

    
2238
        offset += rest_size;
2239
        c = c1;
2240
    }
2241

    
2242
    if (ftruncate(fd, size)) {
2243
        perror("ftruncate()");
2244
        close(fd);
2245
        g_free(cluster);
2246
        return -4;
2247
    }
2248
    close(fd);
2249
    g_free(cluster);
2250

    
2251
    return commit_mappings(s, first_cluster, dir_index);
2252
}
2253

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

    
2275
/* test, if all direntries have mappings */
2276
static void check2(BDRVVVFATState* s)
2277
{
2278
    int i;
2279
    int first_mapping = -1;
2280

    
2281
    for (i = 0; i < s->directory.next; i++) {
2282
        direntry_t* direntry = array_get(&(s->directory), i);
2283

    
2284
        if (is_short_name(direntry) && begin_of_direntry(direntry)) {
2285
            mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
2286
            assert(mapping);
2287
            assert(mapping->dir_index == i || is_dot(direntry));
2288
            assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry));
2289
        }
2290

    
2291
        if ((i % (0x10 * s->sectors_per_cluster)) == 0) {
2292
            /* cluster start */
2293
            int j, count = 0;
2294

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

    
2323
static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2324
{
2325
    int i;
2326

    
2327
#ifdef DEBUG
2328
    fprintf(stderr, "handle_renames\n");
2329
    for (i = 0; i < s->commits.next; i++) {
2330
        commit_t* commit = array_get(&(s->commits), i);
2331
        fprintf(stderr, "%d, %s (%d, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action);
2332
    }
2333
#endif
2334

    
2335
    for (i = 0; i < s->commits.next;) {
2336
        commit_t* commit = array_get(&(s->commits), i);
2337
        if (commit->action == ACTION_RENAME) {
2338
            mapping_t* mapping = find_mapping_for_cluster(s,
2339
                    commit->param.rename.cluster);
2340
            char* old_path = mapping->path;
2341

    
2342
            assert(commit->path);
2343
            mapping->path = commit->path;
2344
            if (rename(old_path, mapping->path))
2345
                return -2;
2346

    
2347
            if (mapping->mode & MODE_DIRECTORY) {
2348
                int l1 = strlen(mapping->path);
2349
                int l2 = strlen(old_path);
2350
                int diff = l1 - l2;
2351
                direntry_t* direntry = array_get(&(s->directory),
2352
                        mapping->info.dir.first_dir_index);
2353
                uint32_t c = mapping->begin;
2354
                int i = 0;
2355

    
2356
                /* recurse */
2357
                while (!fat_eof(s, c)) {
2358
                    do {
2359
                        direntry_t* d = direntry + i;
2360

    
2361
                        if (is_file(d) || (is_directory(d) && !is_dot(d))) {
2362
                            mapping_t* m = find_mapping_for_cluster(s,
2363
                                    begin_of_direntry(d));
2364
                            int l = strlen(m->path);
2365
                            char* new_path = g_malloc(l + diff + 1);
2366

    
2367
                            assert(!strncmp(m->path, mapping->path, l2));
2368

    
2369
                            pstrcpy(new_path, l + diff + 1, mapping->path);
2370
                            pstrcpy(new_path + l1, l + diff + 1 - l1,
2371
                                    m->path + l2);
2372

    
2373
                            schedule_rename(s, m->begin, new_path);
2374
                        }
2375
                        i++;
2376
                    } while((i % (0x10 * s->sectors_per_cluster)) != 0);
2377
                    c = fat_get(s, c);
2378
                }
2379
            }
2380

    
2381
            g_free(old_path);
2382
            array_remove(&(s->commits), i);
2383
            continue;
2384
        } else if (commit->action == ACTION_MKDIR) {
2385
            mapping_t* mapping;
2386
            int j, parent_path_len;
2387

    
2388
#ifdef __MINGW32__
2389
            if (mkdir(commit->path))
2390
                return -5;
2391
#else
2392
            if (mkdir(commit->path, 0755))
2393
                return -5;
2394
#endif
2395

    
2396
            mapping = insert_mapping(s, commit->param.mkdir.cluster,
2397
                    commit->param.mkdir.cluster + 1);
2398
            if (mapping == NULL)
2399
                return -6;
2400

    
2401
            mapping->mode = MODE_DIRECTORY;
2402
            mapping->read_only = 0;
2403
            mapping->path = commit->path;
2404
            j = s->directory.next;
2405
            assert(j);
2406
            insert_direntries(s, s->directory.next,
2407
                    0x10 * s->sectors_per_cluster);
2408
            mapping->info.dir.first_dir_index = j;
2409

    
2410
            parent_path_len = strlen(commit->path)
2411
                - strlen(get_basename(commit->path)) - 1;
2412
            for (j = 0; j < s->mapping.next; j++) {
2413
                mapping_t* m = array_get(&(s->mapping), j);
2414
                if (m->first_mapping_index < 0 && m != mapping &&
2415
                        !strncmp(m->path, mapping->path, parent_path_len) &&
2416
                        strlen(m->path) == parent_path_len)
2417
                    break;
2418
            }
2419
            assert(j < s->mapping.next);
2420
            mapping->info.dir.parent_mapping_index = j;
2421

    
2422
            array_remove(&(s->commits), i);
2423
            continue;
2424
        }
2425

    
2426
        i++;
2427
    }
2428
    return 0;
2429
}
2430

    
2431
/*
2432
 * TODO: make sure that the short name is not matching *another* file
2433
 */
2434
static int handle_commits(BDRVVVFATState* s)
2435
{
2436
    int i, fail = 0;
2437

    
2438
    vvfat_close_current_file(s);
2439

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

    
2456
            assert(mapping);
2457
            assert(mapping->begin == begin);
2458
            assert(commit->path == NULL);
2459

    
2460
            if (commit_one_file(s, commit->param.writeout.dir_index,
2461
                        commit->param.writeout.modified_offset))
2462
                fail = -3;
2463

    
2464
            break;
2465
        }
2466
        case ACTION_NEW_FILE: {
2467
            int begin = commit->param.new_file.first_cluster;
2468
            mapping_t* mapping = find_mapping_for_cluster(s, begin);
2469
            direntry_t* entry;
2470
            int i;
2471

    
2472
            /* find direntry */
2473
            for (i = 0; i < s->directory.next; i++) {
2474
                entry = array_get(&(s->directory), i);
2475
                if (is_file(entry) && begin_of_direntry(entry) == begin)
2476
                    break;
2477
            }
2478

    
2479
            if (i >= s->directory.next) {
2480
                fail = -6;
2481
                continue;
2482
            }
2483

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

    
2499
            if (commit_one_file(s, i, 0))
2500
                fail = -7;
2501

    
2502
            break;
2503
        }
2504
        default:
2505
            abort();
2506
        }
2507
    }
2508
    if (i > 0 && array_remove_slice(&(s->commits), 0, i))
2509
        return -1;
2510
    return fail;
2511
}
2512

    
2513
static int handle_deletes(BDRVVVFATState* s)
2514
{
2515
    int i, deferred = 1, deleted = 1;
2516

    
2517
    /* delete files corresponding to mappings marked as deleted */
2518
    /* handle DELETEs and unused mappings (modified_fat_get(s, mapping->begin) == 0) */
2519
    while (deferred && deleted) {
2520
        deferred = 0;
2521
        deleted = 0;
2522

    
2523
        for (i = 1; i < s->mapping.next; i++) {
2524
            mapping_t* mapping = array_get(&(s->mapping), i);
2525
            if (mapping->mode & MODE_DELETED) {
2526
                direntry_t* entry = array_get(&(s->directory),
2527
                        mapping->dir_index);
2528

    
2529
                if (is_free(entry)) {
2530
                    /* remove file/directory */
2531
                    if (mapping->mode & MODE_DIRECTORY) {
2532
                        int j, next_dir_index = s->directory.next,
2533
                        first_dir_index = mapping->info.dir.first_dir_index;
2534

    
2535
                        if (rmdir(mapping->path) < 0) {
2536
                            if (errno == ENOTEMPTY) {
2537
                                deferred++;
2538
                                continue;
2539
                            } else
2540
                                return -5;
2541
                        }
2542

    
2543
                        for (j = 1; j < s->mapping.next; j++) {
2544
                            mapping_t* m = array_get(&(s->mapping), j);
2545
                            if (m->mode & MODE_DIRECTORY &&
2546
                                    m->info.dir.first_dir_index >
2547
                                    first_dir_index &&
2548
                                    m->info.dir.first_dir_index <
2549
                                    next_dir_index)
2550
                                next_dir_index =
2551
                                    m->info.dir.first_dir_index;
2552
                        }
2553
                        remove_direntries(s, first_dir_index,
2554
                                next_dir_index - first_dir_index);
2555

    
2556
                        deleted++;
2557
                    }
2558
                } else {
2559
                    if (unlink(mapping->path))
2560
                        return -4;
2561
                    deleted++;
2562
                }
2563
                DLOG(fprintf(stderr, "DELETE (%d)\n", i); print_mapping(mapping); print_direntry(entry));
2564
                remove_mapping(s, i);
2565
            }
2566
        }
2567
    }
2568

    
2569
    return 0;
2570
}
2571

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

    
2584
    /* the real meat are the commits. Nothing to do? Move along! */
2585
    if (s->commits.next == 0)
2586
        return 0;
2587

    
2588
    vvfat_close_current_file(s);
2589

    
2590
    ret = handle_renames_and_mkdirs(s);
2591
    if (ret) {
2592
        fprintf(stderr, "Error handling renames (%d)\n", ret);
2593
        abort();
2594
        return ret;
2595
    }
2596

    
2597
    /* copy FAT (with bdrv_read) */
2598
    memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
2599

    
2600
    /* recurse direntries from root (using bs->bdrv_read) */
2601
    ret = commit_direntries(s, 0, -1);
2602
    if (ret) {
2603
        fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
2604
        abort();
2605
        return ret;
2606
    }
2607

    
2608
    ret = handle_commits(s);
2609
    if (ret) {
2610
        fprintf(stderr, "Error handling commits (%d)\n", ret);
2611
        abort();
2612
        return ret;
2613
    }
2614

    
2615
    ret = handle_deletes(s);
2616
    if (ret) {
2617
        fprintf(stderr, "Error deleting\n");
2618
        abort();
2619
        return ret;
2620
    }
2621

    
2622
    s->qcow->drv->bdrv_make_empty(s->qcow);
2623

    
2624
    memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
2625

    
2626
DLOG(checkpoint());
2627
    return 0;
2628
}
2629

    
2630
static int try_commit(BDRVVVFATState* s)
2631
{
2632
    vvfat_close_current_file(s);
2633
DLOG(checkpoint());
2634
    if(!is_consistent(s))
2635
        return -1;
2636
    return do_commit(s);
2637
}
2638

    
2639
static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
2640
                    const uint8_t *buf, int nb_sectors)
2641
{
2642
    BDRVVVFATState *s = bs->opaque;
2643
    int i, ret;
2644

    
2645
DLOG(checkpoint());
2646

    
2647
    /* Check if we're operating in read-only mode */
2648
    if (s->qcow == NULL) {
2649
        return -EACCES;
2650
    }
2651

    
2652
    vvfat_close_current_file(s);
2653

    
2654
    /*
2655
     * Some sanity checks:
2656
     * - do not allow writing to the boot sector
2657
     * - do not allow to write non-ASCII filenames
2658
     */
2659

    
2660
    if (sector_num < s->first_sectors_number)
2661
        return -1;
2662

    
2663
    for (i = sector2cluster(s, sector_num);
2664
            i <= sector2cluster(s, sector_num + nb_sectors - 1);) {
2665
        mapping_t* mapping = find_mapping_for_cluster(s, i);
2666
        if (mapping) {
2667
            if (mapping->read_only) {
2668
                fprintf(stderr, "Tried to write to write-protected file %s\n",
2669
                        mapping->path);
2670
                return -1;
2671
            }
2672

    
2673
            if (mapping->mode & MODE_DIRECTORY) {
2674
                int begin = cluster2sector(s, i);
2675
                int end = begin + s->sectors_per_cluster, k;
2676
                int dir_index;
2677
                const direntry_t* direntries;
2678
                long_file_name lfn;
2679

    
2680
                lfn_init(&lfn);
2681

    
2682
                if (begin < sector_num)
2683
                    begin = sector_num;
2684
                if (end > sector_num + nb_sectors)
2685
                    end = sector_num + nb_sectors;
2686
                dir_index  = mapping->dir_index +
2687
                    0x10 * (begin - mapping->begin * s->sectors_per_cluster);
2688
                direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
2689

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

    
2713
    /*
2714
     * Use qcow backend. Commit later.
2715
     */
2716
DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
2717
    ret = s->qcow->drv->bdrv_write(s->qcow, sector_num, buf, nb_sectors);
2718
    if (ret < 0) {
2719
        fprintf(stderr, "Error writing to qcow backend\n");
2720
        return ret;
2721
    }
2722

    
2723
    for (i = sector2cluster(s, sector_num);
2724
            i <= sector2cluster(s, sector_num + nb_sectors - 1); i++)
2725
        if (i >= 0)
2726
            s->used_clusters[i] |= USED_ALLOCATED;
2727

    
2728
DLOG(checkpoint());
2729
    /* TODO: add timeout */
2730
    try_commit(s);
2731

    
2732
DLOG(checkpoint());
2733
    return 0;
2734
}
2735

    
2736
static coroutine_fn int vvfat_co_write(BlockDriverState *bs, int64_t sector_num,
2737
                                       const uint8_t *buf, int nb_sectors)
2738
{
2739
    int ret;
2740
    BDRVVVFATState *s = bs->opaque;
2741
    qemu_co_mutex_lock(&s->lock);
2742
    ret = vvfat_write(bs, sector_num, buf, nb_sectors);
2743
    qemu_co_mutex_unlock(&s->lock);
2744
    return ret;
2745
}
2746

    
2747
static int vvfat_is_allocated(BlockDriverState *bs,
2748
        int64_t sector_num, int nb_sectors, int* n)
2749
{
2750
    BDRVVVFATState* s = bs->opaque;
2751
    *n = s->sector_count - sector_num;
2752
    if (*n > nb_sectors)
2753
        *n = nb_sectors;
2754
    else if (*n < 0)
2755
        return 0;
2756
    return 1;
2757
}
2758

    
2759
static int write_target_commit(BlockDriverState *bs, int64_t sector_num,
2760
        const uint8_t* buffer, int nb_sectors) {
2761
    BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
2762
    return try_commit(s);
2763
}
2764

    
2765
static void write_target_close(BlockDriverState *bs) {
2766
    BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
2767
    bdrv_delete(s->qcow);
2768
    g_free(s->qcow_filename);
2769
}
2770

    
2771
static BlockDriver vvfat_write_target = {
2772
    .format_name        = "vvfat_write_target",
2773
    .bdrv_write         = write_target_commit,
2774
    .bdrv_close         = write_target_close,
2775
};
2776

    
2777
static int enable_write_target(BDRVVVFATState *s)
2778
{
2779
    BlockDriver *bdrv_qcow;
2780
    QEMUOptionParameter *options;
2781
    int ret;
2782
    int size = sector2cluster(s, s->sector_count);
2783
    s->used_clusters = calloc(size, 1);
2784

    
2785
    array_init(&(s->commits), sizeof(commit_t));
2786

    
2787
    s->qcow_filename = g_malloc(1024);
2788
    get_tmp_filename(s->qcow_filename, 1024);
2789

    
2790
    bdrv_qcow = bdrv_find_format("qcow");
2791
    options = parse_option_parameters("", bdrv_qcow->create_options, NULL);
2792
    set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512);
2793
    set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:");
2794

    
2795
    if (bdrv_create(bdrv_qcow, s->qcow_filename, options) < 0)
2796
        return -1;
2797

    
2798
    s->qcow = bdrv_new("");
2799
    if (s->qcow == NULL) {
2800
        return -1;
2801
    }
2802

    
2803
    ret = bdrv_open(s->qcow, s->qcow_filename,
2804
            BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, bdrv_qcow);
2805
    if (ret < 0) {
2806
        return ret;
2807
    }
2808

    
2809
#ifndef _WIN32
2810
    unlink(s->qcow_filename);
2811
#endif
2812

    
2813
    s->bs->backing_hd = calloc(sizeof(BlockDriverState), 1);
2814
    s->bs->backing_hd->drv = &vvfat_write_target;
2815
    s->bs->backing_hd->opaque = g_malloc(sizeof(void*));
2816
    *(void**)s->bs->backing_hd->opaque = s;
2817

    
2818
    return 0;
2819
}
2820

    
2821
static void vvfat_close(BlockDriverState *bs)
2822
{
2823
    BDRVVVFATState *s = bs->opaque;
2824

    
2825
    vvfat_close_current_file(s);
2826
    array_free(&(s->fat));
2827
    array_free(&(s->directory));
2828
    array_free(&(s->mapping));
2829
    g_free(s->cluster_buffer);
2830
}
2831

    
2832
static BlockDriver bdrv_vvfat = {
2833
    .format_name        = "vvfat",
2834
    .instance_size        = sizeof(BDRVVVFATState),
2835
    .bdrv_file_open        = vvfat_open,
2836
    .bdrv_read          = vvfat_co_read,
2837
    .bdrv_write         = vvfat_co_write,
2838
    .bdrv_close                = vvfat_close,
2839
    .bdrv_is_allocated        = vvfat_is_allocated,
2840
    .protocol_name        = "fat",
2841
};
2842

    
2843
static void bdrv_vvfat_init(void)
2844
{
2845
    bdrv_register(&bdrv_vvfat);
2846
}
2847

    
2848
block_init(bdrv_vvfat_init);
2849

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