Statistics
| Branch: | Revision:

root / block-vvfat.c @ 295abf36

History | View | Annotate | Download (79.1 kB)

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

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

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

    
111
    return 0;
112
}
113

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

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

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

    
124
    return result;
125
}
126

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

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

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

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

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

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

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

    
172
    free(buf);
173

    
174
    return 0;
175
}
176

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
320
typedef struct BDRVVVFATState {
321
    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
        chksum=(((chksum&0xfe)>>1)|((chksum&0x01)?0x80:0))
514
            +(unsigned char)entry->name[i];
515

    
516
    return chksum;
517
}
518

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

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

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

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

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

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

    
599
}
600

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

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

    
617
    entry_long=create_long_filename(s,filename);
618

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

    
626
    entry=array_get_next(&(s->directory));
627
    memset(entry->name,0x20,11);
628
    strncpy((char*)entry->name,filename,i);
629

    
630
    if(j > 0)
631
        for (i = 0; i < 3 && filename[j+1+i]; i++)
632
            entry->extension[i] = filename[j+1+i];
633

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

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

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

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

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

    
673
    /* calculate checksum; propagate to long name */
674
    if(entry_long) {
675
        uint8_t chksum=fat_chksum(entry);
676

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

    
685
    return entry;
686
}
687

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

    
702
    DIR* dir=opendir(dirname);
703
    struct dirent* entry;
704
    int i;
705

    
706
    assert(mapping->mode & MODE_DIRECTORY);
707

    
708
    if(!dir) {
709
        mapping->end = mapping->begin;
710
        return -1;
711
    }
712

    
713
    i = mapping->info.dir.first_dir_index =
714
            first_cluster == 0 ? 0 : s->directory.next;
715

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

    
725
        if(first_cluster == 0 && (is_dotdot || is_dot))
726
            continue;
727

    
728
        buffer=(char*)malloc(length);
729
        assert(buffer);
730
        snprintf(buffer,length,"%s/%s",dirname,entry->d_name);
731

    
732
        if(stat(buffer,&st)<0) {
733
            free(buffer);
734
            continue;
735
        }
736

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

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

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

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

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

    
809
    direntry = (direntry_t*)array_get(&(s->directory), mapping->dir_index);
810
    set_begin_of_direntry(direntry, mapping->begin);
811

    
812
    return 0;
813
}
814

    
815
static inline uint32_t sector2cluster(BDRVVVFATState* s,off_t sector_num)
816
{
817
    return (sector_num-s->faked_sectors)/s->sectors_per_cluster;
818
}
819

    
820
static inline off_t cluster2sector(BDRVVVFATState* s, uint32_t cluster_num)
821
{
822
    return s->faked_sectors + s->sectors_per_cluster * cluster_num;
823
}
824

    
825
static inline uint32_t sector_offset_in_cluster(BDRVVVFATState* s,off_t sector_num)
826
{
827
    return (sector_num-s->first_sectors_number-2*s->sectors_per_fat)%s->sectors_per_cluster;
828
}
829

    
830
#ifdef DBG
831
static direntry_t* get_direntry_for_mapping(BDRVVVFATState* s,mapping_t* mapping)
832
{
833
    if(mapping->mode==MODE_UNDEFINED)
834
        return 0;
835
    return (direntry_t*)(s->directory.pointer+sizeof(direntry_t)*mapping->dir_index);
836
}
837
#endif
838

    
839
static int init_directories(BDRVVVFATState* s,
840
        const char* dirname)
841
{
842
    bootsector_t* bootsector;
843
    mapping_t* mapping;
844
    unsigned int i;
845
    unsigned int cluster;
846

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

    
849
    s->cluster_size=s->sectors_per_cluster*0x200;
850
    s->cluster_buffer=malloc(s->cluster_size);
851
    assert(s->cluster_buffer);
852

    
853
    /*
854
     * The formula: sc = spf+1+spf*spc*(512*8/fat_type),
855
     * where sc is sector_count,
856
     * spf is sectors_per_fat,
857
     * spc is sectors_per_clusters, and
858
     * fat_type = 12, 16 or 32.
859
     */
860
    i = 1+s->sectors_per_cluster*0x200*8/s->fat_type;
861
    s->sectors_per_fat=(s->sector_count+i)/i; /* round up */
862

    
863
    array_init(&(s->mapping),sizeof(mapping_t));
864
    array_init(&(s->directory),sizeof(direntry_t));
865

    
866
    /* add volume label */
867
    {
868
        direntry_t* entry=array_get_next(&(s->directory));
869
        entry->attributes=0x28; /* archive | volume label */
870
        snprintf((char*)entry->name,11,"QEMU VVFAT");
871
    }
872

    
873
    /* Now build FAT, and write back information into directory */
874
    init_fat(s);
875

    
876
    s->faked_sectors=s->first_sectors_number+s->sectors_per_fat*2;
877
    s->cluster_count=sector2cluster(s, s->sector_count);
878

    
879
    mapping = array_get_next(&(s->mapping));
880
    mapping->begin = 0;
881
    mapping->dir_index = 0;
882
    mapping->info.dir.parent_mapping_index = -1;
883
    mapping->first_mapping_index = -1;
884
    mapping->path = strdup(dirname);
885
    i = strlen(mapping->path);
886
    if (i > 0 && mapping->path[i - 1] == '/')
887
        mapping->path[i - 1] = '\0';
888
    mapping->mode = MODE_DIRECTORY;
889
    mapping->read_only = 0;
890
    s->path = mapping->path;
891

    
892
    for (i = 0, cluster = 0; i < s->mapping.next; i++) {
893
        int j;
894
        /* MS-DOS expects the FAT to be 0 for the root directory
895
         * (except for the media byte). */
896
        /* LATER TODO: still true for FAT32? */
897
        int fix_fat = (i != 0);
898
        mapping = array_get(&(s->mapping), i);
899

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

    
916
                mapping->end = cluster + 1 + (mapping->end-1)/s->cluster_size;
917
                set_begin_of_direntry(direntry, mapping->begin);
918
            } else {
919
                mapping->end = cluster + 1;
920
                fix_fat = 0;
921
            }
922
        }
923

    
924
        assert(mapping->begin < mapping->end);
925

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

    
933
        /* next free cluster */
934
        cluster = mapping->end;
935

    
936
        if(cluster > s->cluster_count) {
937
            fprintf(stderr,"Directory does not fit in FAT%d\n",s->fat_type);
938
            return -1;
939
        }
940
    }
941

    
942
    mapping = array_get(&(s->mapping), 0);
943
    s->sectors_of_root_directory = mapping->end * s->sectors_per_cluster;
944
    s->last_cluster_of_root_directory = mapping->end;
945

    
946
    /* the FAT signature */
947
    fat_set(s,0,s->max_fat_value);
948
    fat_set(s,1,s->max_fat_value);
949

    
950
    s->current_mapping = NULL;
951

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

    
971
    /* LATER TODO: if FAT32, this is wrong */
972
    bootsector->u.fat16.drive_number=s->fat_type==12?0:0x80; /* assume this is hda (TODO) */
973
    bootsector->u.fat16.current_head=0;
974
    bootsector->u.fat16.signature=0x29;
975
    bootsector->u.fat16.id=cpu_to_le32(0xfabe1afd);
976

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

    
981
    return 0;
982
}
983

    
984
#ifdef DEBUG
985
static BDRVVVFATState *vvv = NULL;
986
#endif
987

    
988
static int enable_write_target(BDRVVVFATState *s);
989
static int is_consistent(BDRVVVFATState *s);
990

    
991
static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
992
{
993
    BDRVVVFATState *s = bs->opaque;
994
    int floppy = 0;
995
    int i;
996

    
997
#ifdef DEBUG
998
    vvv = s;
999
#endif
1000

    
1001
DLOG(if (stderr == NULL) {
1002
    stderr = fopen("vvfat.log", "a");
1003
    setbuf(stderr, NULL);
1004
})
1005

    
1006
    s->bs = bs;
1007

    
1008
    s->fat_type=16;
1009
    /* LATER TODO: if FAT32, adjust */
1010
    s->sectors_per_cluster=0x10;
1011
    /* 504MB disk*/
1012
    bs->cyls=1024; bs->heads=16; bs->secs=63;
1013

    
1014
    s->current_cluster=0xffffffff;
1015

    
1016
    s->first_sectors_number=0x40;
1017
    /* read only is the default for safety */
1018
    bs->read_only = 1;
1019
    s->qcow = s->write_target = NULL;
1020
    s->qcow_filename = NULL;
1021
    s->fat2 = NULL;
1022
    s->downcase_short_names = 1;
1023

    
1024
    if (!strstart(dirname, "fat:", NULL))
1025
        return -1;
1026

    
1027
    if (strstr(dirname, ":floppy:")) {
1028
        floppy = 1;
1029
        s->fat_type = 12;
1030
        s->first_sectors_number = 1;
1031
        s->sectors_per_cluster=2;
1032
        bs->cyls = 80; bs->heads = 2; bs->secs = 36;
1033
    }
1034

    
1035
    s->sector_count=bs->cyls*bs->heads*bs->secs;
1036

    
1037
    if (strstr(dirname, ":32:")) {
1038
        fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. You are welcome to do so!\n");
1039
        s->fat_type = 32;
1040
    } else if (strstr(dirname, ":16:")) {
1041
        s->fat_type = 16;
1042
    } else if (strstr(dirname, ":12:")) {
1043
        s->fat_type = 12;
1044
        s->sector_count=2880;
1045
    }
1046

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

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

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

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

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

    
1068
    if(s->first_sectors_number==0x40)
1069
        init_mbr(s);
1070

    
1071
    /* for some reason or other, MS-DOS does not like to know about CHS... */
1072
    if (floppy)
1073
        bs->heads = bs->cyls = bs->secs = 0;
1074

    
1075
    //    assert(is_consistent(s));
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
    int index3=index1+1;
1097
    while(1) {
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 0;
1127
    mapping=array_get(&(s->mapping),index);
1128
    if(mapping->begin>cluster_num)
1129
        return 0;
1130
    assert(mapping->begin<=cluster_num && mapping->end>cluster_num);
1131
    return mapping;
1132
}
1133

    
1134
/*
1135
 * This function simply compares path == mapping->path. Since the mappings
1136
 * are sorted by cluster, this is expensive: O(n).
1137
 */
1138
static inline mapping_t* find_mapping_for_path(BDRVVVFATState* s,
1139
        const char* path)
1140
{
1141
    int i;
1142

    
1143
    for (i = 0; i < s->mapping.next; i++) {
1144
        mapping_t* mapping = array_get(&(s->mapping), i);
1145
        if (mapping->first_mapping_index < 0 &&
1146
                !strcmp(path, mapping->path))
1147
            return mapping;
1148
    }
1149

    
1150
    return NULL;
1151
}
1152

    
1153
static int open_file(BDRVVVFATState* s,mapping_t* mapping)
1154
{
1155
    if(!mapping)
1156
        return -1;
1157
    if(!s->current_mapping ||
1158
            strcmp(s->current_mapping->path,mapping->path)) {
1159
        /* open file */
1160
        int fd = open(mapping->path, O_RDONLY | O_BINARY | O_LARGEFILE);
1161
        if(fd<0)
1162
            return -1;
1163
        vvfat_close_current_file(s);
1164
        s->current_fd = fd;
1165
        s->current_mapping = mapping;
1166
    }
1167
    return 0;
1168
}
1169

    
1170
static inline int read_cluster(BDRVVVFATState *s,int cluster_num)
1171
{
1172
    if(s->current_cluster != cluster_num) {
1173
        int result=0;
1174
        off_t offset;
1175
        assert(!s->current_mapping || s->current_fd || (s->current_mapping->mode & MODE_DIRECTORY));
1176
        if(!s->current_mapping
1177
                || s->current_mapping->begin>cluster_num
1178
                || s->current_mapping->end<=cluster_num) {
1179
            /* binary search of mappings for file */
1180
            mapping_t* mapping=find_mapping_for_cluster(s,cluster_num);
1181

    
1182
            assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
1183

    
1184
            if (mapping && mapping->mode & MODE_DIRECTORY) {
1185
                vvfat_close_current_file(s);
1186
                s->current_mapping = mapping;
1187
read_cluster_directory:
1188
                offset = s->cluster_size*(cluster_num-s->current_mapping->begin);
1189
                s->cluster = (unsigned char*)s->directory.pointer+offset
1190
                        + 0x20*s->current_mapping->info.dir.first_dir_index;
1191
                assert(((s->cluster-(unsigned char*)s->directory.pointer)%s->cluster_size)==0);
1192
                assert((char*)s->cluster+s->cluster_size <= s->directory.pointer+s->directory.next*s->directory.item_size);
1193
                s->current_cluster = cluster_num;
1194
                return 0;
1195
            }
1196

    
1197
            if(open_file(s,mapping))
1198
                return -2;
1199
        } else if (s->current_mapping->mode & MODE_DIRECTORY)
1200
            goto read_cluster_directory;
1201

    
1202
        assert(s->current_fd);
1203

    
1204
        offset=s->cluster_size*(cluster_num-s->current_mapping->begin)+s->current_mapping->info.file.offset;
1205
        if(lseek(s->current_fd, offset, SEEK_SET)!=offset)
1206
            return -3;
1207
        s->cluster=s->cluster_buffer;
1208
        result=read(s->current_fd,s->cluster,s->cluster_size);
1209
        if(result<0) {
1210
            s->current_cluster = -1;
1211
            return -1;
1212
        }
1213
        s->current_cluster = cluster_num;
1214
    }
1215
    return 0;
1216
}
1217

    
1218
#ifdef DEBUG
1219
static void hexdump(const void* address, uint32_t len)
1220
{
1221
    const unsigned char* p = address;
1222
    int i, j;
1223

    
1224
    for (i = 0; i < len; i += 16) {
1225
        for (j = 0; j < 16 && i + j < len; j++)
1226
            fprintf(stderr, "%02x ", p[i + j]);
1227
        for (; j < 16; j++)
1228
            fprintf(stderr, "   ");
1229
        fprintf(stderr, " ");
1230
        for (j = 0; j < 16 && i + j < len; j++)
1231
            fprintf(stderr, "%c", (p[i + j] < ' ' || p[i + j] > 0x7f) ? '.' : p[i + j]);
1232
        fprintf(stderr, "\n");
1233
    }
1234
}
1235

    
1236
static void print_direntry(const direntry_t* direntry)
1237
{
1238
    int j = 0;
1239
    char buffer[1024];
1240

    
1241
    fprintf(stderr, "direntry 0x%x: ", (int)direntry);
1242
    if(!direntry)
1243
        return;
1244
    if(is_long_name(direntry)) {
1245
        unsigned char* c=(unsigned char*)direntry;
1246
        int i;
1247
        for(i=1;i<11 && c[i] && c[i]!=0xff;i+=2)
1248
#define ADD_CHAR(c) {buffer[j] = (c); if (buffer[j] < ' ') buffer[j] = '?'; j++;}
1249
            ADD_CHAR(c[i]);
1250
        for(i=14;i<26 && c[i] && c[i]!=0xff;i+=2)
1251
            ADD_CHAR(c[i]);
1252
        for(i=28;i<32 && c[i] && c[i]!=0xff;i+=2)
1253
            ADD_CHAR(c[i]);
1254
        buffer[j] = 0;
1255
        fprintf(stderr, "%s\n", buffer);
1256
    } else {
1257
        int i;
1258
        for(i=0;i<11;i++)
1259
            ADD_CHAR(direntry->name[i]);
1260
        buffer[j] = 0;
1261
        fprintf(stderr,"%s attributes=0x%02x begin=%d size=%d\n",
1262
                buffer,
1263
                direntry->attributes,
1264
                begin_of_direntry(direntry),le32_to_cpu(direntry->size));
1265
    }
1266
}
1267

    
1268
static void print_mapping(const mapping_t* mapping)
1269
{
1270
    fprintf(stderr, "mapping (0x%x): begin, end = %d, %d, dir_index = %d, first_mapping_index = %d, name = %s, mode = 0x%x, " , (int)mapping, mapping->begin, mapping->end, mapping->dir_index, mapping->first_mapping_index, mapping->path, mapping->mode);
1271
    if (mapping->mode & MODE_DIRECTORY)
1272
        fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
1273
    else
1274
        fprintf(stderr, "offset = %d\n", mapping->info.file.offset);
1275
}
1276
#endif
1277

    
1278
static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
1279
                    uint8_t *buf, int nb_sectors)
1280
{
1281
    BDRVVVFATState *s = bs->opaque;
1282
    int i;
1283

    
1284
    for(i=0;i<nb_sectors;i++,sector_num++) {
1285
        if (sector_num >= s->sector_count)
1286
           return -1;
1287
        if (s->qcow) {
1288
            int n;
1289
            if (s->qcow->drv->bdrv_is_allocated(s->qcow,
1290
                        sector_num, nb_sectors-i, &n)) {
1291
DLOG(fprintf(stderr, "sectors %d+%d allocated\n", (int)sector_num, n));
1292
                if (s->qcow->drv->bdrv_read(s->qcow, sector_num, buf+i*0x200, n))
1293
                    return -1;
1294
                i += n - 1;
1295
                sector_num += n - 1;
1296
                continue;
1297
            }
1298
DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num));
1299
        }
1300
        if(sector_num<s->faked_sectors) {
1301
            if(sector_num<s->first_sectors_number)
1302
                memcpy(buf+i*0x200,&(s->first_sectors[sector_num*0x200]),0x200);
1303
            else if(sector_num-s->first_sectors_number<s->sectors_per_fat)
1304
                memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number)*0x200]),0x200);
1305
            else if(sector_num-s->first_sectors_number-s->sectors_per_fat<s->sectors_per_fat)
1306
                memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number-s->sectors_per_fat)*0x200]),0x200);
1307
        } else {
1308
            uint32_t sector=sector_num-s->faked_sectors,
1309
            sector_offset_in_cluster=(sector%s->sectors_per_cluster),
1310
            cluster_num=sector/s->sectors_per_cluster;
1311
            if(read_cluster(s, cluster_num) != 0) {
1312
                /* LATER TODO: strict: return -1; */
1313
                memset(buf+i*0x200,0,0x200);
1314
                continue;
1315
            }
1316
            memcpy(buf+i*0x200,s->cluster+sector_offset_in_cluster*0x200,0x200);
1317
        }
1318
    }
1319
    return 0;
1320
}
1321

    
1322
/* LATER TODO: statify all functions */
1323

    
1324
/*
1325
 * Idea of the write support (use snapshot):
1326
 *
1327
 * 1. check if all data is consistent, recording renames, modifications,
1328
 *    new files and directories (in s->commits).
1329
 *
1330
 * 2. if the data is not consistent, stop committing
1331
 *
1332
 * 3. handle renames, and create new files and directories (do not yet
1333
 *    write their contents)
1334
 *
1335
 * 4. walk the directories, fixing the mapping and direntries, and marking
1336
 *    the handled mappings as not deleted
1337
 *
1338
 * 5. commit the contents of the files
1339
 *
1340
 * 6. handle deleted files and directories
1341
 *
1342
 */
1343

    
1344
typedef struct commit_t {
1345
    char* path;
1346
    union {
1347
        struct { uint32_t cluster; } rename;
1348
        struct { int dir_index; uint32_t modified_offset; } writeout;
1349
        struct { uint32_t first_cluster; } new_file;
1350
        struct { uint32_t cluster; } mkdir;
1351
    } param;
1352
    /* DELETEs and RMDIRs are handled differently: see handle_deletes() */
1353
    enum {
1354
        ACTION_RENAME, ACTION_WRITEOUT, ACTION_NEW_FILE, ACTION_MKDIR
1355
    } action;
1356
} commit_t;
1357

    
1358
static void clear_commits(BDRVVVFATState* s)
1359
{
1360
    int i;
1361
DLOG(fprintf(stderr, "clear_commits (%d commits)\n", s->commits.next));
1362
    for (i = 0; i < s->commits.next; i++) {
1363
        commit_t* commit = array_get(&(s->commits), i);
1364
        assert(commit->path || commit->action == ACTION_WRITEOUT);
1365
        if (commit->action != ACTION_WRITEOUT) {
1366
            assert(commit->path);
1367
            free(commit->path);
1368
        } else
1369
            assert(commit->path == NULL);
1370
    }
1371
    s->commits.next = 0;
1372
}
1373

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

    
1383
static void schedule_writeout(BDRVVVFATState* s,
1384
        int dir_index, uint32_t modified_offset)
1385
{
1386
    commit_t* commit = array_get_next(&(s->commits));
1387
    commit->path = NULL;
1388
    commit->param.writeout.dir_index = dir_index;
1389
    commit->param.writeout.modified_offset = modified_offset;
1390
    commit->action = ACTION_WRITEOUT;
1391
}
1392

    
1393
static void schedule_new_file(BDRVVVFATState* s,
1394
        char* path, uint32_t first_cluster)
1395
{
1396
    commit_t* commit = array_get_next(&(s->commits));
1397
    commit->path = path;
1398
    commit->param.new_file.first_cluster = first_cluster;
1399
    commit->action = ACTION_NEW_FILE;
1400
}
1401

    
1402
static void schedule_mkdir(BDRVVVFATState* s, uint32_t cluster, char* path)
1403
{
1404
    commit_t* commit = array_get_next(&(s->commits));
1405
    commit->path = path;
1406
    commit->param.mkdir.cluster = cluster;
1407
    commit->action = ACTION_MKDIR;
1408
}
1409

    
1410
typedef struct {
1411
    /*
1412
     * Since the sequence number is at most 0x3f, and the filename
1413
     * length is at most 13 times the sequence number, the maximal
1414
     * filename length is 0x3f * 13 bytes.
1415
     */
1416
    unsigned char name[0x3f * 13 + 1];
1417
    int checksum, len;
1418
    int sequence_number;
1419
} long_file_name;
1420

    
1421
static void lfn_init(long_file_name* lfn)
1422
{
1423
   lfn->sequence_number = lfn->len = 0;
1424
   lfn->checksum = 0x100;
1425
}
1426

    
1427
/* return 0 if parsed successfully, > 0 if no long name, < 0 if error */
1428
static int parse_long_name(long_file_name* lfn,
1429
        const direntry_t* direntry)
1430
{
1431
    int i, j, offset;
1432
    const unsigned char* pointer = (const unsigned char*)direntry;
1433

    
1434
    if (!is_long_name(direntry))
1435
        return 1;
1436

    
1437
    if (pointer[0] & 0x40) {
1438
        lfn->sequence_number = pointer[0] & 0x3f;
1439
        lfn->checksum = pointer[13];
1440
        lfn->name[0] = 0;
1441
        lfn->name[lfn->sequence_number * 13] = 0;
1442
    } else if ((pointer[0] & 0x3f) != --lfn->sequence_number)
1443
        return -1;
1444
    else if (pointer[13] != lfn->checksum)
1445
        return -2;
1446
    else if (pointer[12] || pointer[26] || pointer[27])
1447
        return -3;
1448

    
1449
    offset = 13 * (lfn->sequence_number - 1);
1450
    for (i = 0, j = 1; i < 13; i++, j+=2) {
1451
        if (j == 11)
1452
            j = 14;
1453
        else if (j == 26)
1454
            j = 28;
1455

    
1456
        if (pointer[j+1] == 0)
1457
            lfn->name[offset + i] = pointer[j];
1458
        else if (pointer[j+1] != 0xff || (pointer[0] & 0x40) == 0)
1459
            return -4;
1460
        else
1461
            lfn->name[offset + i] = 0;
1462
    }
1463

    
1464
    if (pointer[0] & 0x40)
1465
        lfn->len = offset + strlen((char*)lfn->name + offset);
1466

    
1467
    return 0;
1468
}
1469

    
1470
/* returns 0 if successful, >0 if no short_name, and <0 on error */
1471
static int parse_short_name(BDRVVVFATState* s,
1472
        long_file_name* lfn, direntry_t* direntry)
1473
{
1474
    int i, j;
1475

    
1476
    if (!is_short_name(direntry))
1477
        return 1;
1478

    
1479
    for (j = 7; j >= 0 && direntry->name[j] == ' '; j--);
1480
    for (i = 0; i <= j; i++) {
1481
        if (direntry->name[i] <= ' ' || direntry->name[i] > 0x7f)
1482
            return -1;
1483
        else if (s->downcase_short_names)
1484
            lfn->name[i] = tolower(direntry->name[i]);
1485
        else
1486
            lfn->name[i] = direntry->name[i];
1487
    }
1488

    
1489
    for (j = 2; j >= 0 && direntry->extension[j] == ' '; j--);
1490
    if (j >= 0) {
1491
        lfn->name[i++] = '.';
1492
        lfn->name[i + j + 1] = '\0';
1493
        for (;j >= 0; j--) {
1494
            if (direntry->extension[j] <= ' ' || direntry->extension[j] > 0x7f)
1495
                return -2;
1496
            else if (s->downcase_short_names)
1497
                lfn->name[i + j] = tolower(direntry->extension[j]);
1498
            else
1499
                lfn->name[i + j] = direntry->extension[j];
1500
        }
1501
    } else
1502
        lfn->name[i + j + 1] = '\0';
1503

    
1504
    lfn->len = strlen((char*)lfn->name);
1505

    
1506
    return 0;
1507
}
1508

    
1509
static inline uint32_t modified_fat_get(BDRVVVFATState* s,
1510
        unsigned int cluster)
1511
{
1512
    if (cluster < s->last_cluster_of_root_directory) {
1513
        if (cluster + 1 == s->last_cluster_of_root_directory)
1514
            return s->max_fat_value;
1515
        else
1516
            return cluster + 1;
1517
    }
1518

    
1519
    if (s->fat_type==32) {
1520
        uint32_t* entry=((uint32_t*)s->fat2)+cluster;
1521
        return le32_to_cpu(*entry);
1522
    } else if (s->fat_type==16) {
1523
        uint16_t* entry=((uint16_t*)s->fat2)+cluster;
1524
        return le16_to_cpu(*entry);
1525
    } else {
1526
        const uint8_t* x=s->fat2+cluster*3/2;
1527
        return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
1528
    }
1529
}
1530

    
1531
static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num)
1532
{
1533
    int was_modified = 0;
1534
    int i, dummy;
1535

    
1536
    if (s->qcow == NULL)
1537
        return 0;
1538

    
1539
    for (i = 0; !was_modified && i < s->sectors_per_cluster; i++)
1540
        was_modified = s->qcow->drv->bdrv_is_allocated(s->qcow,
1541
                cluster2sector(s, cluster_num) + i, 1, &dummy);
1542

    
1543
    return was_modified;
1544
}
1545

    
1546
static const char* get_basename(const char* path)
1547
{
1548
    char* basename = strrchr(path, '/');
1549
    if (basename == NULL)
1550
        return path;
1551
    else
1552
        return basename + 1; /* strip '/' */
1553
}
1554

    
1555
/*
1556
 * The array s->used_clusters holds the states of the clusters. If it is
1557
 * part of a file, it has bit 2 set, in case of a directory, bit 1. If it
1558
 * was modified, bit 3 is set.
1559
 * If any cluster is allocated, but not part of a file or directory, this
1560
 * driver refuses to commit.
1561
 */
1562
typedef enum {
1563
     USED_DIRECTORY = 1, USED_FILE = 2, USED_ANY = 3, USED_ALLOCATED = 4
1564
} used_t;
1565

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

    
1600
    uint32_t cluster_num = begin_of_direntry(direntry);
1601
    uint32_t offset = 0;
1602
    int first_mapping_index = -1;
1603
    mapping_t* mapping = NULL;
1604
    const char* basename2 = NULL;
1605

    
1606
    vvfat_close_current_file(s);
1607

    
1608
    /* the root directory */
1609
    if (cluster_num == 0)
1610
        return 0;
1611

    
1612
    /* write support */
1613
    if (s->qcow) {
1614
        basename2 = get_basename(path);
1615

    
1616
        mapping = find_mapping_for_cluster(s, cluster_num);
1617

    
1618
        if (mapping) {
1619
            const char* basename;
1620

    
1621
            assert(mapping->mode & MODE_DELETED);
1622
            mapping->mode &= ~MODE_DELETED;
1623

    
1624
            basename = get_basename(mapping->path);
1625

    
1626
            assert(mapping->mode & MODE_NORMAL);
1627

    
1628
            /* rename */
1629
            if (strcmp(basename, basename2))
1630
                schedule_rename(s, cluster_num, strdup(path));
1631
        } else if (is_file(direntry))
1632
            /* new file */
1633
            schedule_new_file(s, strdup(path), cluster_num);
1634
        else {
1635
            assert(0);
1636
            return 0;
1637
        }
1638
    }
1639

    
1640
    while(1) {
1641
        if (s->qcow) {
1642
            if (!copy_it && cluster_was_modified(s, cluster_num)) {
1643
                if (mapping == NULL ||
1644
                        mapping->begin > cluster_num ||
1645
                        mapping->end <= cluster_num)
1646
                mapping = find_mapping_for_cluster(s, cluster_num);
1647

    
1648

    
1649
                if (mapping &&
1650
                        (mapping->mode & MODE_DIRECTORY) == 0) {
1651

    
1652
                    /* was modified in qcow */
1653
                    if (offset != mapping->info.file.offset + s->cluster_size
1654
                            * (cluster_num - mapping->begin)) {
1655
                        /* offset of this cluster in file chain has changed */
1656
                        assert(0);
1657
                        copy_it = 1;
1658
                    } else if (offset == 0) {
1659
                        const char* basename = get_basename(mapping->path);
1660

    
1661
                        if (strcmp(basename, basename2))
1662
                            copy_it = 1;
1663
                        first_mapping_index = array_index(&(s->mapping), mapping);
1664
                    }
1665

    
1666
                    if (mapping->first_mapping_index != first_mapping_index
1667
                            && mapping->info.file.offset > 0) {
1668
                        assert(0);
1669
                        copy_it = 1;
1670
                    }
1671

    
1672
                    /* need to write out? */
1673
                    if (!was_modified && is_file(direntry)) {
1674
                        was_modified = 1;
1675
                        schedule_writeout(s, mapping->dir_index, offset);
1676
                    }
1677
                }
1678
            }
1679

    
1680
            if (copy_it) {
1681
                int i, dummy;
1682
                /*
1683
                 * This is horribly inefficient, but that is okay, since
1684
                 * it is rarely executed, if at all.
1685
                 */
1686
                int64_t offset = cluster2sector(s, cluster_num);
1687

    
1688
                vvfat_close_current_file(s);
1689
                for (i = 0; i < s->sectors_per_cluster; i++)
1690
                    if (!s->qcow->drv->bdrv_is_allocated(s->qcow,
1691
                                offset + i, 1, &dummy)) {
1692
                        if (vvfat_read(s->bs,
1693
                                    offset, s->cluster_buffer, 1))
1694
                            return -1;
1695
                        if (s->qcow->drv->bdrv_write(s->qcow,
1696
                                    offset, s->cluster_buffer, 1))
1697
                            return -2;
1698
                    }
1699
            }
1700
        }
1701

    
1702
        ret++;
1703
        if (s->used_clusters[cluster_num] & USED_ANY)
1704
            return 0;
1705
        s->used_clusters[cluster_num] = USED_FILE;
1706

    
1707
        cluster_num = modified_fat_get(s, cluster_num);
1708

    
1709
        if (fat_eof(s, cluster_num))
1710
            return ret;
1711
        else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
1712
            return -1;
1713

    
1714
        offset += s->cluster_size;
1715
    }
1716
}
1717

    
1718
/*
1719
 * This function looks at the modified data (qcow).
1720
 * It returns 0 upon inconsistency or error, and the number of clusters
1721
 * used by the directory, its subdirectories and their files.
1722
 */
1723
static int check_directory_consistency(BDRVVVFATState *s,
1724
        int cluster_num, const char* path)
1725
{
1726
    int ret = 0;
1727
    unsigned char* cluster = malloc(s->cluster_size);
1728
    direntry_t* direntries = (direntry_t*)cluster;
1729
    mapping_t* mapping = find_mapping_for_cluster(s, cluster_num);
1730

    
1731
    long_file_name lfn;
1732
    int path_len = strlen(path);
1733
    char path2[PATH_MAX];
1734

    
1735
    assert(path_len < PATH_MAX); /* len was tested before! */
1736
    strcpy(path2, path);
1737
    path2[path_len] = '/';
1738
    path2[path_len + 1] = '\0';
1739

    
1740
    if (mapping) {
1741
        const char* basename = get_basename(mapping->path);
1742
        const char* basename2 = get_basename(path);
1743

    
1744
        assert(mapping->mode & MODE_DIRECTORY);
1745

    
1746
        assert(mapping->mode & MODE_DELETED);
1747
        mapping->mode &= ~MODE_DELETED;
1748

    
1749
        if (strcmp(basename, basename2))
1750
            schedule_rename(s, cluster_num, strdup(path));
1751
    } else
1752
        /* new directory */
1753
        schedule_mkdir(s, cluster_num, strdup(path));
1754

    
1755
    lfn_init(&lfn);
1756
    do {
1757
        int i;
1758
        int subret = 0;
1759

    
1760
        ret++;
1761

    
1762
        if (s->used_clusters[cluster_num] & USED_ANY) {
1763
            fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
1764
            return 0;
1765
        }
1766
        s->used_clusters[cluster_num] = USED_DIRECTORY;
1767

    
1768
DLOG(fprintf(stderr, "read cluster %d (sector %d)\n", (int)cluster_num, (int)cluster2sector(s, cluster_num)));
1769
        subret = vvfat_read(s->bs, cluster2sector(s, cluster_num), cluster,
1770
                s->sectors_per_cluster);
1771
        if (subret) {
1772
            fprintf(stderr, "Error fetching direntries\n");
1773
        fail:
1774
            free(cluster);
1775
            return 0;
1776
        }
1777

    
1778
        for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
1779
            int cluster_count;
1780

    
1781
DLOG(fprintf(stderr, "check direntry %d: \n", i); print_direntry(direntries + i));
1782
            if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
1783
                    is_free(direntries + i))
1784
                continue;
1785

    
1786
            subret = parse_long_name(&lfn, direntries + i);
1787
            if (subret < 0) {
1788
                fprintf(stderr, "Error in long name\n");
1789
                goto fail;
1790
            }
1791
            if (subret == 0 || is_free(direntries + i))
1792
                continue;
1793

    
1794
            if (fat_chksum(direntries+i) != lfn.checksum) {
1795
                subret = parse_short_name(s, &lfn, direntries + i);
1796
                if (subret < 0) {
1797
                    fprintf(stderr, "Error in short name (%d)\n", subret);
1798
                    goto fail;
1799
                }
1800
                if (subret > 0 || !strcmp((char*)lfn.name, ".")
1801
                        || !strcmp((char*)lfn.name, ".."))
1802
                    continue;
1803
            }
1804
            lfn.checksum = 0x100; /* cannot use long name twice */
1805

    
1806
            if (path_len + 1 + lfn.len >= PATH_MAX) {
1807
                fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
1808
                goto fail;
1809
            }
1810
            strcpy(path2 + path_len + 1, (char*)lfn.name);
1811

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

    
1835
            ret += cluster_count;
1836
        }
1837

    
1838
        cluster_num = modified_fat_get(s, cluster_num);
1839
    } while(!fat_eof(s, cluster_num));
1840

    
1841
    free(cluster);
1842
    return ret;
1843
}
1844

    
1845
/* returns 1 on success */
1846
static int is_consistent(BDRVVVFATState* s)
1847
{
1848
    int i, check;
1849
    int used_clusters_count = 0;
1850

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

    
1880
    clear_commits(s);
1881

    
1882
    /* mark every mapped file/directory as deleted.
1883
     * (check_directory_consistency() will unmark those still present). */
1884
    if (s->qcow)
1885
        for (i = 0; i < s->mapping.next; i++) {
1886
            mapping_t* mapping = array_get(&(s->mapping), i);
1887
            if (mapping->first_mapping_index < 0)
1888
                mapping->mode |= MODE_DELETED;
1889
        }
1890

    
1891
    used_clusters_count = check_directory_consistency(s, 0, s->path);
1892
    if (used_clusters_count <= 0) {
1893
        DLOG(fprintf(stderr, "problem in directory\n"));
1894
        return 0;
1895
    }
1896

    
1897
    check = s->last_cluster_of_root_directory;
1898
    for (i = check; i < sector2cluster(s, s->sector_count); i++) {
1899
        if (modified_fat_get(s, i)) {
1900
            if(!s->used_clusters[i]) {
1901
                DLOG(fprintf(stderr, "FAT was modified (%d), but cluster is not used?\n", i));
1902
                return 0;
1903
            }
1904
            check++;
1905
        }
1906

    
1907
        if (s->used_clusters[i] == USED_ALLOCATED) {
1908
            /* allocated, but not used... */
1909
            DLOG(fprintf(stderr, "unused, modified cluster: %d\n", i));
1910
            return 0;
1911
        }
1912
    }
1913

    
1914
    if (check != used_clusters_count)
1915
        return 0;
1916

    
1917
    return used_clusters_count;
1918
}
1919

    
1920
static inline void adjust_mapping_indices(BDRVVVFATState* s,
1921
        int offset, int adjust)
1922
{
1923
    int i;
1924

    
1925
    for (i = 0; i < s->mapping.next; i++) {
1926
        mapping_t* mapping = array_get(&(s->mapping), i);
1927

    
1928
#define ADJUST_MAPPING_INDEX(name) \
1929
        if (mapping->name >= offset) \
1930
            mapping->name += adjust
1931

    
1932
        ADJUST_MAPPING_INDEX(first_mapping_index);
1933
        if (mapping->mode & MODE_DIRECTORY)
1934
            ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
1935
    }
1936
}
1937

    
1938
/* insert or update mapping */
1939
static mapping_t* insert_mapping(BDRVVVFATState* s,
1940
        uint32_t begin, uint32_t end)
1941
{
1942
    /*
1943
     * - find mapping where mapping->begin >= begin,
1944
     * - if mapping->begin > begin: insert
1945
     *   - adjust all references to mappings!
1946
     * - else: adjust
1947
     * - replace name
1948
     */
1949
    int index = find_mapping_for_cluster_aux(s, begin, 0, s->mapping.next);
1950
    mapping_t* mapping = NULL;
1951
    mapping_t* first_mapping = array_get(&(s->mapping), 0);
1952

    
1953
    if (index < s->mapping.next && (mapping = array_get(&(s->mapping), index))
1954
            && mapping->begin < begin) {
1955
        mapping->end = begin;
1956
        index++;
1957
        mapping = array_get(&(s->mapping), index);
1958
    }
1959
    if (index >= s->mapping.next || mapping->begin > begin) {
1960
        mapping = array_insert(&(s->mapping), index, 1);
1961
        mapping->path = NULL;
1962
        adjust_mapping_indices(s, index, +1);
1963
    }
1964

    
1965
    mapping->begin = begin;
1966
    mapping->end = end;
1967

    
1968
DLOG(mapping_t* next_mapping;
1969
assert(index + 1 >= s->mapping.next ||
1970
((next_mapping = array_get(&(s->mapping), index + 1)) &&
1971
 next_mapping->begin >= end)));
1972

    
1973
    if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1974
        s->current_mapping = array_get(&(s->mapping),
1975
                s->current_mapping - first_mapping);
1976

    
1977
    return mapping;
1978
}
1979

    
1980
static int remove_mapping(BDRVVVFATState* s, int mapping_index)
1981
{
1982
    mapping_t* mapping = array_get(&(s->mapping), mapping_index);
1983
    mapping_t* first_mapping = array_get(&(s->mapping), 0);
1984

    
1985
    /* free mapping */
1986
    if (mapping->first_mapping_index < 0)
1987
        free(mapping->path);
1988

    
1989
    /* remove from s->mapping */
1990
    array_remove(&(s->mapping), mapping_index);
1991

    
1992
    /* adjust all references to mappings */
1993
    adjust_mapping_indices(s, mapping_index, -1);
1994

    
1995
    if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1996
        s->current_mapping = array_get(&(s->mapping),
1997
                s->current_mapping - first_mapping);
1998

    
1999
    return 0;
2000
}
2001

    
2002
static void adjust_dirindices(BDRVVVFATState* s, int offset, int adjust)
2003
{
2004
    int i;
2005
    for (i = 0; i < s->mapping.next; i++) {
2006
        mapping_t* mapping = array_get(&(s->mapping), i);
2007
        if (mapping->dir_index >= offset)
2008
            mapping->dir_index += adjust;
2009
        if ((mapping->mode & MODE_DIRECTORY) &&
2010
                mapping->info.dir.first_dir_index >= offset)
2011
            mapping->info.dir.first_dir_index += adjust;
2012
    }
2013
}
2014

    
2015
static direntry_t* insert_direntries(BDRVVVFATState* s,
2016
        int dir_index, int count)
2017
{
2018
    /*
2019
     * make room in s->directory,
2020
     * adjust_dirindices
2021
     */
2022
    direntry_t* result = array_insert(&(s->directory), dir_index, count);
2023
    if (result == NULL)
2024
        return NULL;
2025
    adjust_dirindices(s, dir_index, count);
2026
    return result;
2027
}
2028

    
2029
static int remove_direntries(BDRVVVFATState* s, int dir_index, int count)
2030
{
2031
    int ret = array_remove_slice(&(s->directory), dir_index, count);
2032
    if (ret)
2033
        return ret;
2034
    adjust_dirindices(s, dir_index, -count);
2035
    return 0;
2036
}
2037

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

    
2051
    vvfat_close_current_file(s);
2052

    
2053
    assert(mapping);
2054
    assert(mapping->begin == first_cluster);
2055
    mapping->first_mapping_index = -1;
2056
    mapping->dir_index = dir_index;
2057
    mapping->mode = (dir_index <= 0 || is_directory(direntry)) ?
2058
        MODE_DIRECTORY : MODE_NORMAL;
2059

    
2060
    while (!fat_eof(s, cluster)) {
2061
        uint32_t c, c1;
2062

    
2063
        for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
2064
                c = c1, c1 = modified_fat_get(s, c1));
2065

    
2066
        c++;
2067
        if (c > mapping->end) {
2068
            int index = array_index(&(s->mapping), mapping);
2069
            int i, max_i = s->mapping.next - index;
2070
            for (i = 1; i < max_i && mapping[i].begin < c; i++);
2071
            while (--i > 0)
2072
                remove_mapping(s, index + 1);
2073
        }
2074
        assert(mapping == array_get(&(s->mapping), s->mapping.next - 1)
2075
                || mapping[1].begin >= c);
2076
        mapping->end = c;
2077

    
2078
        if (!fat_eof(s, c1)) {
2079
            int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next);
2080
            mapping_t* next_mapping = i >= s->mapping.next ? NULL :
2081
                array_get(&(s->mapping), i);
2082

    
2083
            if (next_mapping == NULL || next_mapping->begin > c1) {
2084
                int i1 = array_index(&(s->mapping), mapping);
2085

    
2086
                next_mapping = insert_mapping(s, c1, c1+1);
2087

    
2088
                if (c1 < c)
2089
                    i1++;
2090
                mapping = array_get(&(s->mapping), i1);
2091
            }
2092

    
2093
            next_mapping->dir_index = mapping->dir_index;
2094
            next_mapping->first_mapping_index =
2095
                mapping->first_mapping_index < 0 ?
2096
                array_index(&(s->mapping), mapping) :
2097
                mapping->first_mapping_index;
2098
            next_mapping->path = mapping->path;
2099
            next_mapping->mode = mapping->mode;
2100
            next_mapping->read_only = mapping->read_only;
2101
            if (mapping->mode & MODE_DIRECTORY) {
2102
                next_mapping->info.dir.parent_mapping_index =
2103
                        mapping->info.dir.parent_mapping_index;
2104
                next_mapping->info.dir.first_dir_index =
2105
                        mapping->info.dir.first_dir_index +
2106
                        0x10 * s->sectors_per_cluster *
2107
                        (mapping->end - mapping->begin);
2108
            } else
2109
                next_mapping->info.file.offset = mapping->info.file.offset +
2110
                        mapping->end - mapping->begin;
2111

    
2112
            mapping = next_mapping;
2113
        }
2114

    
2115
        cluster = c1;
2116
    }
2117

    
2118
    return 0;
2119
}
2120

    
2121
static int commit_direntries(BDRVVVFATState* s,
2122
        int dir_index, int parent_mapping_index)
2123
{
2124
    direntry_t* direntry = array_get(&(s->directory), dir_index);
2125
    uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
2126
    mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2127

    
2128
    int factor = 0x10 * s->sectors_per_cluster;
2129
    int old_cluster_count, new_cluster_count;
2130
    int current_dir_index = mapping->info.dir.first_dir_index;
2131
    int first_dir_index = current_dir_index;
2132
    int ret, i;
2133
    uint32_t c;
2134

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

    
2137
    assert(direntry);
2138
    assert(mapping);
2139
    assert(mapping->begin == first_cluster);
2140
    assert(mapping->info.dir.first_dir_index < s->directory.next);
2141
    assert(mapping->mode & MODE_DIRECTORY);
2142
    assert(dir_index == 0 || is_directory(direntry));
2143

    
2144
    mapping->info.dir.parent_mapping_index = parent_mapping_index;
2145

    
2146
    if (first_cluster == 0) {
2147
        old_cluster_count = new_cluster_count =
2148
            s->last_cluster_of_root_directory;
2149
    } else {
2150
        for (old_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2151
                c = fat_get(s, c))
2152
            old_cluster_count++;
2153

    
2154
        for (new_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2155
                c = modified_fat_get(s, c))
2156
            new_cluster_count++;
2157
    }
2158

    
2159
    if (new_cluster_count > old_cluster_count) {
2160
        if (insert_direntries(s,
2161
                current_dir_index + factor * old_cluster_count,
2162
                factor * (new_cluster_count - old_cluster_count)) == NULL)
2163
            return -1;
2164
    } else if (new_cluster_count < old_cluster_count)
2165
        remove_direntries(s,
2166
                current_dir_index + factor * new_cluster_count,
2167
                factor * (old_cluster_count - new_cluster_count));
2168

    
2169
    for (c = first_cluster; !fat_eof(s, c); c = modified_fat_get(s, c)) {
2170
        void* direntry = array_get(&(s->directory), current_dir_index);
2171
        int ret = vvfat_read(s->bs, cluster2sector(s, c), direntry,
2172
                s->sectors_per_cluster);
2173
        if (ret)
2174
            return ret;
2175
        assert(!strncmp(s->directory.pointer, "QEMU", 4));
2176
        current_dir_index += factor;
2177
    }
2178

    
2179
    ret = commit_mappings(s, first_cluster, dir_index);
2180
    if (ret)
2181
        return ret;
2182

    
2183
    /* recurse */
2184
    for (i = 0; i < factor * new_cluster_count; i++) {
2185
        direntry = array_get(&(s->directory), first_dir_index + i);
2186
        if (is_directory(direntry) && !is_dot(direntry)) {
2187
            mapping = find_mapping_for_cluster(s, first_cluster);
2188
            assert(mapping->mode & MODE_DIRECTORY);
2189
            ret = commit_direntries(s, first_dir_index + i,
2190
                array_index(&(s->mapping), mapping));
2191
            if (ret)
2192
                return ret;
2193
        }
2194
    }
2195

    
2196
    return 0;
2197
}
2198

    
2199
/* commit one file (adjust contents, adjust mapping),
2200
   return first_mapping_index */
2201
static int commit_one_file(BDRVVVFATState* s,
2202
        int dir_index, uint32_t offset)
2203
{
2204
    direntry_t* direntry = array_get(&(s->directory), dir_index);
2205
    uint32_t c = begin_of_direntry(direntry);
2206
    uint32_t first_cluster = c;
2207
    mapping_t* mapping = find_mapping_for_cluster(s, c);
2208
    uint32_t size = filesize_of_direntry(direntry);
2209
    char* cluster = malloc(s->cluster_size);
2210
    uint32_t i;
2211
    int fd = 0;
2212

    
2213
    assert(offset < size);
2214
    assert((offset % s->cluster_size) == 0);
2215

    
2216
    for (i = s->cluster_size; i < offset; i += s->cluster_size)
2217
        c = modified_fat_get(s, c);
2218

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

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

    
2235
        c1 = modified_fat_get(s, c);
2236

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

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

    
2243
        if (ret < 0)
2244
            return ret;
2245

    
2246
        if (write(fd, cluster, rest_size) < 0)
2247
            return -2;
2248

    
2249
        offset += rest_size;
2250
        c = c1;
2251
    }
2252

    
2253
    ftruncate(fd, size);
2254
    close(fd);
2255

    
2256
    return commit_mappings(s, first_cluster, dir_index);
2257
}
2258

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

    
2281
/* test, if all direntries have mappings */
2282
static void check2(BDRVVVFATState* s)
2283
{
2284
    int i;
2285
    int first_mapping = -1;
2286

    
2287
    for (i = 0; i < s->directory.next; i++) {
2288
        direntry_t* direntry = array_get(&(s->directory), i);
2289

    
2290
        if (is_short_name(direntry) && begin_of_direntry(direntry)) {
2291
            mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
2292
            assert(mapping);
2293
            assert(mapping->dir_index == i || is_dot(direntry));
2294
            assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry));
2295
        }
2296

    
2297
        if ((i % (0x10 * s->sectors_per_cluster)) == 0) {
2298
            /* cluster start */
2299
            int j, count = 0;
2300

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

    
2329
static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2330
{
2331
    int i;
2332

    
2333
#ifdef DEBUG
2334
    fprintf(stderr, "handle_renames\n");
2335
    for (i = 0; i < s->commits.next; i++) {
2336
        commit_t* commit = array_get(&(s->commits), i);
2337
        fprintf(stderr, "%d, %s (%d, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action);
2338
    }
2339
#endif
2340

    
2341
    for (i = 0; i < s->commits.next;) {
2342
        commit_t* commit = array_get(&(s->commits), i);
2343
        if (commit->action == ACTION_RENAME) {
2344
            mapping_t* mapping = find_mapping_for_cluster(s,
2345
                    commit->param.rename.cluster);
2346
            char* old_path = mapping->path;
2347

    
2348
            assert(commit->path);
2349
            mapping->path = commit->path;
2350
            if (rename(old_path, mapping->path))
2351
                return -2;
2352

    
2353
            if (mapping->mode & MODE_DIRECTORY) {
2354
                int l1 = strlen(mapping->path);
2355
                int l2 = strlen(old_path);
2356
                int diff = l1 - l2;
2357
                direntry_t* direntry = array_get(&(s->directory),
2358
                        mapping->info.dir.first_dir_index);
2359
                uint32_t c = mapping->begin;
2360
                int i = 0;
2361

    
2362
                /* recurse */
2363
                while (!fat_eof(s, c)) {
2364
                    do {
2365
                        direntry_t* d = direntry + i;
2366

    
2367
                        if (is_file(d) || (is_directory(d) && !is_dot(d))) {
2368
                            mapping_t* m = find_mapping_for_cluster(s,
2369
                                    begin_of_direntry(d));
2370
                            int l = strlen(m->path);
2371
                            char* new_path = malloc(l + diff + 1);
2372

    
2373
                            assert(!strncmp(m->path, mapping->path, l2));
2374

    
2375
                            strcpy(new_path, mapping->path);
2376
                            strcpy(new_path + l1, m->path + l2);
2377

    
2378
                            schedule_rename(s, m->begin, new_path);
2379
                        }
2380
                        i++;
2381
                    } while((i % (0x10 * s->sectors_per_cluster)) != 0);
2382
                    c = fat_get(s, c);
2383
                }
2384
            }
2385

    
2386
            free(old_path);
2387
            array_remove(&(s->commits), i);
2388
            continue;
2389
        } else if (commit->action == ACTION_MKDIR) {
2390
            mapping_t* mapping;
2391
            int j, parent_path_len;
2392

    
2393
#ifdef __MINGW32__
2394
            if (mkdir(commit->path))
2395
                return -5;
2396
#else
2397
            if (mkdir(commit->path, 0755))
2398
                return -5;
2399
#endif
2400

    
2401
            mapping = insert_mapping(s, commit->param.mkdir.cluster,
2402
                    commit->param.mkdir.cluster + 1);
2403
            if (mapping == NULL)
2404
                return -6;
2405

    
2406
            mapping->mode = MODE_DIRECTORY;
2407
            mapping->read_only = 0;
2408
            mapping->path = commit->path;
2409
            j = s->directory.next;
2410
            assert(j);
2411
            insert_direntries(s, s->directory.next,
2412
                    0x10 * s->sectors_per_cluster);
2413
            mapping->info.dir.first_dir_index = j;
2414

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

    
2427
            array_remove(&(s->commits), i);
2428
            continue;
2429
        }
2430

    
2431
        i++;
2432
    }
2433
    return 0;
2434
}
2435

    
2436
/*
2437
 * TODO: make sure that the short name is not matching *another* file
2438
 */
2439
static int handle_commits(BDRVVVFATState* s)
2440
{
2441
    int i, fail = 0;
2442

    
2443
    vvfat_close_current_file(s);
2444

    
2445
    for (i = 0; !fail && i < s->commits.next; i++) {
2446
        commit_t* commit = array_get(&(s->commits), i);
2447
        switch(commit->action) {
2448
        case ACTION_RENAME: case ACTION_MKDIR:
2449
            assert(0);
2450
            fail = -2;
2451
            break;
2452
        case ACTION_WRITEOUT: {
2453
            direntry_t* entry = array_get(&(s->directory),
2454
                    commit->param.writeout.dir_index);
2455
            uint32_t begin = begin_of_direntry(entry);
2456
            mapping_t* mapping = find_mapping_for_cluster(s, begin);
2457

    
2458
            assert(mapping);
2459
            assert(mapping->begin == begin);
2460
            assert(commit->path == NULL);
2461

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

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

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

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

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

    
2501
            if (commit_one_file(s, i, 0))
2502
                fail = -7;
2503

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

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

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

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

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

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

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

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

    
2571
    return 0;
2572
}
2573

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

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

    
2590
    vvfat_close_current_file(s);
2591

    
2592
    ret = handle_renames_and_mkdirs(s);
2593
    if (ret) {
2594
        fprintf(stderr, "Error handling renames (%d)\n", ret);
2595
        assert(0);
2596
        return ret;
2597
    }
2598

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

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

    
2610
    ret = handle_commits(s);
2611
    if (ret) {
2612
        fprintf(stderr, "Error handling commits (%d)\n", ret);
2613
        assert(0);
2614
        return ret;
2615
    }
2616

    
2617
    ret = handle_deletes(s);
2618
    if (ret) {
2619
        fprintf(stderr, "Error deleting\n");
2620
        assert(0);
2621
        return ret;
2622
    }
2623

    
2624
    s->qcow->drv->bdrv_make_empty(s->qcow);
2625

    
2626
    memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
2627

    
2628
DLOG(checkpoint());
2629
    return 0;
2630
}
2631

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

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

    
2647
DLOG(checkpoint());
2648

    
2649
    vvfat_close_current_file(s);
2650

    
2651
    /*
2652
     * Some sanity checks:
2653
     * - do not allow writing to the boot sector
2654
     * - do not allow to write non-ASCII filenames
2655
     */
2656

    
2657
    if (sector_num < s->first_sectors_number)
2658
        return -1;
2659

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

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

    
2677
                lfn_init(&lfn);
2678

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

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

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

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

    
2725
DLOG(checkpoint());
2726
    /* TODO: add timeout */
2727
    try_commit(s);
2728

    
2729
DLOG(checkpoint());
2730
    return 0;
2731
}
2732

    
2733
static int vvfat_is_allocated(BlockDriverState *bs,
2734
        int64_t sector_num, int nb_sectors, int* n)
2735
{
2736
    BDRVVVFATState* s = bs->opaque;
2737
    *n = s->sector_count - sector_num;
2738
    if (*n > nb_sectors)
2739
        *n = nb_sectors;
2740
    else if (*n < 0)
2741
        return 0;
2742
    return 1;
2743
}
2744

    
2745
static int write_target_commit(BlockDriverState *bs, int64_t sector_num,
2746
        const uint8_t* buffer, int nb_sectors) {
2747
    BDRVVVFATState* s = bs->opaque;
2748
    return try_commit(s);
2749
}
2750

    
2751
static void write_target_close(BlockDriverState *bs) {
2752
    BDRVVVFATState* s = bs->opaque;
2753
    bdrv_delete(s->qcow);
2754
    free(s->qcow_filename);
2755
}
2756

    
2757
static BlockDriver vvfat_write_target = {
2758
    "vvfat_write_target", 0, NULL, NULL, NULL,
2759
    write_target_commit,
2760
    write_target_close,
2761
    NULL, NULL, NULL
2762
};
2763

    
2764
static int enable_write_target(BDRVVVFATState *s)
2765
{
2766
    int size = sector2cluster(s, s->sector_count);
2767
    s->used_clusters = calloc(size, 1);
2768

    
2769
    array_init(&(s->commits), sizeof(commit_t));
2770

    
2771
    s->qcow_filename = malloc(1024);
2772
    get_tmp_filename(s->qcow_filename, 1024);
2773
    if (bdrv_create(&bdrv_qcow,
2774
                s->qcow_filename, s->sector_count, "fat:", 0) < 0)
2775
        return -1;
2776
    s->qcow = bdrv_new("");
2777
    if (s->qcow == NULL || bdrv_open(s->qcow, s->qcow_filename, 0) < 0)
2778
        return -1;
2779

    
2780
#ifndef _WIN32
2781
    unlink(s->qcow_filename);
2782
#endif
2783

    
2784
    s->bs->backing_hd = calloc(sizeof(BlockDriverState), 1);
2785
    s->bs->backing_hd->drv = &vvfat_write_target;
2786
    s->bs->backing_hd->opaque = s;
2787

    
2788
    return 0;
2789
}
2790

    
2791
static void vvfat_close(BlockDriverState *bs)
2792
{
2793
    BDRVVVFATState *s = bs->opaque;
2794

    
2795
    vvfat_close_current_file(s);
2796
    array_free(&(s->fat));
2797
    array_free(&(s->directory));
2798
    array_free(&(s->mapping));
2799
    if(s->cluster_buffer)
2800
        free(s->cluster_buffer);
2801
}
2802

    
2803
BlockDriver bdrv_vvfat = {
2804
    "vvfat",
2805
    sizeof(BDRVVVFATState),
2806
    NULL, /* no probe for protocols */
2807
    vvfat_open,
2808
    vvfat_read,
2809
    vvfat_write,
2810
    vvfat_close,
2811
    NULL, /* ??? Not sure if we can do any meaningful flushing.  */
2812
    NULL,
2813
    vvfat_is_allocated,
2814
    .protocol_name = "fat",
2815
};
2816

    
2817
#ifdef DEBUG
2818
static void checkpoint(void) {
2819
    assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2);
2820
    check1(vvv);
2821
    check2(vvv);
2822
    assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY));
2823
#if 0
2824
    if (((direntry_t*)vvv->directory.pointer)[1].attributes != 0xf)
2825
        fprintf(stderr, "Nonono!\n");
2826
    mapping_t* mapping;
2827
    direntry_t* direntry;
2828
    assert(vvv->mapping.size >= vvv->mapping.item_size * vvv->mapping.next);
2829
    assert(vvv->directory.size >= vvv->directory.item_size * vvv->directory.next);
2830
    if (vvv->mapping.next<47)
2831
        return;
2832
    assert((mapping = array_get(&(vvv->mapping), 47)));
2833
    assert(mapping->dir_index < vvv->directory.next);
2834
    direntry = array_get(&(vvv->directory), mapping->dir_index);
2835
    assert(!memcmp(direntry->name, "USB     H  ", 11) || direntry->name[0]==0);
2836
#endif
2837
    return;
2838
    /* avoid compiler warnings: */
2839
    hexdump(NULL, 100);
2840
    remove_mapping(vvv, NULL);
2841
    print_mapping(NULL);
2842
    print_direntry(NULL);
2843
}
2844
#endif
2845