Statistics
| Branch: | Revision:

root / block / vvfat.c @ 43dc2a64

History | View | Annotate | Download (80.3 kB)

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

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

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

    
46
/* #define DEBUG */
47

    
48
#ifdef DEBUG
49

    
50
#define DLOG(a) a
51

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

    
56
static void checkpoint(void);
57

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

    
67
#else
68

    
69
#define DLOG(a)
70

    
71
#endif
72

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

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

    
87
static inline void array_free(array_t* array)
88
{
89
    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 NULL;
133
        array->size+=increment;
134
    }
135
    memmove(array->pointer+(index+count)*array->item_size,
136
                array->pointer+index*array->item_size,
137
                (array->next-index)*array->item_size);
138
    array->next+=count;
139
    return array->pointer+index*array->item_size;
140
}
141

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

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

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

    
159
    is=array->item_size;
160
    from=array->pointer+index_from*is;
161
    to=array->pointer+index_to*is;
162
    buf=qemu_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
        unsigned char c;
514

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

    
519
    return chksum;
520
}
521

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

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

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

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

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

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

    
602
}
603

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

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

    
620
    entry_long=create_long_filename(s,filename);
621

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

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

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

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

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

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

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

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

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

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

    
688
    return entry;
689
}
690

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
814
    return 0;
815
}
816

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

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

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

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

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

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

    
851
    s->cluster_size=s->sectors_per_cluster*0x200;
852
    s->cluster_buffer=qemu_malloc(s->cluster_size);
853

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

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

    
867
    /* add volume label */
868
    {
869
        direntry_t* entry=array_get_next(&(s->directory));
870
        entry->attributes=0x28; /* archive | volume label */
871
        memcpy(entry->name,"QEMU VVF",8);
872
        memcpy(entry->extension,"AT ",3);
873
    }
874

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

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

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

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

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

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

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

    
927
        /* next free cluster */
928
        cluster = mapping->end;
929

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

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

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

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

    
956
    s->current_mapping = NULL;
957

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

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

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

    
987
    return 0;
988
}
989

    
990
#ifdef DEBUG
991
static BDRVVVFATState *vvv = NULL;
992
#endif
993

    
994
static int enable_write_target(BDRVVVFATState *s);
995
static int is_consistent(BDRVVVFATState *s);
996

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

    
1003
#ifdef DEBUG
1004
    vvv = s;
1005
#endif
1006

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

    
1012
    s->bs = bs;
1013

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

    
1020
    s->current_cluster=0xffffffff;
1021

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

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

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

    
1041
    s->sector_count=bs->cyls*bs->heads*bs->secs;
1042

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

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

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

    
1067
    bs->total_sectors=bs->cyls*bs->heads*bs->secs;
1068

    
1069
    if(init_directories(s, dirname))
1070
        return -1;
1071

    
1072
    s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
1073

    
1074
    if(s->first_sectors_number==0x40)
1075
        init_mbr(s);
1076

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

    
1081
    //    assert(is_consistent(s));
1082
    return 0;
1083
}
1084

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

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

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

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

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

    
1156
    return NULL;
1157
}
1158

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

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

    
1188
            assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
1189

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

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

    
1208
        assert(s->current_fd);
1209

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

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

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

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

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

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

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

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

    
1328
/* LATER TODO: statify all functions */
1329

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

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

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

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

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

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

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

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

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

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

    
1440
    if (!is_long_name(direntry))
1441
        return 1;
1442

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

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

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

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

    
1473
    return 0;
1474
}
1475

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

    
1482
    if (!is_short_name(direntry))
1483
        return 1;
1484

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

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

    
1510
    lfn->len = strlen((char*)lfn->name);
1511

    
1512
    return 0;
1513
}
1514

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

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

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

    
1542
    if (s->qcow == NULL)
1543
        return 0;
1544

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

    
1549
    return was_modified;
1550
}
1551

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

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

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

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

    
1612
    vvfat_close_current_file(s);
1613

    
1614
    /* the root directory */
1615
    if (cluster_num == 0)
1616
        return 0;
1617

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

    
1622
        mapping = find_mapping_for_cluster(s, cluster_num);
1623

    
1624
        if (mapping) {
1625
            const char* basename;
1626

    
1627
            assert(mapping->mode & MODE_DELETED);
1628
            mapping->mode &= ~MODE_DELETED;
1629

    
1630
            basename = get_basename(mapping->path);
1631

    
1632
            assert(mapping->mode & MODE_NORMAL);
1633

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

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

    
1654

    
1655
                if (mapping &&
1656
                        (mapping->mode & MODE_DIRECTORY) == 0) {
1657

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

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

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

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

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

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

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

    
1713
        cluster_num = modified_fat_get(s, cluster_num);
1714

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

    
1720
        offset += s->cluster_size;
1721
    }
1722
}
1723

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

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

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

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

    
1750
        assert(mapping->mode & MODE_DIRECTORY);
1751

    
1752
        assert(mapping->mode & MODE_DELETED);
1753
        mapping->mode &= ~MODE_DELETED;
1754

    
1755
        if (strcmp(basename, basename2))
1756
            schedule_rename(s, cluster_num, qemu_strdup(path));
1757
    } else
1758
        /* new directory */
1759
        schedule_mkdir(s, cluster_num, qemu_strdup(path));
1760

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

    
1766
        ret++;
1767

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

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

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

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

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

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

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

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

    
1842
            ret += cluster_count;
1843
        }
1844

    
1845
        cluster_num = modified_fat_get(s, cluster_num);
1846
    } while(!fat_eof(s, cluster_num));
1847

    
1848
    free(cluster);
1849
    return ret;
1850
}
1851

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

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

    
1887
    clear_commits(s);
1888

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

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

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

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

    
1921
    if (check != used_clusters_count)
1922
        return 0;
1923

    
1924
    return used_clusters_count;
1925
}
1926

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

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

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

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

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

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

    
1972
    mapping->begin = begin;
1973
    mapping->end = end;
1974

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

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

    
1984
    return mapping;
1985
}
1986

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

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

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

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

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

    
2006
    return 0;
2007
}
2008

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

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

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

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

    
2058
    vvfat_close_current_file(s);
2059

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

    
2067
    while (!fat_eof(s, cluster)) {
2068
        uint32_t c, c1;
2069

    
2070
        for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
2071
                c = c1, c1 = modified_fat_get(s, c1));
2072

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

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

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

    
2093
                next_mapping = insert_mapping(s, c1, c1+1);
2094

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

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

    
2119
            mapping = next_mapping;
2120
        }
2121

    
2122
        cluster = c1;
2123
    }
2124

    
2125
    return 0;
2126
}
2127

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

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

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

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

    
2151
    mapping->info.dir.parent_mapping_index = parent_mapping_index;
2152

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

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

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

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

    
2186
    ret = commit_mappings(s, first_cluster, dir_index);
2187
    if (ret)
2188
        return ret;
2189

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

    
2203
    return 0;
2204
}
2205

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

    
2220
    assert(offset < size);
2221
    assert((offset % s->cluster_size) == 0);
2222

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

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

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

    
2242
        c1 = modified_fat_get(s, c);
2243

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

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

    
2250
        if (ret < 0)
2251
            return ret;
2252

    
2253
        if (write(fd, cluster, rest_size) < 0)
2254
            return -2;
2255

    
2256
        offset += rest_size;
2257
        c = c1;
2258
    }
2259

    
2260
    if (ftruncate(fd, size)) {
2261
        perror("ftruncate()");
2262
        close(fd);
2263
        return -4;
2264
    }
2265
    close(fd);
2266

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

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

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

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

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

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

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

    
2340
static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2341
{
2342
    int i;
2343

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

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

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

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

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

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

    
2384
                            assert(!strncmp(m->path, mapping->path, l2));
2385

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

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

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

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

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

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

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

    
2439
            array_remove(&(s->commits), i);
2440
            continue;
2441
        }
2442

    
2443
        i++;
2444
    }
2445
    return 0;
2446
}
2447

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

    
2455
    vvfat_close_current_file(s);
2456

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

    
2473
            assert(mapping);
2474
            assert(mapping->begin == begin);
2475
            assert(commit->path == NULL);
2476

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

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

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

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

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

    
2516
            if (commit_one_file(s, i, 0))
2517
                fail = -7;
2518

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

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

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

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

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

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

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

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

    
2586
    return 0;
2587
}
2588

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

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

    
2605
    vvfat_close_current_file(s);
2606

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

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

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

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

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

    
2639
    s->qcow->drv->bdrv_make_empty(s->qcow);
2640

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

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

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

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

    
2662
DLOG(checkpoint());
2663

    
2664
    vvfat_close_current_file(s);
2665

    
2666
    /*
2667
     * Some sanity checks:
2668
     * - do not allow writing to the boot sector
2669
     * - do not allow to write non-ASCII filenames
2670
     */
2671

    
2672
    if (sector_num < s->first_sectors_number)
2673
        return -1;
2674

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

    
2685
            if (mapping->mode & MODE_DIRECTORY) {
2686
                int begin = cluster2sector(s, i);
2687
                int end = begin + s->sectors_per_cluster, k;
2688
                int dir_index;
2689
                const direntry_t* direntries;
2690
                long_file_name lfn;
2691

    
2692
                lfn_init(&lfn);
2693

    
2694
                if (begin < sector_num)
2695
                    begin = sector_num;
2696
                if (end > sector_num + nb_sectors)
2697
                    end = sector_num + nb_sectors;
2698
                dir_index  = mapping->dir_index +
2699
                    0x10 * (begin - mapping->begin * s->sectors_per_cluster);
2700
                direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
2701

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

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

    
2735
    for (i = sector2cluster(s, sector_num);
2736
            i <= sector2cluster(s, sector_num + nb_sectors - 1); i++)
2737
        if (i >= 0)
2738
            s->used_clusters[i] |= USED_ALLOCATED;
2739

    
2740
DLOG(checkpoint());
2741
    /* TODO: add timeout */
2742
    try_commit(s);
2743

    
2744
DLOG(checkpoint());
2745
    return 0;
2746
}
2747

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

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

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

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

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

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

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

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

    
2795
    if (bdrv_create(bdrv_qcow, s->qcow_filename, options) < 0)
2796
        return -1;
2797
    s->qcow = bdrv_new("");
2798
    if (s->qcow == NULL || bdrv_open(s->qcow, s->qcow_filename, BDRV_O_RDWR) < 0)
2799
        return -1;
2800

    
2801
#ifndef _WIN32
2802
    unlink(s->qcow_filename);
2803
#endif
2804

    
2805
    s->bs->backing_hd = calloc(sizeof(BlockDriverState), 1);
2806
    s->bs->backing_hd->drv = &vvfat_write_target;
2807
    s->bs->backing_hd->opaque = s;
2808

    
2809
    return 0;
2810
}
2811

    
2812
static void vvfat_close(BlockDriverState *bs)
2813
{
2814
    BDRVVVFATState *s = bs->opaque;
2815

    
2816
    vvfat_close_current_file(s);
2817
    array_free(&(s->fat));
2818
    array_free(&(s->directory));
2819
    array_free(&(s->mapping));
2820
    if(s->cluster_buffer)
2821
        free(s->cluster_buffer);
2822
}
2823

    
2824
static BlockDriver bdrv_vvfat = {
2825
    .format_name        = "vvfat",
2826
    .instance_size        = sizeof(BDRVVVFATState),
2827
    .bdrv_open                = vvfat_open,
2828
    .bdrv_read                = vvfat_read,
2829
    .bdrv_write                = vvfat_write,
2830
    .bdrv_close                = vvfat_close,
2831
    .bdrv_is_allocated        = vvfat_is_allocated,
2832
    .protocol_name        = "fat",
2833
};
2834

    
2835
static void bdrv_vvfat_init(void)
2836
{
2837
    bdrv_register(&bdrv_vvfat);
2838
}
2839

    
2840
block_init(bdrv_vvfat_init);
2841

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