Statistics
| Branch: | Revision:

root / block-vvfat.c @ 1d6198c3

History | View | Annotate | Download (79.5 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 = qemu_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=qemu_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
    memcpy(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
        /* MS-DOS expects the FAT to be 0 for the root directory
894
         * (except for the media byte). */
895
        /* LATER TODO: still true for FAT32? */
896
        int fix_fat = (i != 0);
897
        mapping = array_get(&(s->mapping), i);
898

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

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

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

    
925
        /* next free cluster */
926
        cluster = mapping->end;
927

    
928
        if(cluster > s->cluster_count) {
929
            fprintf(stderr,"Directory does not fit in FAT%d (capacity %s)\n",
930
                    s->fat_type,
931
                    s->fat_type == 12 ? s->sector_count == 2880 ? "1.44 MB"
932
                                                                : "2.88 MB"
933
                                      : "504MB");
934
            return -EINVAL;
935
        }
936

    
937
        /* fix fat for entry */
938
        if (fix_fat) {
939
            int j;
940
            for(j = mapping->begin; j < mapping->end - 1; j++)
941
                fat_set(s, j, j+1);
942
            fat_set(s, mapping->end - 1, s->max_fat_value);
943
        }
944
    }
945

    
946
    mapping = array_get(&(s->mapping), 0);
947
    s->sectors_of_root_directory = mapping->end * s->sectors_per_cluster;
948
    s->last_cluster_of_root_directory = mapping->end;
949

    
950
    /* the FAT signature */
951
    fat_set(s,0,s->max_fat_value);
952
    fat_set(s,1,s->max_fat_value);
953

    
954
    s->current_mapping = NULL;
955

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

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

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

    
985
    return 0;
986
}
987

    
988
#ifdef DEBUG
989
static BDRVVVFATState *vvv = NULL;
990
#endif
991

    
992
static int enable_write_target(BDRVVVFATState *s);
993
static int is_consistent(BDRVVVFATState *s);
994

    
995
static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
996
{
997
    BDRVVVFATState *s = bs->opaque;
998
    int floppy = 0;
999
    int i;
1000

    
1001
#ifdef DEBUG
1002
    vvv = s;
1003
#endif
1004

    
1005
DLOG(if (stderr == NULL) {
1006
    stderr = fopen("vvfat.log", "a");
1007
    setbuf(stderr, NULL);
1008
})
1009

    
1010
    s->bs = bs;
1011

    
1012
    s->fat_type=16;
1013
    /* LATER TODO: if FAT32, adjust */
1014
    s->sectors_per_cluster=0x10;
1015
    /* 504MB disk*/
1016
    bs->cyls=1024; bs->heads=16; bs->secs=63;
1017

    
1018
    s->current_cluster=0xffffffff;
1019

    
1020
    s->first_sectors_number=0x40;
1021
    /* read only is the default for safety */
1022
    bs->read_only = 1;
1023
    s->qcow = s->write_target = NULL;
1024
    s->qcow_filename = NULL;
1025
    s->fat2 = NULL;
1026
    s->downcase_short_names = 1;
1027

    
1028
    if (!strstart(dirname, "fat:", NULL))
1029
        return -1;
1030

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

    
1039
    s->sector_count=bs->cyls*bs->heads*bs->secs;
1040

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

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

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

    
1065
    bs->total_sectors=bs->cyls*bs->heads*bs->secs;
1066

    
1067
    if(init_directories(s, dirname))
1068
        return -1;
1069

    
1070
    s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
1071

    
1072
    if(s->first_sectors_number==0x40)
1073
        init_mbr(s);
1074

    
1075
    /* for some reason or other, MS-DOS does not like to know about CHS... */
1076
    if (floppy)
1077
        bs->heads = bs->cyls = bs->secs = 0;
1078

    
1079
    //    assert(is_consistent(s));
1080
    return 0;
1081
}
1082

    
1083
static inline void vvfat_close_current_file(BDRVVVFATState *s)
1084
{
1085
    if(s->current_mapping) {
1086
        s->current_mapping = NULL;
1087
        if (s->current_fd) {
1088
                close(s->current_fd);
1089
                s->current_fd = 0;
1090
        }
1091
    }
1092
    s->current_cluster = -1;
1093
}
1094

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

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

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

    
1147
    for (i = 0; i < s->mapping.next; i++) {
1148
        mapping_t* mapping = array_get(&(s->mapping), i);
1149
        if (mapping->first_mapping_index < 0 &&
1150
                !strcmp(path, mapping->path))
1151
            return mapping;
1152
    }
1153

    
1154
    return NULL;
1155
}
1156

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

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

    
1186
            assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
1187

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

    
1201
            if(open_file(s,mapping))
1202
                return -2;
1203
        } else if (s->current_mapping->mode & MODE_DIRECTORY)
1204
            goto read_cluster_directory;
1205

    
1206
        assert(s->current_fd);
1207

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

    
1222
#ifdef DEBUG
1223
static void hexdump(const void* address, uint32_t len)
1224
{
1225
    const unsigned char* p = address;
1226
    int i, j;
1227

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

    
1240
static void print_direntry(const direntry_t* direntry)
1241
{
1242
    int j = 0;
1243
    char buffer[1024];
1244

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

    
1272
static void print_mapping(const mapping_t* mapping)
1273
{
1274
    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);
1275
    if (mapping->mode & MODE_DIRECTORY)
1276
        fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
1277
    else
1278
        fprintf(stderr, "offset = %d\n", mapping->info.file.offset);
1279
}
1280
#endif
1281

    
1282
static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
1283
                    uint8_t *buf, int nb_sectors)
1284
{
1285
    BDRVVVFATState *s = bs->opaque;
1286
    int i;
1287

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

    
1326
/* LATER TODO: statify all functions */
1327

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

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

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

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

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

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

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

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

    
1425
static void lfn_init(long_file_name* lfn)
1426
{
1427
   lfn->sequence_number = lfn->len = 0;
1428
   lfn->checksum = 0x100;
1429
}
1430

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

    
1438
    if (!is_long_name(direntry))
1439
        return 1;
1440

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

    
1453
    offset = 13 * (lfn->sequence_number - 1);
1454
    for (i = 0, j = 1; i < 13; i++, j+=2) {
1455
        if (j == 11)
1456
            j = 14;
1457
        else if (j == 26)
1458
            j = 28;
1459

    
1460
        if (pointer[j+1] == 0)
1461
            lfn->name[offset + i] = pointer[j];
1462
        else if (pointer[j+1] != 0xff || (pointer[0] & 0x40) == 0)
1463
            return -4;
1464
        else
1465
            lfn->name[offset + i] = 0;
1466
    }
1467

    
1468
    if (pointer[0] & 0x40)
1469
        lfn->len = offset + strlen((char*)lfn->name + offset);
1470

    
1471
    return 0;
1472
}
1473

    
1474
/* returns 0 if successful, >0 if no short_name, and <0 on error */
1475
static int parse_short_name(BDRVVVFATState* s,
1476
        long_file_name* lfn, direntry_t* direntry)
1477
{
1478
    int i, j;
1479

    
1480
    if (!is_short_name(direntry))
1481
        return 1;
1482

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

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

    
1508
    lfn->len = strlen((char*)lfn->name);
1509

    
1510
    return 0;
1511
}
1512

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

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

    
1535
static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num)
1536
{
1537
    int was_modified = 0;
1538
    int i, dummy;
1539

    
1540
    if (s->qcow == NULL)
1541
        return 0;
1542

    
1543
    for (i = 0; !was_modified && i < s->sectors_per_cluster; i++)
1544
        was_modified = s->qcow->drv->bdrv_is_allocated(s->qcow,
1545
                cluster2sector(s, cluster_num) + i, 1, &dummy);
1546

    
1547
    return was_modified;
1548
}
1549

    
1550
static const char* get_basename(const char* path)
1551
{
1552
    char* basename = strrchr(path, '/');
1553
    if (basename == NULL)
1554
        return path;
1555
    else
1556
        return basename + 1; /* strip '/' */
1557
}
1558

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

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

    
1604
    uint32_t cluster_num = begin_of_direntry(direntry);
1605
    uint32_t offset = 0;
1606
    int first_mapping_index = -1;
1607
    mapping_t* mapping = NULL;
1608
    const char* basename2 = NULL;
1609

    
1610
    vvfat_close_current_file(s);
1611

    
1612
    /* the root directory */
1613
    if (cluster_num == 0)
1614
        return 0;
1615

    
1616
    /* write support */
1617
    if (s->qcow) {
1618
        basename2 = get_basename(path);
1619

    
1620
        mapping = find_mapping_for_cluster(s, cluster_num);
1621

    
1622
        if (mapping) {
1623
            const char* basename;
1624

    
1625
            assert(mapping->mode & MODE_DELETED);
1626
            mapping->mode &= ~MODE_DELETED;
1627

    
1628
            basename = get_basename(mapping->path);
1629

    
1630
            assert(mapping->mode & MODE_NORMAL);
1631

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

    
1644
    while(1) {
1645
        if (s->qcow) {
1646
            if (!copy_it && cluster_was_modified(s, cluster_num)) {
1647
                if (mapping == NULL ||
1648
                        mapping->begin > cluster_num ||
1649
                        mapping->end <= cluster_num)
1650
                mapping = find_mapping_for_cluster(s, cluster_num);
1651

    
1652

    
1653
                if (mapping &&
1654
                        (mapping->mode & MODE_DIRECTORY) == 0) {
1655

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

    
1665
                        if (strcmp(basename, basename2))
1666
                            copy_it = 1;
1667
                        first_mapping_index = array_index(&(s->mapping), mapping);
1668
                    }
1669

    
1670
                    if (mapping->first_mapping_index != first_mapping_index
1671
                            && mapping->info.file.offset > 0) {
1672
                        assert(0);
1673
                        copy_it = 1;
1674
                    }
1675

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

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

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

    
1706
        ret++;
1707
        if (s->used_clusters[cluster_num] & USED_ANY)
1708
            return 0;
1709
        s->used_clusters[cluster_num] = USED_FILE;
1710

    
1711
        cluster_num = modified_fat_get(s, cluster_num);
1712

    
1713
        if (fat_eof(s, cluster_num))
1714
            return ret;
1715
        else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
1716
            return -1;
1717

    
1718
        offset += s->cluster_size;
1719
    }
1720
}
1721

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

    
1735
    long_file_name lfn;
1736
    int path_len = strlen(path);
1737
    char path2[PATH_MAX];
1738

    
1739
    assert(path_len < PATH_MAX); /* len was tested before! */
1740
    pstrcpy(path2, sizeof(path2), path);
1741
    path2[path_len] = '/';
1742
    path2[path_len + 1] = '\0';
1743

    
1744
    if (mapping) {
1745
        const char* basename = get_basename(mapping->path);
1746
        const char* basename2 = get_basename(path);
1747

    
1748
        assert(mapping->mode & MODE_DIRECTORY);
1749

    
1750
        assert(mapping->mode & MODE_DELETED);
1751
        mapping->mode &= ~MODE_DELETED;
1752

    
1753
        if (strcmp(basename, basename2))
1754
            schedule_rename(s, cluster_num, strdup(path));
1755
    } else
1756
        /* new directory */
1757
        schedule_mkdir(s, cluster_num, strdup(path));
1758

    
1759
    lfn_init(&lfn);
1760
    do {
1761
        int i;
1762
        int subret = 0;
1763

    
1764
        ret++;
1765

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

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

    
1782
        for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
1783
            int cluster_count;
1784

    
1785
DLOG(fprintf(stderr, "check direntry %d: \n", i); print_direntry(direntries + i));
1786
            if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
1787
                    is_free(direntries + i))
1788
                continue;
1789

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

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

    
1810
            if (path_len + 1 + lfn.len >= PATH_MAX) {
1811
                fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
1812
                goto fail;
1813
            }
1814
            pstrcpy(path2 + path_len + 1, sizeof(path2) - path_len - 1,
1815
                    (char*)lfn.name);
1816

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

    
1840
            ret += cluster_count;
1841
        }
1842

    
1843
        cluster_num = modified_fat_get(s, cluster_num);
1844
    } while(!fat_eof(s, cluster_num));
1845

    
1846
    free(cluster);
1847
    return ret;
1848
}
1849

    
1850
/* returns 1 on success */
1851
static int is_consistent(BDRVVVFATState* s)
1852
{
1853
    int i, check;
1854
    int used_clusters_count = 0;
1855

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

    
1885
    clear_commits(s);
1886

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

    
1896
    used_clusters_count = check_directory_consistency(s, 0, s->path);
1897
    if (used_clusters_count <= 0) {
1898
        DLOG(fprintf(stderr, "problem in directory\n"));
1899
        return 0;
1900
    }
1901

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

    
1912
        if (s->used_clusters[i] == USED_ALLOCATED) {
1913
            /* allocated, but not used... */
1914
            DLOG(fprintf(stderr, "unused, modified cluster: %d\n", i));
1915
            return 0;
1916
        }
1917
    }
1918

    
1919
    if (check != used_clusters_count)
1920
        return 0;
1921

    
1922
    return used_clusters_count;
1923
}
1924

    
1925
static inline void adjust_mapping_indices(BDRVVVFATState* s,
1926
        int offset, int adjust)
1927
{
1928
    int i;
1929

    
1930
    for (i = 0; i < s->mapping.next; i++) {
1931
        mapping_t* mapping = array_get(&(s->mapping), i);
1932

    
1933
#define ADJUST_MAPPING_INDEX(name) \
1934
        if (mapping->name >= offset) \
1935
            mapping->name += adjust
1936

    
1937
        ADJUST_MAPPING_INDEX(first_mapping_index);
1938
        if (mapping->mode & MODE_DIRECTORY)
1939
            ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
1940
    }
1941
}
1942

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

    
1958
    if (index < s->mapping.next && (mapping = array_get(&(s->mapping), index))
1959
            && mapping->begin < begin) {
1960
        mapping->end = begin;
1961
        index++;
1962
        mapping = array_get(&(s->mapping), index);
1963
    }
1964
    if (index >= s->mapping.next || mapping->begin > begin) {
1965
        mapping = array_insert(&(s->mapping), index, 1);
1966
        mapping->path = NULL;
1967
        adjust_mapping_indices(s, index, +1);
1968
    }
1969

    
1970
    mapping->begin = begin;
1971
    mapping->end = end;
1972

    
1973
DLOG(mapping_t* next_mapping;
1974
assert(index + 1 >= s->mapping.next ||
1975
((next_mapping = array_get(&(s->mapping), index + 1)) &&
1976
 next_mapping->begin >= end)));
1977

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

    
1982
    return mapping;
1983
}
1984

    
1985
static int remove_mapping(BDRVVVFATState* s, int mapping_index)
1986
{
1987
    mapping_t* mapping = array_get(&(s->mapping), mapping_index);
1988
    mapping_t* first_mapping = array_get(&(s->mapping), 0);
1989

    
1990
    /* free mapping */
1991
    if (mapping->first_mapping_index < 0)
1992
        free(mapping->path);
1993

    
1994
    /* remove from s->mapping */
1995
    array_remove(&(s->mapping), mapping_index);
1996

    
1997
    /* adjust all references to mappings */
1998
    adjust_mapping_indices(s, mapping_index, -1);
1999

    
2000
    if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
2001
        s->current_mapping = array_get(&(s->mapping),
2002
                s->current_mapping - first_mapping);
2003

    
2004
    return 0;
2005
}
2006

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

    
2020
static direntry_t* insert_direntries(BDRVVVFATState* s,
2021
        int dir_index, int count)
2022
{
2023
    /*
2024
     * make room in s->directory,
2025
     * adjust_dirindices
2026
     */
2027
    direntry_t* result = array_insert(&(s->directory), dir_index, count);
2028
    if (result == NULL)
2029
        return NULL;
2030
    adjust_dirindices(s, dir_index, count);
2031
    return result;
2032
}
2033

    
2034
static int remove_direntries(BDRVVVFATState* s, int dir_index, int count)
2035
{
2036
    int ret = array_remove_slice(&(s->directory), dir_index, count);
2037
    if (ret)
2038
        return ret;
2039
    adjust_dirindices(s, dir_index, -count);
2040
    return 0;
2041
}
2042

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

    
2056
    vvfat_close_current_file(s);
2057

    
2058
    assert(mapping);
2059
    assert(mapping->begin == first_cluster);
2060
    mapping->first_mapping_index = -1;
2061
    mapping->dir_index = dir_index;
2062
    mapping->mode = (dir_index <= 0 || is_directory(direntry)) ?
2063
        MODE_DIRECTORY : MODE_NORMAL;
2064

    
2065
    while (!fat_eof(s, cluster)) {
2066
        uint32_t c, c1;
2067

    
2068
        for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
2069
                c = c1, c1 = modified_fat_get(s, c1));
2070

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

    
2083
        if (!fat_eof(s, c1)) {
2084
            int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next);
2085
            mapping_t* next_mapping = i >= s->mapping.next ? NULL :
2086
                array_get(&(s->mapping), i);
2087

    
2088
            if (next_mapping == NULL || next_mapping->begin > c1) {
2089
                int i1 = array_index(&(s->mapping), mapping);
2090

    
2091
                next_mapping = insert_mapping(s, c1, c1+1);
2092

    
2093
                if (c1 < c)
2094
                    i1++;
2095
                mapping = array_get(&(s->mapping), i1);
2096
            }
2097

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

    
2117
            mapping = next_mapping;
2118
        }
2119

    
2120
        cluster = c1;
2121
    }
2122

    
2123
    return 0;
2124
}
2125

    
2126
static int commit_direntries(BDRVVVFATState* s,
2127
        int dir_index, int parent_mapping_index)
2128
{
2129
    direntry_t* direntry = array_get(&(s->directory), dir_index);
2130
    uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
2131
    mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2132

    
2133
    int factor = 0x10 * s->sectors_per_cluster;
2134
    int old_cluster_count, new_cluster_count;
2135
    int current_dir_index = mapping->info.dir.first_dir_index;
2136
    int first_dir_index = current_dir_index;
2137
    int ret, i;
2138
    uint32_t c;
2139

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

    
2142
    assert(direntry);
2143
    assert(mapping);
2144
    assert(mapping->begin == first_cluster);
2145
    assert(mapping->info.dir.first_dir_index < s->directory.next);
2146
    assert(mapping->mode & MODE_DIRECTORY);
2147
    assert(dir_index == 0 || is_directory(direntry));
2148

    
2149
    mapping->info.dir.parent_mapping_index = parent_mapping_index;
2150

    
2151
    if (first_cluster == 0) {
2152
        old_cluster_count = new_cluster_count =
2153
            s->last_cluster_of_root_directory;
2154
    } else {
2155
        for (old_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2156
                c = fat_get(s, c))
2157
            old_cluster_count++;
2158

    
2159
        for (new_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2160
                c = modified_fat_get(s, c))
2161
            new_cluster_count++;
2162
    }
2163

    
2164
    if (new_cluster_count > old_cluster_count) {
2165
        if (insert_direntries(s,
2166
                current_dir_index + factor * old_cluster_count,
2167
                factor * (new_cluster_count - old_cluster_count)) == NULL)
2168
            return -1;
2169
    } else if (new_cluster_count < old_cluster_count)
2170
        remove_direntries(s,
2171
                current_dir_index + factor * new_cluster_count,
2172
                factor * (old_cluster_count - new_cluster_count));
2173

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

    
2184
    ret = commit_mappings(s, first_cluster, dir_index);
2185
    if (ret)
2186
        return ret;
2187

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

    
2201
    return 0;
2202
}
2203

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

    
2218
    assert(offset < size);
2219
    assert((offset % s->cluster_size) == 0);
2220

    
2221
    for (i = s->cluster_size; i < offset; i += s->cluster_size)
2222
        c = modified_fat_get(s, c);
2223

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

    
2234
    while (offset < size) {
2235
        uint32_t c1;
2236
        int rest_size = (size - offset > s->cluster_size ?
2237
                s->cluster_size : size - offset);
2238
        int ret;
2239

    
2240
        c1 = modified_fat_get(s, c);
2241

    
2242
        assert((size - offset == 0 && fat_eof(s, c)) ||
2243
                (size > offset && c >=2 && !fat_eof(s, c)));
2244

    
2245
        ret = vvfat_read(s->bs, cluster2sector(s, c),
2246
            (uint8_t*)cluster, (rest_size + 0x1ff) / 0x200);
2247

    
2248
        if (ret < 0)
2249
            return ret;
2250

    
2251
        if (write(fd, cluster, rest_size) < 0)
2252
            return -2;
2253

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

    
2258
    ftruncate(fd, size);
2259
    close(fd);
2260

    
2261
    return commit_mappings(s, first_cluster, dir_index);
2262
}
2263

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

    
2286
/* test, if all direntries have mappings */
2287
static void check2(BDRVVVFATState* s)
2288
{
2289
    int i;
2290
    int first_mapping = -1;
2291

    
2292
    for (i = 0; i < s->directory.next; i++) {
2293
        direntry_t* direntry = array_get(&(s->directory), i);
2294

    
2295
        if (is_short_name(direntry) && begin_of_direntry(direntry)) {
2296
            mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
2297
            assert(mapping);
2298
            assert(mapping->dir_index == i || is_dot(direntry));
2299
            assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry));
2300
        }
2301

    
2302
        if ((i % (0x10 * s->sectors_per_cluster)) == 0) {
2303
            /* cluster start */
2304
            int j, count = 0;
2305

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

    
2334
static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2335
{
2336
    int i;
2337

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

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

    
2353
            assert(commit->path);
2354
            mapping->path = commit->path;
2355
            if (rename(old_path, mapping->path))
2356
                return -2;
2357

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

    
2367
                /* recurse */
2368
                while (!fat_eof(s, c)) {
2369
                    do {
2370
                        direntry_t* d = direntry + i;
2371

    
2372
                        if (is_file(d) || (is_directory(d) && !is_dot(d))) {
2373
                            mapping_t* m = find_mapping_for_cluster(s,
2374
                                    begin_of_direntry(d));
2375
                            int l = strlen(m->path);
2376
                            char* new_path = malloc(l + diff + 1);
2377

    
2378
                            assert(!strncmp(m->path, mapping->path, l2));
2379

    
2380
                            pstrcpy(new_path, l + diff + 1, mapping->path);
2381
                            pstrcpy(new_path + l1, l + diff + 1 - l1,
2382
                                    m->path + l2);
2383

    
2384
                            schedule_rename(s, m->begin, new_path);
2385
                        }
2386
                        i++;
2387
                    } while((i % (0x10 * s->sectors_per_cluster)) != 0);
2388
                    c = fat_get(s, c);
2389
                }
2390
            }
2391

    
2392
            free(old_path);
2393
            array_remove(&(s->commits), i);
2394
            continue;
2395
        } else if (commit->action == ACTION_MKDIR) {
2396
            mapping_t* mapping;
2397
            int j, parent_path_len;
2398

    
2399
#ifdef __MINGW32__
2400
            if (mkdir(commit->path))
2401
                return -5;
2402
#else
2403
            if (mkdir(commit->path, 0755))
2404
                return -5;
2405
#endif
2406

    
2407
            mapping = insert_mapping(s, commit->param.mkdir.cluster,
2408
                    commit->param.mkdir.cluster + 1);
2409
            if (mapping == NULL)
2410
                return -6;
2411

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

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

    
2433
            array_remove(&(s->commits), i);
2434
            continue;
2435
        }
2436

    
2437
        i++;
2438
    }
2439
    return 0;
2440
}
2441

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

    
2449
    vvfat_close_current_file(s);
2450

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

    
2464
            assert(mapping);
2465
            assert(mapping->begin == begin);
2466
            assert(commit->path == NULL);
2467

    
2468
            if (commit_one_file(s, commit->param.writeout.dir_index,
2469
                        commit->param.writeout.modified_offset))
2470
                fail = -3;
2471

    
2472
            break;
2473
        }
2474
        case ACTION_NEW_FILE: {
2475
            int begin = commit->param.new_file.first_cluster;
2476
            mapping_t* mapping = find_mapping_for_cluster(s, begin);
2477
            direntry_t* entry;
2478
            int i;
2479

    
2480
            /* find direntry */
2481
            for (i = 0; i < s->directory.next; i++) {
2482
                entry = array_get(&(s->directory), i);
2483
                if (is_file(entry) && begin_of_direntry(entry) == begin)
2484
                    break;
2485
            }
2486

    
2487
            if (i >= s->directory.next) {
2488
                fail = -6;
2489
                continue;
2490
            }
2491

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

    
2507
            if (commit_one_file(s, i, 0))
2508
                fail = -7;
2509

    
2510
            break;
2511
        }
2512
        default:
2513
            assert(0);
2514
        }
2515
    }
2516
    if (i > 0 && array_remove_slice(&(s->commits), 0, i))
2517
        return -1;
2518
    return fail;
2519
}
2520

    
2521
static int handle_deletes(BDRVVVFATState* s)
2522
{
2523
    int i, deferred = 1, deleted = 1;
2524

    
2525
    /* delete files corresponding to mappings marked as deleted */
2526
    /* handle DELETEs and unused mappings (modified_fat_get(s, mapping->begin) == 0) */
2527
    while (deferred && deleted) {
2528
        deferred = 0;
2529
        deleted = 0;
2530

    
2531
        for (i = 1; i < s->mapping.next; i++) {
2532
            mapping_t* mapping = array_get(&(s->mapping), i);
2533
            if (mapping->mode & MODE_DELETED) {
2534
                direntry_t* entry = array_get(&(s->directory),
2535
                        mapping->dir_index);
2536

    
2537
                if (is_free(entry)) {
2538
                    /* remove file/directory */
2539
                    if (mapping->mode & MODE_DIRECTORY) {
2540
                        int j, next_dir_index = s->directory.next,
2541
                        first_dir_index = mapping->info.dir.first_dir_index;
2542

    
2543
                        if (rmdir(mapping->path) < 0) {
2544
                            if (errno == ENOTEMPTY) {
2545
                                deferred++;
2546
                                continue;
2547
                            } else
2548
                                return -5;
2549
                        }
2550

    
2551
                        for (j = 1; j < s->mapping.next; j++) {
2552
                            mapping_t* m = array_get(&(s->mapping), j);
2553
                            if (m->mode & MODE_DIRECTORY &&
2554
                                    m->info.dir.first_dir_index >
2555
                                    first_dir_index &&
2556
                                    m->info.dir.first_dir_index <
2557
                                    next_dir_index)
2558
                                next_dir_index =
2559
                                    m->info.dir.first_dir_index;
2560
                        }
2561
                        remove_direntries(s, first_dir_index,
2562
                                next_dir_index - first_dir_index);
2563

    
2564
                        deleted++;
2565
                    }
2566
                } else {
2567
                    if (unlink(mapping->path))
2568
                        return -4;
2569
                    deleted++;
2570
                }
2571
                DLOG(fprintf(stderr, "DELETE (%d)\n", i); print_mapping(mapping); print_direntry(entry));
2572
                remove_mapping(s, i);
2573
            }
2574
        }
2575
    }
2576

    
2577
    return 0;
2578
}
2579

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

    
2592
    /* the real meat are the commits. Nothing to do? Move along! */
2593
    if (s->commits.next == 0)
2594
        return 0;
2595

    
2596
    vvfat_close_current_file(s);
2597

    
2598
    ret = handle_renames_and_mkdirs(s);
2599
    if (ret) {
2600
        fprintf(stderr, "Error handling renames (%d)\n", ret);
2601
        assert(0);
2602
        return ret;
2603
    }
2604

    
2605
    /* copy FAT (with bdrv_read) */
2606
    memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
2607

    
2608
    /* recurse direntries from root (using bs->bdrv_read) */
2609
    ret = commit_direntries(s, 0, -1);
2610
    if (ret) {
2611
        fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
2612
        assert(0);
2613
        return ret;
2614
    }
2615

    
2616
    ret = handle_commits(s);
2617
    if (ret) {
2618
        fprintf(stderr, "Error handling commits (%d)\n", ret);
2619
        assert(0);
2620
        return ret;
2621
    }
2622

    
2623
    ret = handle_deletes(s);
2624
    if (ret) {
2625
        fprintf(stderr, "Error deleting\n");
2626
        assert(0);
2627
        return ret;
2628
    }
2629

    
2630
    s->qcow->drv->bdrv_make_empty(s->qcow);
2631

    
2632
    memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
2633

    
2634
DLOG(checkpoint());
2635
    return 0;
2636
}
2637

    
2638
static int try_commit(BDRVVVFATState* s)
2639
{
2640
    vvfat_close_current_file(s);
2641
DLOG(checkpoint());
2642
    if(!is_consistent(s))
2643
        return -1;
2644
    return do_commit(s);
2645
}
2646

    
2647
static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
2648
                    const uint8_t *buf, int nb_sectors)
2649
{
2650
    BDRVVVFATState *s = bs->opaque;
2651
    int i, ret;
2652

    
2653
DLOG(checkpoint());
2654

    
2655
    vvfat_close_current_file(s);
2656

    
2657
    /*
2658
     * Some sanity checks:
2659
     * - do not allow writing to the boot sector
2660
     * - do not allow to write non-ASCII filenames
2661
     */
2662

    
2663
    if (sector_num < s->first_sectors_number)
2664
        return -1;
2665

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

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

    
2683
                lfn_init(&lfn);
2684

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

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

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

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

    
2731
DLOG(checkpoint());
2732
    /* TODO: add timeout */
2733
    try_commit(s);
2734

    
2735
DLOG(checkpoint());
2736
    return 0;
2737
}
2738

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

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

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

    
2763
static BlockDriver vvfat_write_target = {
2764
    "vvfat_write_target", 0, NULL, NULL, NULL,
2765
    write_target_commit,
2766
    write_target_close,
2767
    NULL, NULL, NULL
2768
};
2769

    
2770
static int enable_write_target(BDRVVVFATState *s)
2771
{
2772
    int size = sector2cluster(s, s->sector_count);
2773
    s->used_clusters = calloc(size, 1);
2774

    
2775
    array_init(&(s->commits), sizeof(commit_t));
2776

    
2777
    s->qcow_filename = malloc(1024);
2778
    get_tmp_filename(s->qcow_filename, 1024);
2779
    if (bdrv_create(&bdrv_qcow,
2780
                s->qcow_filename, s->sector_count, "fat:", 0) < 0)
2781
        return -1;
2782
    s->qcow = bdrv_new("");
2783
    if (s->qcow == NULL || bdrv_open(s->qcow, s->qcow_filename, 0) < 0)
2784
        return -1;
2785

    
2786
#ifndef _WIN32
2787
    unlink(s->qcow_filename);
2788
#endif
2789

    
2790
    s->bs->backing_hd = calloc(sizeof(BlockDriverState), 1);
2791
    s->bs->backing_hd->drv = &vvfat_write_target;
2792
    s->bs->backing_hd->opaque = s;
2793

    
2794
    return 0;
2795
}
2796

    
2797
static void vvfat_close(BlockDriverState *bs)
2798
{
2799
    BDRVVVFATState *s = bs->opaque;
2800

    
2801
    vvfat_close_current_file(s);
2802
    array_free(&(s->fat));
2803
    array_free(&(s->directory));
2804
    array_free(&(s->mapping));
2805
    if(s->cluster_buffer)
2806
        free(s->cluster_buffer);
2807
}
2808

    
2809
BlockDriver bdrv_vvfat = {
2810
    "vvfat",
2811
    sizeof(BDRVVVFATState),
2812
    NULL, /* no probe for protocols */
2813
    vvfat_open,
2814
    vvfat_read,
2815
    vvfat_write,
2816
    vvfat_close,
2817
    NULL, /* ??? Not sure if we can do any meaningful flushing.  */
2818
    NULL,
2819
    vvfat_is_allocated,
2820
    .protocol_name = "fat",
2821
};
2822

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