Statistics
| Branch: | Revision:

root / block-vvfat.c @ 3f4cb3d3

History | View | Annotate | Download (79.5 kB)

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

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

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

    
46
/* #define DEBUG */
47

    
48
#ifdef DEBUG
49

    
50
#define DLOG(a) a
51

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

    
56
static void checkpoint(void);
57

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

    
67
#else
68

    
69
#define DLOG(a)
70

    
71
#endif
72

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

    
79
static inline void array_init(array_t* array,unsigned int item_size)
80
{
81
    array->pointer = 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
        chksum=(((chksum&0xfe)>>1)|((chksum&0x01)?0x80:0))
514
            +(unsigned char)entry->name[i];
515

    
516
    return chksum;
517
}
518

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

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

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

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

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

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

    
599
}
600

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

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

    
617
    entry_long=create_long_filename(s,filename);
618

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

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

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

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

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

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

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

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

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

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

    
685
    return entry;
686
}
687

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
811
    return 0;
812
}
813

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

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

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

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

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

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

    
848
    s->cluster_size=s->sectors_per_cluster*0x200;
849
    s->cluster_buffer=qemu_malloc(s->cluster_size);
850

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

    
861
    array_init(&(s->mapping),sizeof(mapping_t));
862
    array_init(&(s->directory),sizeof(direntry_t));
863

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

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

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

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

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

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

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

    
921
        assert(mapping->begin < mapping->end);
922

    
923
        /* next free cluster */
924
        cluster = mapping->end;
925

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

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

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

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

    
952
    s->current_mapping = NULL;
953

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

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

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

    
983
    return 0;
984
}
985

    
986
#ifdef DEBUG
987
static BDRVVVFATState *vvv = NULL;
988
#endif
989

    
990
static int enable_write_target(BDRVVVFATState *s);
991
static int is_consistent(BDRVVVFATState *s);
992

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

    
999
#ifdef DEBUG
1000
    vvv = s;
1001
#endif
1002

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

    
1008
    s->bs = bs;
1009

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

    
1016
    s->current_cluster=0xffffffff;
1017

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

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

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

    
1037
    s->sector_count=bs->cyls*bs->heads*bs->secs;
1038

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

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

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

    
1063
    bs->total_sectors=bs->cyls*bs->heads*bs->secs;
1064

    
1065
    if(init_directories(s, dirname))
1066
        return -1;
1067

    
1068
    s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
1069

    
1070
    if(s->first_sectors_number==0x40)
1071
        init_mbr(s);
1072

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

    
1077
    //    assert(is_consistent(s));
1078
    return 0;
1079
}
1080

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

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

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

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

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

    
1152
    return NULL;
1153
}
1154

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

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

    
1184
            assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
1185

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

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

    
1204
        assert(s->current_fd);
1205

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

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

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

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

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

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

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

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

    
1324
/* LATER TODO: statify all functions */
1325

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

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

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

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

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

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

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

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

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

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

    
1436
    if (!is_long_name(direntry))
1437
        return 1;
1438

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

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

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

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

    
1469
    return 0;
1470
}
1471

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

    
1478
    if (!is_short_name(direntry))
1479
        return 1;
1480

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

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

    
1506
    lfn->len = strlen((char*)lfn->name);
1507

    
1508
    return 0;
1509
}
1510

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

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

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

    
1538
    if (s->qcow == NULL)
1539
        return 0;
1540

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

    
1545
    return was_modified;
1546
}
1547

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

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

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

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

    
1608
    vvfat_close_current_file(s);
1609

    
1610
    /* the root directory */
1611
    if (cluster_num == 0)
1612
        return 0;
1613

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

    
1618
        mapping = find_mapping_for_cluster(s, cluster_num);
1619

    
1620
        if (mapping) {
1621
            const char* basename;
1622

    
1623
            assert(mapping->mode & MODE_DELETED);
1624
            mapping->mode &= ~MODE_DELETED;
1625

    
1626
            basename = get_basename(mapping->path);
1627

    
1628
            assert(mapping->mode & MODE_NORMAL);
1629

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

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

    
1650

    
1651
                if (mapping &&
1652
                        (mapping->mode & MODE_DIRECTORY) == 0) {
1653

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

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

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

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

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

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

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

    
1709
        cluster_num = modified_fat_get(s, cluster_num);
1710

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

    
1716
        offset += s->cluster_size;
1717
    }
1718
}
1719

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

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

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

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

    
1746
        assert(mapping->mode & MODE_DIRECTORY);
1747

    
1748
        assert(mapping->mode & MODE_DELETED);
1749
        mapping->mode &= ~MODE_DELETED;
1750

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

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

    
1762
        ret++;
1763

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

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

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

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

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

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

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

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

    
1838
            ret += cluster_count;
1839
        }
1840

    
1841
        cluster_num = modified_fat_get(s, cluster_num);
1842
    } while(!fat_eof(s, cluster_num));
1843

    
1844
    free(cluster);
1845
    return ret;
1846
}
1847

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

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

    
1883
    clear_commits(s);
1884

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

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

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

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

    
1917
    if (check != used_clusters_count)
1918
        return 0;
1919

    
1920
    return used_clusters_count;
1921
}
1922

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

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

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

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

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

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

    
1968
    mapping->begin = begin;
1969
    mapping->end = end;
1970

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

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

    
1980
    return mapping;
1981
}
1982

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

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

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

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

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

    
2002
    return 0;
2003
}
2004

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

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

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

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

    
2054
    vvfat_close_current_file(s);
2055

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

    
2063
    while (!fat_eof(s, cluster)) {
2064
        uint32_t c, c1;
2065

    
2066
        for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
2067
                c = c1, c1 = modified_fat_get(s, c1));
2068

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

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

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

    
2089
                next_mapping = insert_mapping(s, c1, c1+1);
2090

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

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

    
2115
            mapping = next_mapping;
2116
        }
2117

    
2118
        cluster = c1;
2119
    }
2120

    
2121
    return 0;
2122
}
2123

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

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

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

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

    
2147
    mapping->info.dir.parent_mapping_index = parent_mapping_index;
2148

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

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

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

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

    
2182
    ret = commit_mappings(s, first_cluster, dir_index);
2183
    if (ret)
2184
        return ret;
2185

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

    
2199
    return 0;
2200
}
2201

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

    
2216
    assert(offset < size);
2217
    assert((offset % s->cluster_size) == 0);
2218

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

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

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

    
2238
        c1 = modified_fat_get(s, c);
2239

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

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

    
2246
        if (ret < 0)
2247
            return ret;
2248

    
2249
        if (write(fd, cluster, rest_size) < 0)
2250
            return -2;
2251

    
2252
        offset += rest_size;
2253
        c = c1;
2254
    }
2255

    
2256
    ftruncate(fd, size);
2257
    close(fd);
2258

    
2259
    return commit_mappings(s, first_cluster, dir_index);
2260
}
2261

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

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

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

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

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

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

    
2332
static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2333
{
2334
    int i;
2335

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

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

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

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

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

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

    
2376
                            assert(!strncmp(m->path, mapping->path, l2));
2377

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

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

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

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

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

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

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

    
2431
            array_remove(&(s->commits), i);
2432
            continue;
2433
        }
2434

    
2435
        i++;
2436
    }
2437
    return 0;
2438
}
2439

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

    
2447
    vvfat_close_current_file(s);
2448

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

    
2462
            assert(mapping);
2463
            assert(mapping->begin == begin);
2464
            assert(commit->path == NULL);
2465

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

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

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

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

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

    
2505
            if (commit_one_file(s, i, 0))
2506
                fail = -7;
2507

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

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

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

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

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

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

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

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

    
2575
    return 0;
2576
}
2577

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

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

    
2594
    vvfat_close_current_file(s);
2595

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

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

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

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

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

    
2628
    s->qcow->drv->bdrv_make_empty(s->qcow);
2629

    
2630
    memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
2631

    
2632
DLOG(checkpoint());
2633
    return 0;
2634
}
2635

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

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

    
2651
DLOG(checkpoint());
2652

    
2653
    vvfat_close_current_file(s);
2654

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

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

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

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

    
2681
                lfn_init(&lfn);
2682

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

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

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

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

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

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

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

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

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

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

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

    
2773
    array_init(&(s->commits), sizeof(commit_t));
2774

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

    
2784
#ifndef _WIN32
2785
    unlink(s->qcow_filename);
2786
#endif
2787

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

    
2792
    return 0;
2793
}
2794

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

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

    
2807
BlockDriver bdrv_vvfat = {
2808
    .format_name        = "vvfat",
2809
    .instance_size        = sizeof(BDRVVVFATState),
2810
    .bdrv_open                = vvfat_open,
2811
    .bdrv_read                = vvfat_read,
2812
    .bdrv_write                = vvfat_write,
2813
    .bdrv_close                = vvfat_close,
2814
    .bdrv_is_allocated        = vvfat_is_allocated,
2815
    .protocol_name        = "fat",
2816
};
2817

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