Statistics
| Branch: | Revision:

root / block / vvfat.c @ 9217e26f

History | View | Annotate | Download (80.6 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
    while(1) {
1103
        int index3;
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 %p: ", 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 (%p): begin, end = %d, %d, dir_index = %d, "
1277
        "first_mapping_index = %d, name = %s, mode = 0x%x, " ,
1278
        mapping, mapping->begin, mapping->end, mapping->dir_index,
1279
        mapping->first_mapping_index, mapping->path, mapping->mode);
1280

    
1281
    if (mapping->mode & MODE_DIRECTORY)
1282
        fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
1283
    else
1284
        fprintf(stderr, "offset = %d\n", mapping->info.file.offset);
1285
}
1286
#endif
1287

    
1288
static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
1289
                    uint8_t *buf, int nb_sectors)
1290
{
1291
    BDRVVVFATState *s = bs->opaque;
1292
    int i;
1293

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

    
1332
/* LATER TODO: statify all functions */
1333

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

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

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

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

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

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

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

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

    
1431
static void lfn_init(long_file_name* lfn)
1432
{
1433
   lfn->sequence_number = lfn->len = 0;
1434
   lfn->checksum = 0x100;
1435
}
1436

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

    
1444
    if (!is_long_name(direntry))
1445
        return 1;
1446

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

    
1459
    offset = 13 * (lfn->sequence_number - 1);
1460
    for (i = 0, j = 1; i < 13; i++, j+=2) {
1461
        if (j == 11)
1462
            j = 14;
1463
        else if (j == 26)
1464
            j = 28;
1465

    
1466
        if (pointer[j+1] == 0)
1467
            lfn->name[offset + i] = pointer[j];
1468
        else if (pointer[j+1] != 0xff || (pointer[0] & 0x40) == 0)
1469
            return -4;
1470
        else
1471
            lfn->name[offset + i] = 0;
1472
    }
1473

    
1474
    if (pointer[0] & 0x40)
1475
        lfn->len = offset + strlen((char*)lfn->name + offset);
1476

    
1477
    return 0;
1478
}
1479

    
1480
/* returns 0 if successful, >0 if no short_name, and <0 on error */
1481
static int parse_short_name(BDRVVVFATState* s,
1482
        long_file_name* lfn, direntry_t* direntry)
1483
{
1484
    int i, j;
1485

    
1486
    if (!is_short_name(direntry))
1487
        return 1;
1488

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

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

    
1514
    lfn->len = strlen((char*)lfn->name);
1515

    
1516
    return 0;
1517
}
1518

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

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

    
1541
static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num)
1542
{
1543
    int was_modified = 0;
1544
    int i, dummy;
1545

    
1546
    if (s->qcow == NULL)
1547
        return 0;
1548

    
1549
    for (i = 0; !was_modified && i < s->sectors_per_cluster; i++)
1550
        was_modified = s->qcow->drv->bdrv_is_allocated(s->qcow,
1551
                cluster2sector(s, cluster_num) + i, 1, &dummy);
1552

    
1553
    return was_modified;
1554
}
1555

    
1556
static const char* get_basename(const char* path)
1557
{
1558
    char* basename = strrchr(path, '/');
1559
    if (basename == NULL)
1560
        return path;
1561
    else
1562
        return basename + 1; /* strip '/' */
1563
}
1564

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

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

    
1610
    uint32_t cluster_num = begin_of_direntry(direntry);
1611
    uint32_t offset = 0;
1612
    int first_mapping_index = -1;
1613
    mapping_t* mapping = NULL;
1614
    const char* basename2 = NULL;
1615

    
1616
    vvfat_close_current_file(s);
1617

    
1618
    /* the root directory */
1619
    if (cluster_num == 0)
1620
        return 0;
1621

    
1622
    /* write support */
1623
    if (s->qcow) {
1624
        basename2 = get_basename(path);
1625

    
1626
        mapping = find_mapping_for_cluster(s, cluster_num);
1627

    
1628
        if (mapping) {
1629
            const char* basename;
1630

    
1631
            assert(mapping->mode & MODE_DELETED);
1632
            mapping->mode &= ~MODE_DELETED;
1633

    
1634
            basename = get_basename(mapping->path);
1635

    
1636
            assert(mapping->mode & MODE_NORMAL);
1637

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

    
1650
    while(1) {
1651
        if (s->qcow) {
1652
            if (!copy_it && cluster_was_modified(s, cluster_num)) {
1653
                if (mapping == NULL ||
1654
                        mapping->begin > cluster_num ||
1655
                        mapping->end <= cluster_num)
1656
                mapping = find_mapping_for_cluster(s, cluster_num);
1657

    
1658

    
1659
                if (mapping &&
1660
                        (mapping->mode & MODE_DIRECTORY) == 0) {
1661

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

    
1671
                        if (strcmp(basename, basename2))
1672
                            copy_it = 1;
1673
                        first_mapping_index = array_index(&(s->mapping), mapping);
1674
                    }
1675

    
1676
                    if (mapping->first_mapping_index != first_mapping_index
1677
                            && mapping->info.file.offset > 0) {
1678
                        abort();
1679
                        copy_it = 1;
1680
                    }
1681

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

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

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

    
1712
        ret++;
1713
        if (s->used_clusters[cluster_num] & USED_ANY)
1714
            return 0;
1715
        s->used_clusters[cluster_num] = USED_FILE;
1716

    
1717
        cluster_num = modified_fat_get(s, cluster_num);
1718

    
1719
        if (fat_eof(s, cluster_num))
1720
            return ret;
1721
        else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
1722
            return -1;
1723

    
1724
        offset += s->cluster_size;
1725
    }
1726
}
1727

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

    
1741
    long_file_name lfn;
1742
    int path_len = strlen(path);
1743
    char path2[PATH_MAX];
1744

    
1745
    assert(path_len < PATH_MAX); /* len was tested before! */
1746
    pstrcpy(path2, sizeof(path2), path);
1747
    path2[path_len] = '/';
1748
    path2[path_len + 1] = '\0';
1749

    
1750
    if (mapping) {
1751
        const char* basename = get_basename(mapping->path);
1752
        const char* basename2 = get_basename(path);
1753

    
1754
        assert(mapping->mode & MODE_DIRECTORY);
1755

    
1756
        assert(mapping->mode & MODE_DELETED);
1757
        mapping->mode &= ~MODE_DELETED;
1758

    
1759
        if (strcmp(basename, basename2))
1760
            schedule_rename(s, cluster_num, qemu_strdup(path));
1761
    } else
1762
        /* new directory */
1763
        schedule_mkdir(s, cluster_num, qemu_strdup(path));
1764

    
1765
    lfn_init(&lfn);
1766
    do {
1767
        int i;
1768
        int subret = 0;
1769

    
1770
        ret++;
1771

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

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

    
1788
        for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
1789
            int cluster_count = 0;
1790

    
1791
DLOG(fprintf(stderr, "check direntry %d: \n", i); print_direntry(direntries + i));
1792
            if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
1793
                    is_free(direntries + i))
1794
                continue;
1795

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

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

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

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

    
1846
            ret += cluster_count;
1847
        }
1848

    
1849
        cluster_num = modified_fat_get(s, cluster_num);
1850
    } while(!fat_eof(s, cluster_num));
1851

    
1852
    free(cluster);
1853
    return ret;
1854
}
1855

    
1856
/* returns 1 on success */
1857
static int is_consistent(BDRVVVFATState* s)
1858
{
1859
    int i, check;
1860
    int used_clusters_count = 0;
1861

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

    
1891
    clear_commits(s);
1892

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

    
1902
    used_clusters_count = check_directory_consistency(s, 0, s->path);
1903
    if (used_clusters_count <= 0) {
1904
        DLOG(fprintf(stderr, "problem in directory\n"));
1905
        return 0;
1906
    }
1907

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

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

    
1925
    if (check != used_clusters_count)
1926
        return 0;
1927

    
1928
    return used_clusters_count;
1929
}
1930

    
1931
static inline void adjust_mapping_indices(BDRVVVFATState* s,
1932
        int offset, int adjust)
1933
{
1934
    int i;
1935

    
1936
    for (i = 0; i < s->mapping.next; i++) {
1937
        mapping_t* mapping = array_get(&(s->mapping), i);
1938

    
1939
#define ADJUST_MAPPING_INDEX(name) \
1940
        if (mapping->name >= offset) \
1941
            mapping->name += adjust
1942

    
1943
        ADJUST_MAPPING_INDEX(first_mapping_index);
1944
        if (mapping->mode & MODE_DIRECTORY)
1945
            ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
1946
    }
1947
}
1948

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

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

    
1976
    mapping->begin = begin;
1977
    mapping->end = end;
1978

    
1979
DLOG(mapping_t* next_mapping;
1980
assert(index + 1 >= s->mapping.next ||
1981
((next_mapping = array_get(&(s->mapping), index + 1)) &&
1982
 next_mapping->begin >= end)));
1983

    
1984
    if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1985
        s->current_mapping = array_get(&(s->mapping),
1986
                s->current_mapping - first_mapping);
1987

    
1988
    return mapping;
1989
}
1990

    
1991
static int remove_mapping(BDRVVVFATState* s, int mapping_index)
1992
{
1993
    mapping_t* mapping = array_get(&(s->mapping), mapping_index);
1994
    mapping_t* first_mapping = array_get(&(s->mapping), 0);
1995

    
1996
    /* free mapping */
1997
    if (mapping->first_mapping_index < 0)
1998
        free(mapping->path);
1999

    
2000
    /* remove from s->mapping */
2001
    array_remove(&(s->mapping), mapping_index);
2002

    
2003
    /* adjust all references to mappings */
2004
    adjust_mapping_indices(s, mapping_index, -1);
2005

    
2006
    if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
2007
        s->current_mapping = array_get(&(s->mapping),
2008
                s->current_mapping - first_mapping);
2009

    
2010
    return 0;
2011
}
2012

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

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

    
2040
static int remove_direntries(BDRVVVFATState* s, int dir_index, int count)
2041
{
2042
    int ret = array_remove_slice(&(s->directory), dir_index, count);
2043
    if (ret)
2044
        return ret;
2045
    adjust_dirindices(s, dir_index, -count);
2046
    return 0;
2047
}
2048

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

    
2062
    vvfat_close_current_file(s);
2063

    
2064
    assert(mapping);
2065
    assert(mapping->begin == first_cluster);
2066
    mapping->first_mapping_index = -1;
2067
    mapping->dir_index = dir_index;
2068
    mapping->mode = (dir_index <= 0 || is_directory(direntry)) ?
2069
        MODE_DIRECTORY : MODE_NORMAL;
2070

    
2071
    while (!fat_eof(s, cluster)) {
2072
        uint32_t c, c1;
2073

    
2074
        for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
2075
                c = c1, c1 = modified_fat_get(s, c1));
2076

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

    
2089
        if (!fat_eof(s, c1)) {
2090
            int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next);
2091
            mapping_t* next_mapping = i >= s->mapping.next ? NULL :
2092
                array_get(&(s->mapping), i);
2093

    
2094
            if (next_mapping == NULL || next_mapping->begin > c1) {
2095
                int i1 = array_index(&(s->mapping), mapping);
2096

    
2097
                next_mapping = insert_mapping(s, c1, c1+1);
2098

    
2099
                if (c1 < c)
2100
                    i1++;
2101
                mapping = array_get(&(s->mapping), i1);
2102
            }
2103

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

    
2123
            mapping = next_mapping;
2124
        }
2125

    
2126
        cluster = c1;
2127
    }
2128

    
2129
    return 0;
2130
}
2131

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

    
2139
    int factor = 0x10 * s->sectors_per_cluster;
2140
    int old_cluster_count, new_cluster_count;
2141
    int current_dir_index = mapping->info.dir.first_dir_index;
2142
    int first_dir_index = current_dir_index;
2143
    int ret, i;
2144
    uint32_t c;
2145

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

    
2148
    assert(direntry);
2149
    assert(mapping);
2150
    assert(mapping->begin == first_cluster);
2151
    assert(mapping->info.dir.first_dir_index < s->directory.next);
2152
    assert(mapping->mode & MODE_DIRECTORY);
2153
    assert(dir_index == 0 || is_directory(direntry));
2154

    
2155
    mapping->info.dir.parent_mapping_index = parent_mapping_index;
2156

    
2157
    if (first_cluster == 0) {
2158
        old_cluster_count = new_cluster_count =
2159
            s->last_cluster_of_root_directory;
2160
    } else {
2161
        for (old_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2162
                c = fat_get(s, c))
2163
            old_cluster_count++;
2164

    
2165
        for (new_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2166
                c = modified_fat_get(s, c))
2167
            new_cluster_count++;
2168
    }
2169

    
2170
    if (new_cluster_count > old_cluster_count) {
2171
        if (insert_direntries(s,
2172
                current_dir_index + factor * old_cluster_count,
2173
                factor * (new_cluster_count - old_cluster_count)) == NULL)
2174
            return -1;
2175
    } else if (new_cluster_count < old_cluster_count)
2176
        remove_direntries(s,
2177
                current_dir_index + factor * new_cluster_count,
2178
                factor * (old_cluster_count - new_cluster_count));
2179

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

    
2190
    ret = commit_mappings(s, first_cluster, dir_index);
2191
    if (ret)
2192
        return ret;
2193

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

    
2207
    return 0;
2208
}
2209

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

    
2224
    assert(offset < size);
2225
    assert((offset % s->cluster_size) == 0);
2226

    
2227
    for (i = s->cluster_size; i < offset; i += s->cluster_size)
2228
        c = modified_fat_get(s, c);
2229

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

    
2240
    while (offset < size) {
2241
        uint32_t c1;
2242
        int rest_size = (size - offset > s->cluster_size ?
2243
                s->cluster_size : size - offset);
2244
        int ret;
2245

    
2246
        c1 = modified_fat_get(s, c);
2247

    
2248
        assert((size - offset == 0 && fat_eof(s, c)) ||
2249
                (size > offset && c >=2 && !fat_eof(s, c)));
2250

    
2251
        ret = vvfat_read(s->bs, cluster2sector(s, c),
2252
            (uint8_t*)cluster, (rest_size + 0x1ff) / 0x200);
2253

    
2254
        if (ret < 0)
2255
            return ret;
2256

    
2257
        if (write(fd, cluster, rest_size) < 0)
2258
            return -2;
2259

    
2260
        offset += rest_size;
2261
        c = c1;
2262
    }
2263

    
2264
    if (ftruncate(fd, size)) {
2265
        perror("ftruncate()");
2266
        close(fd);
2267
        return -4;
2268
    }
2269
    close(fd);
2270

    
2271
    return commit_mappings(s, first_cluster, dir_index);
2272
}
2273

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

    
2296
/* test, if all direntries have mappings */
2297
static void check2(BDRVVVFATState* s)
2298
{
2299
    int i;
2300
    int first_mapping = -1;
2301

    
2302
    for (i = 0; i < s->directory.next; i++) {
2303
        direntry_t* direntry = array_get(&(s->directory), i);
2304

    
2305
        if (is_short_name(direntry) && begin_of_direntry(direntry)) {
2306
            mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
2307
            assert(mapping);
2308
            assert(mapping->dir_index == i || is_dot(direntry));
2309
            assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry));
2310
        }
2311

    
2312
        if ((i % (0x10 * s->sectors_per_cluster)) == 0) {
2313
            /* cluster start */
2314
            int j, count = 0;
2315

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

    
2344
static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2345
{
2346
    int i;
2347

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

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

    
2363
            assert(commit->path);
2364
            mapping->path = commit->path;
2365
            if (rename(old_path, mapping->path))
2366
                return -2;
2367

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

    
2377
                /* recurse */
2378
                while (!fat_eof(s, c)) {
2379
                    do {
2380
                        direntry_t* d = direntry + i;
2381

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

    
2388
                            assert(!strncmp(m->path, mapping->path, l2));
2389

    
2390
                            pstrcpy(new_path, l + diff + 1, mapping->path);
2391
                            pstrcpy(new_path + l1, l + diff + 1 - l1,
2392
                                    m->path + l2);
2393

    
2394
                            schedule_rename(s, m->begin, new_path);
2395
                        }
2396
                        i++;
2397
                    } while((i % (0x10 * s->sectors_per_cluster)) != 0);
2398
                    c = fat_get(s, c);
2399
                }
2400
            }
2401

    
2402
            free(old_path);
2403
            array_remove(&(s->commits), i);
2404
            continue;
2405
        } else if (commit->action == ACTION_MKDIR) {
2406
            mapping_t* mapping;
2407
            int j, parent_path_len;
2408

    
2409
#ifdef __MINGW32__
2410
            if (mkdir(commit->path))
2411
                return -5;
2412
#else
2413
            if (mkdir(commit->path, 0755))
2414
                return -5;
2415
#endif
2416

    
2417
            mapping = insert_mapping(s, commit->param.mkdir.cluster,
2418
                    commit->param.mkdir.cluster + 1);
2419
            if (mapping == NULL)
2420
                return -6;
2421

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

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

    
2443
            array_remove(&(s->commits), i);
2444
            continue;
2445
        }
2446

    
2447
        i++;
2448
    }
2449
    return 0;
2450
}
2451

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

    
2459
    vvfat_close_current_file(s);
2460

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

    
2477
            assert(mapping);
2478
            assert(mapping->begin == begin);
2479
            assert(commit->path == NULL);
2480

    
2481
            if (commit_one_file(s, commit->param.writeout.dir_index,
2482
                        commit->param.writeout.modified_offset))
2483
                fail = -3;
2484

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

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

    
2500
            if (i >= s->directory.next) {
2501
                fail = -6;
2502
                continue;
2503
            }
2504

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

    
2520
            if (commit_one_file(s, i, 0))
2521
                fail = -7;
2522

    
2523
            break;
2524
        }
2525
        default:
2526
            abort();
2527
        }
2528
    }
2529
    if (i > 0 && array_remove_slice(&(s->commits), 0, i))
2530
        return -1;
2531
    return fail;
2532
}
2533

    
2534
static int handle_deletes(BDRVVVFATState* s)
2535
{
2536
    int i, deferred = 1, deleted = 1;
2537

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

    
2544
        for (i = 1; i < s->mapping.next; i++) {
2545
            mapping_t* mapping = array_get(&(s->mapping), i);
2546
            if (mapping->mode & MODE_DELETED) {
2547
                direntry_t* entry = array_get(&(s->directory),
2548
                        mapping->dir_index);
2549

    
2550
                if (is_free(entry)) {
2551
                    /* remove file/directory */
2552
                    if (mapping->mode & MODE_DIRECTORY) {
2553
                        int j, next_dir_index = s->directory.next,
2554
                        first_dir_index = mapping->info.dir.first_dir_index;
2555

    
2556
                        if (rmdir(mapping->path) < 0) {
2557
                            if (errno == ENOTEMPTY) {
2558
                                deferred++;
2559
                                continue;
2560
                            } else
2561
                                return -5;
2562
                        }
2563

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

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

    
2590
    return 0;
2591
}
2592

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

    
2605
    /* the real meat are the commits. Nothing to do? Move along! */
2606
    if (s->commits.next == 0)
2607
        return 0;
2608

    
2609
    vvfat_close_current_file(s);
2610

    
2611
    ret = handle_renames_and_mkdirs(s);
2612
    if (ret) {
2613
        fprintf(stderr, "Error handling renames (%d)\n", ret);
2614
        abort();
2615
        return ret;
2616
    }
2617

    
2618
    /* copy FAT (with bdrv_read) */
2619
    memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
2620

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

    
2629
    ret = handle_commits(s);
2630
    if (ret) {
2631
        fprintf(stderr, "Error handling commits (%d)\n", ret);
2632
        abort();
2633
        return ret;
2634
    }
2635

    
2636
    ret = handle_deletes(s);
2637
    if (ret) {
2638
        fprintf(stderr, "Error deleting\n");
2639
        abort();
2640
        return ret;
2641
    }
2642

    
2643
    s->qcow->drv->bdrv_make_empty(s->qcow);
2644

    
2645
    memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
2646

    
2647
DLOG(checkpoint());
2648
    return 0;
2649
}
2650

    
2651
static int try_commit(BDRVVVFATState* s)
2652
{
2653
    vvfat_close_current_file(s);
2654
DLOG(checkpoint());
2655
    if(!is_consistent(s))
2656
        return -1;
2657
    return do_commit(s);
2658
}
2659

    
2660
static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
2661
                    const uint8_t *buf, int nb_sectors)
2662
{
2663
    BDRVVVFATState *s = bs->opaque;
2664
    int i, ret;
2665

    
2666
DLOG(checkpoint());
2667

    
2668
    /* Check if we're operating in read-only mode */
2669
    if (s->qcow == NULL) {
2670
        return -EACCES;
2671
    }
2672

    
2673
    vvfat_close_current_file(s);
2674

    
2675
    /*
2676
     * Some sanity checks:
2677
     * - do not allow writing to the boot sector
2678
     * - do not allow to write non-ASCII filenames
2679
     */
2680

    
2681
    if (sector_num < s->first_sectors_number)
2682
        return -1;
2683

    
2684
    for (i = sector2cluster(s, sector_num);
2685
            i <= sector2cluster(s, sector_num + nb_sectors - 1);) {
2686
        mapping_t* mapping = find_mapping_for_cluster(s, i);
2687
        if (mapping) {
2688
            if (mapping->read_only) {
2689
                fprintf(stderr, "Tried to write to write-protected file %s\n",
2690
                        mapping->path);
2691
                return -1;
2692
            }
2693

    
2694
            if (mapping->mode & MODE_DIRECTORY) {
2695
                int begin = cluster2sector(s, i);
2696
                int end = begin + s->sectors_per_cluster, k;
2697
                int dir_index;
2698
                const direntry_t* direntries;
2699
                long_file_name lfn;
2700

    
2701
                lfn_init(&lfn);
2702

    
2703
                if (begin < sector_num)
2704
                    begin = sector_num;
2705
                if (end > sector_num + nb_sectors)
2706
                    end = sector_num + nb_sectors;
2707
                dir_index  = mapping->dir_index +
2708
                    0x10 * (begin - mapping->begin * s->sectors_per_cluster);
2709
                direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
2710

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

    
2734
    /*
2735
     * Use qcow backend. Commit later.
2736
     */
2737
DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
2738
    ret = s->qcow->drv->bdrv_write(s->qcow, sector_num, buf, nb_sectors);
2739
    if (ret < 0) {
2740
        fprintf(stderr, "Error writing to qcow backend\n");
2741
        return ret;
2742
    }
2743

    
2744
    for (i = sector2cluster(s, sector_num);
2745
            i <= sector2cluster(s, sector_num + nb_sectors - 1); i++)
2746
        if (i >= 0)
2747
            s->used_clusters[i] |= USED_ALLOCATED;
2748

    
2749
DLOG(checkpoint());
2750
    /* TODO: add timeout */
2751
    try_commit(s);
2752

    
2753
DLOG(checkpoint());
2754
    return 0;
2755
}
2756

    
2757
static int vvfat_is_allocated(BlockDriverState *bs,
2758
        int64_t sector_num, int nb_sectors, int* n)
2759
{
2760
    BDRVVVFATState* s = bs->opaque;
2761
    *n = s->sector_count - sector_num;
2762
    if (*n > nb_sectors)
2763
        *n = nb_sectors;
2764
    else if (*n < 0)
2765
        return 0;
2766
    return 1;
2767
}
2768

    
2769
static int write_target_commit(BlockDriverState *bs, int64_t sector_num,
2770
        const uint8_t* buffer, int nb_sectors) {
2771
    BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
2772
    return try_commit(s);
2773
}
2774

    
2775
static void write_target_close(BlockDriverState *bs) {
2776
    BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
2777
    bdrv_delete(s->qcow);
2778
    free(s->qcow_filename);
2779
}
2780

    
2781
static BlockDriver vvfat_write_target = {
2782
    .format_name        = "vvfat_write_target",
2783
    .bdrv_write         = write_target_commit,
2784
    .bdrv_close         = write_target_close,
2785
};
2786

    
2787
static int enable_write_target(BDRVVVFATState *s)
2788
{
2789
    BlockDriver *bdrv_qcow;
2790
    QEMUOptionParameter *options;
2791
    int size = sector2cluster(s, s->sector_count);
2792
    s->used_clusters = calloc(size, 1);
2793

    
2794
    array_init(&(s->commits), sizeof(commit_t));
2795

    
2796
    s->qcow_filename = qemu_malloc(1024);
2797
    get_tmp_filename(s->qcow_filename, 1024);
2798

    
2799
    bdrv_qcow = bdrv_find_format("qcow");
2800
    options = parse_option_parameters("", bdrv_qcow->create_options, NULL);
2801
    set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512);
2802
    set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:");
2803

    
2804
    if (bdrv_create(bdrv_qcow, s->qcow_filename, options) < 0)
2805
        return -1;
2806
    s->qcow = bdrv_new("");
2807
    if (s->qcow == NULL ||
2808
        bdrv_open(s->qcow, s->qcow_filename, BDRV_O_RDWR, bdrv_qcow) < 0)
2809
    {
2810
        return -1;
2811
    }
2812

    
2813
#ifndef _WIN32
2814
    unlink(s->qcow_filename);
2815
#endif
2816

    
2817
    s->bs->backing_hd = calloc(sizeof(BlockDriverState), 1);
2818
    s->bs->backing_hd->drv = &vvfat_write_target;
2819
    s->bs->backing_hd->opaque = qemu_malloc(sizeof(void*));
2820
    *(void**)s->bs->backing_hd->opaque = s;
2821

    
2822
    return 0;
2823
}
2824

    
2825
static void vvfat_close(BlockDriverState *bs)
2826
{
2827
    BDRVVVFATState *s = bs->opaque;
2828

    
2829
    vvfat_close_current_file(s);
2830
    array_free(&(s->fat));
2831
    array_free(&(s->directory));
2832
    array_free(&(s->mapping));
2833
    if(s->cluster_buffer)
2834
        free(s->cluster_buffer);
2835
}
2836

    
2837
static BlockDriver bdrv_vvfat = {
2838
    .format_name        = "vvfat",
2839
    .instance_size        = sizeof(BDRVVVFATState),
2840
    .bdrv_file_open        = vvfat_open,
2841
    .bdrv_read                = vvfat_read,
2842
    .bdrv_write                = vvfat_write,
2843
    .bdrv_close                = vvfat_close,
2844
    .bdrv_is_allocated        = vvfat_is_allocated,
2845
    .protocol_name        = "fat",
2846
};
2847

    
2848
static void bdrv_vvfat_init(void)
2849
{
2850
    bdrv_register(&bdrv_vvfat);
2851
}
2852

    
2853
block_init(bdrv_vvfat_init);
2854

    
2855
#ifdef DEBUG
2856
static void checkpoint(void) {
2857
    assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2);
2858
    check1(vvv);
2859
    check2(vvv);
2860
    assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY));
2861
#if 0
2862
    if (((direntry_t*)vvv->directory.pointer)[1].attributes != 0xf)
2863
        fprintf(stderr, "Nonono!\n");
2864
    mapping_t* mapping;
2865
    direntry_t* direntry;
2866
    assert(vvv->mapping.size >= vvv->mapping.item_size * vvv->mapping.next);
2867
    assert(vvv->directory.size >= vvv->directory.item_size * vvv->directory.next);
2868
    if (vvv->mapping.next<47)
2869
        return;
2870
    assert((mapping = array_get(&(vvv->mapping), 47)));
2871
    assert(mapping->dir_index < vvv->directory.next);
2872
    direntry = array_get(&(vvv->directory), mapping->dir_index);
2873
    assert(!memcmp(direntry->name, "USB     H  ", 11) || direntry->name[0]==0);
2874
#endif
2875
    return;
2876
    /* avoid compiler warnings: */
2877
    hexdump(NULL, 100);
2878
    remove_mapping(vvv, 0);
2879
    print_mapping(NULL);
2880
    print_direntry(NULL);
2881
}
2882
#endif