Statistics
| Branch: | Revision:

root / block-vvfat.c @ f9320410

History | View | Annotate | Download (79 kB)

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

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

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

    
46
/* #define DEBUG */
47

    
48
#ifdef DEBUG
49

    
50
#define DLOG(a) a
51

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

    
56
static void checkpoint(void);
57

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

    
67
#else
68

    
69
#define DLOG(a)
70

    
71
#endif
72

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

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

    
87
static inline void array_free(array_t* array)
88
{
89
    if(array->pointer)
90
        free(array->pointer);
91
    array->size=array->next=0;
92
}
93

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

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

    
112
    return 0;
113
}
114

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

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

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

    
125
    return result;
126
}
127

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

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

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

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

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

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

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

    
173
    free(buf);
174

    
175
    return 0;
176
}
177

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

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

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

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

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

    
245
typedef struct {
246
    uint8_t head;
247
    uint8_t sector;
248
    uint8_t cylinder;
249
} mbr_chs_t;
250

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

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

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

    
283
/* this structure are used to transparently access the files */
284

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

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

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

    
320
/* here begins the real VVFAT driver */
321

    
322
typedef struct BDRVVVFATState {
323
    BlockDriverState* bs; /* pointer to parent */
324
    unsigned int first_sectors_number; /* 1 for a single partition, 0x40 for a disk with partition table */
325
    unsigned char first_sectors[0x40*0x200];
326

    
327
    int fat_type; /* 16 or 32 */
328
    array_t fat,directory,mapping;
329

    
330
    unsigned int cluster_size;
331
    unsigned int sectors_per_cluster;
332
    unsigned int sectors_per_fat;
333
    unsigned int sectors_of_root_directory;
334
    uint32_t last_cluster_of_root_directory;
335
    unsigned int faked_sectors; /* how many sectors are faked before file data */
336
    uint32_t sector_count; /* total number of sectors of the partition */
337
    uint32_t cluster_count; /* total number of clusters of this partition */
338
    uint32_t max_fat_value;
339

    
340
    int current_fd;
341
    mapping_t* current_mapping;
342
    unsigned char* cluster; /* points to current cluster */
343
    unsigned char* cluster_buffer; /* points to a buffer to hold temp data */
344
    unsigned int current_cluster;
345

    
346
    /* write support */
347
    BlockDriverState* write_target;
348
    char* qcow_filename;
349
    BlockDriverState* qcow;
350
    void* fat2;
351
    char* used_clusters;
352
    array_t commits;
353
    const char* path;
354
    int downcase_short_names;
355
} BDRVVVFATState;
356

    
357
/* take the sector position spos and convert it to Cylinder/Head/Sector position
358
 * if the position is outside the specified geometry, fill maximum value for CHS
359
 * and return 1 to signal overflow.
360
 */
361
static int sector2CHS(BlockDriverState* bs, mbr_chs_t * chs, int spos){
362
    int head,sector;
363
    sector   = spos % (bs->secs);  spos/= bs->secs;
364
    head     = spos % (bs->heads); spos/= bs->heads;
365
    if(spos >= bs->cyls){
366
        /* Overflow,
367
        it happens if 32bit sector positions are used, while CHS is only 24bit.
368
        Windows/Dos is said to take 1023/255/63 as nonrepresentable CHS */
369
        chs->head     = 0xFF;
370
        chs->sector   = 0xFF;
371
        chs->cylinder = 0xFF;
372
        return 1;
373
    }
374
    chs->head     = (uint8_t)head;
375
    chs->sector   = (uint8_t)( (sector+1) | ((spos>>8)<<6) );
376
    chs->cylinder = (uint8_t)spos;
377
    return 0;
378
}
379

    
380
static void init_mbr(BDRVVVFATState* s)
381
{
382
    /* TODO: if the files mbr.img and bootsect.img exist, use them */
383
    mbr_t* real_mbr=(mbr_t*)s->first_sectors;
384
    partition_t* partition=&(real_mbr->partition[0]);
385
    int lba;
386

    
387
    memset(s->first_sectors,0,512);
388

    
389
    /* Win NT Disk Signature */
390
    real_mbr->nt_id= cpu_to_le32(0xbe1afdfa);
391

    
392
    partition->attributes=0x80; /* bootable */
393

    
394
    /* LBA is used when partition is outside the CHS geometry */
395
    lba = sector2CHS(s->bs, &partition->start_CHS, s->first_sectors_number-1);
396
    lba|= sector2CHS(s->bs, &partition->end_CHS,   s->sector_count);
397

    
398
    /*LBA partitions are identified only by start/length_sector_long not by CHS*/
399
    partition->start_sector_long =cpu_to_le32(s->first_sectors_number-1);
400
    partition->length_sector_long=cpu_to_le32(s->sector_count - s->first_sectors_number+1);
401

    
402
    /* FAT12/FAT16/FAT32 */
403
    /* DOS uses different types when partition is LBA,
404
       probably to prevent older versions from using CHS on them */
405
    partition->fs_type= s->fat_type==12 ? 0x1:
406
                        s->fat_type==16 ? (lba?0xe:0x06):
407
                         /*fat_tyoe==32*/ (lba?0xc:0x0b);
408

    
409
    real_mbr->magic[0]=0x55; real_mbr->magic[1]=0xaa;
410
}
411

    
412
/* direntry functions */
413

    
414
/* dest is assumed to hold 258 bytes, and pads with 0xffff up to next multiple of 26 */
415
static inline int short2long_name(char* dest,const char* src)
416
{
417
    int i;
418
    int len;
419
    for(i=0;i<129 && src[i];i++) {
420
        dest[2*i]=src[i];
421
        dest[2*i+1]=0;
422
    }
423
    len=2*i;
424
    dest[2*i]=dest[2*i+1]=0;
425
    for(i=2*i+2;(i%26);i++)
426
        dest[i]=0xff;
427
    return len;
428
}
429

    
430
static inline direntry_t* create_long_filename(BDRVVVFATState* s,const char* filename)
431
{
432
    char buffer[258];
433
    int length=short2long_name(buffer,filename),
434
        number_of_entries=(length+25)/26,i;
435
    direntry_t* entry;
436

    
437
    for(i=0;i<number_of_entries;i++) {
438
        entry=array_get_next(&(s->directory));
439
        entry->attributes=0xf;
440
        entry->reserved[0]=0;
441
        entry->begin=0;
442
        entry->name[0]=(number_of_entries-i)|(i==0?0x40:0);
443
    }
444
    for(i=0;i<26*number_of_entries;i++) {
445
        int offset=(i%26);
446
        if(offset<10) offset=1+offset;
447
        else if(offset<22) offset=14+offset-10;
448
        else offset=28+offset-22;
449
        entry=array_get(&(s->directory),s->directory.next-1-(i/26));
450
        entry->name[offset]=buffer[i];
451
    }
452
    return array_get(&(s->directory),s->directory.next-number_of_entries);
453
}
454

    
455
static char is_free(const direntry_t* direntry)
456
{
457
    /* return direntry->name[0]==0 ; */
458
    return direntry->attributes == 0 || direntry->name[0]==0xe5;
459
}
460

    
461
static char is_volume_label(const direntry_t* direntry)
462
{
463
    return direntry->attributes == 0x28;
464
}
465

    
466
static char is_long_name(const direntry_t* direntry)
467
{
468
    return direntry->attributes == 0xf;
469
}
470

    
471
static char is_short_name(const direntry_t* direntry)
472
{
473
    return !is_volume_label(direntry) && !is_long_name(direntry)
474
        && !is_free(direntry);
475
}
476

    
477
static char is_directory(const direntry_t* direntry)
478
{
479
    return direntry->attributes & 0x10 && direntry->name[0] != 0xe5;
480
}
481

    
482
static inline char is_dot(const direntry_t* direntry)
483
{
484
    return is_short_name(direntry) && direntry->name[0] == '.';
485
}
486

    
487
static char is_file(const direntry_t* direntry)
488
{
489
    return is_short_name(direntry) && !is_directory(direntry);
490
}
491

    
492
static inline uint32_t begin_of_direntry(const direntry_t* direntry)
493
{
494
    return le16_to_cpu(direntry->begin)|(le16_to_cpu(direntry->begin_hi)<<16);
495
}
496

    
497
static inline uint32_t filesize_of_direntry(const direntry_t* direntry)
498
{
499
    return le32_to_cpu(direntry->size);
500
}
501

    
502
static void set_begin_of_direntry(direntry_t* direntry, uint32_t begin)
503
{
504
    direntry->begin = cpu_to_le16(begin & 0xffff);
505
    direntry->begin_hi = cpu_to_le16((begin >> 16) & 0xffff);
506
}
507

    
508
/* fat functions */
509

    
510
static inline uint8_t fat_chksum(const direntry_t* entry)
511
{
512
    uint8_t chksum=0;
513
    int i;
514

    
515
    for(i=0;i<11;i++)
516
        chksum=(((chksum&0xfe)>>1)|((chksum&0x01)?0x80:0))
517
            +(unsigned char)entry->name[i];
518

    
519
    return chksum;
520
}
521

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

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

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

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

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

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

    
602
}
603

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

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

    
620
    entry_long=create_long_filename(s,filename);
621

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

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

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

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

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

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

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

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

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

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

    
688
    return entry;
689
}
690

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
815
    return 0;
816
}
817

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

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

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

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

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

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

    
852
    s->cluster_size=s->sectors_per_cluster*0x200;
853
    s->cluster_buffer=malloc(s->cluster_size);
854
    assert(s->cluster_buffer);
855

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

    
866
    array_init(&(s->mapping),sizeof(mapping_t));
867
    array_init(&(s->directory),sizeof(direntry_t));
868

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

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

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

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

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

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

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

    
927
        assert(mapping->begin < mapping->end);
928

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

    
936
        /* next free cluster */
937
        cluster = mapping->end;
938

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

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

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

    
953
    s->current_mapping = NULL;
954

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

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

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

    
984
    return 0;
985
}
986

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

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

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

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

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

    
1009
    s->bs = bs;
1010

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

    
1017
    s->current_cluster=0xffffffff;
1018

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1153
    return NULL;
1154
}
1155

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

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

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

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

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

    
1205
        assert(s->current_fd);
1206

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1413
typedef struct {
1414
    unsigned char name[1024];
1415
    int checksum, len;
1416
    int sequence_number;
1417
} long_file_name;
1418

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

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

    
1432
    if (!is_long_name(direntry))
1433
        return 1;
1434

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

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

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

    
1461
    if (pointer[0] & 0x40)
1462
        lfn->len = offset + strlen((char*)lfn->name + offset);
1463

    
1464
    return 0;
1465
}
1466

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

    
1473
    if (!is_short_name(direntry))
1474
        return 1;
1475

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

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

    
1501
    lfn->len = strlen((char*)lfn->name);
1502

    
1503
    return 0;
1504
}
1505

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

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

    
1528
static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num)
1529
{
1530
    int was_modified = 0;
1531
    int i, dummy;
1532

    
1533
    if (s->qcow == NULL)
1534
        return 0;
1535

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

    
1540
    return was_modified;
1541
}
1542

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

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

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

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

    
1603
    vvfat_close_current_file(s);
1604

    
1605
    /* the root directory */
1606
    if (cluster_num == 0)
1607
        return 0;
1608

    
1609
    /* write support */
1610
    if (s->qcow) {
1611
        basename2 = get_basename(path);
1612

    
1613
        mapping = find_mapping_for_cluster(s, cluster_num);
1614

    
1615
        if (mapping) {
1616
            const char* basename;
1617

    
1618
            assert(mapping->mode & MODE_DELETED);
1619
            mapping->mode &= ~MODE_DELETED;
1620

    
1621
            basename = get_basename(mapping->path);
1622

    
1623
            assert(mapping->mode & MODE_NORMAL);
1624

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

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

    
1645

    
1646
                if (mapping &&
1647
                        (mapping->mode & MODE_DIRECTORY) == 0) {
1648

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

    
1658
                        if (strcmp(basename, basename2))
1659
                            copy_it = 1;
1660
                        first_mapping_index = array_index(&(s->mapping), mapping);
1661
                    }
1662

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

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

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

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

    
1699
        ret++;
1700
        if (s->used_clusters[cluster_num] & USED_ANY)
1701
            return 0;
1702
        s->used_clusters[cluster_num] = USED_FILE;
1703

    
1704
        cluster_num = modified_fat_get(s, cluster_num);
1705

    
1706
        if (fat_eof(s, cluster_num))
1707
            return ret;
1708
        else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
1709
            return -1;
1710

    
1711
        offset += s->cluster_size;
1712
    }
1713
}
1714

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

    
1728
    long_file_name lfn;
1729
    int path_len = strlen(path);
1730
    char path2[PATH_MAX];
1731

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

    
1737
    if (mapping) {
1738
        const char* basename = get_basename(mapping->path);
1739
        const char* basename2 = get_basename(path);
1740

    
1741
        assert(mapping->mode & MODE_DIRECTORY);
1742

    
1743
        assert(mapping->mode & MODE_DELETED);
1744
        mapping->mode &= ~MODE_DELETED;
1745

    
1746
        if (strcmp(basename, basename2))
1747
            schedule_rename(s, cluster_num, strdup(path));
1748
    } else
1749
        /* new directory */
1750
        schedule_mkdir(s, cluster_num, strdup(path));
1751

    
1752
    lfn_init(&lfn);
1753
    do {
1754
        int i;
1755
        int subret = 0;
1756

    
1757
        ret++;
1758

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

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

    
1775
        for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
1776
            int cluster_count;
1777

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

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

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

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

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

    
1832
            ret += cluster_count;
1833
        }
1834

    
1835
        cluster_num = modified_fat_get(s, cluster_num);
1836
    } while(!fat_eof(s, cluster_num));
1837

    
1838
    free(cluster);
1839
    return ret;
1840
}
1841

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

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

    
1877
    clear_commits(s);
1878

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

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

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

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

    
1911
    if (check != used_clusters_count)
1912
        return 0;
1913

    
1914
    return used_clusters_count;
1915
}
1916

    
1917
static inline void adjust_mapping_indices(BDRVVVFATState* s,
1918
        int offset, int adjust)
1919
{
1920
    int i;
1921

    
1922
    for (i = 0; i < s->mapping.next; i++) {
1923
        mapping_t* mapping = array_get(&(s->mapping), i);
1924

    
1925
#define ADJUST_MAPPING_INDEX(name) \
1926
        if (mapping->name >= offset) \
1927
            mapping->name += adjust
1928

    
1929
        ADJUST_MAPPING_INDEX(first_mapping_index);
1930
        if (mapping->mode & MODE_DIRECTORY)
1931
            ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
1932
    }
1933
}
1934

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

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

    
1962
    mapping->begin = begin;
1963
    mapping->end = end;
1964

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

    
1970
    if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1971
        s->current_mapping = array_get(&(s->mapping),
1972
                s->current_mapping - first_mapping);
1973

    
1974
    return mapping;
1975
}
1976

    
1977
static int remove_mapping(BDRVVVFATState* s, int mapping_index)
1978
{
1979
    mapping_t* mapping = array_get(&(s->mapping), mapping_index);
1980
    mapping_t* first_mapping = array_get(&(s->mapping), 0);
1981

    
1982
    /* free mapping */
1983
    if (mapping->first_mapping_index < 0)
1984
        free(mapping->path);
1985

    
1986
    /* remove from s->mapping */
1987
    array_remove(&(s->mapping), mapping_index);
1988

    
1989
    /* adjust all references to mappings */
1990
    adjust_mapping_indices(s, mapping_index, -1);
1991

    
1992
    if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1993
        s->current_mapping = array_get(&(s->mapping),
1994
                s->current_mapping - first_mapping);
1995

    
1996
    return 0;
1997
}
1998

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

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

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

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

    
2048
    vvfat_close_current_file(s);
2049

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

    
2057
    while (!fat_eof(s, cluster)) {
2058
        uint32_t c, c1;
2059

    
2060
        for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
2061
                c = c1, c1 = modified_fat_get(s, c1));
2062

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

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

    
2080
            if (next_mapping == NULL || next_mapping->begin > c1) {
2081
                int i1 = array_index(&(s->mapping), mapping);
2082

    
2083
                next_mapping = insert_mapping(s, c1, c1+1);
2084

    
2085
                if (c1 < c)
2086
                    i1++;
2087
                mapping = array_get(&(s->mapping), i1);
2088
            }
2089

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

    
2109
            mapping = next_mapping;
2110
        }
2111

    
2112
        cluster = c1;
2113
    }
2114

    
2115
    return 0;
2116
}
2117

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

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

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

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

    
2141
    mapping->info.dir.parent_mapping_index = parent_mapping_index;
2142

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

    
2151
        for (new_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2152
                c = modified_fat_get(s, c))
2153
            new_cluster_count++;
2154
    }
2155

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

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

    
2176
    ret = commit_mappings(s, first_cluster, dir_index);
2177
    if (ret)
2178
        return ret;
2179

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

    
2193
    return 0;
2194
}
2195

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

    
2210
    assert(offset < size);
2211
    assert((offset % s->cluster_size) == 0);
2212

    
2213
    for (i = s->cluster_size; i < offset; i += s->cluster_size)
2214
        c = modified_fat_get(s, c);
2215

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

    
2226
    while (offset < size) {
2227
        uint32_t c1;
2228
        int rest_size = (size - offset > s->cluster_size ?
2229
                s->cluster_size : size - offset);
2230
        int ret;
2231

    
2232
        c1 = modified_fat_get(s, c);
2233

    
2234
        assert((size - offset == 0 && fat_eof(s, c)) ||
2235
                (size > offset && c >=2 && !fat_eof(s, c)));
2236
        assert(size >= 0);
2237

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

    
2241
        if (ret < 0)
2242
            return ret;
2243

    
2244
        if (write(fd, cluster, rest_size) < 0)
2245
            return -2;
2246

    
2247
        offset += rest_size;
2248
        c = c1;
2249
    }
2250

    
2251
    ftruncate(fd, size);
2252
    close(fd);
2253

    
2254
    return commit_mappings(s, first_cluster, dir_index);
2255
}
2256

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

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

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

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

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

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

    
2327
static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2328
{
2329
    int i;
2330

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

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

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

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

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

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

    
2371
                            assert(!strncmp(m->path, mapping->path, l2));
2372

    
2373
                            strcpy(new_path, mapping->path);
2374
                            strcpy(new_path + l1, m->path + l2);
2375

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

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

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

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

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

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

    
2425
            array_remove(&(s->commits), i);
2426
            continue;
2427
        }
2428

    
2429
        i++;
2430
    }
2431
    return 0;
2432
}
2433

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

    
2441
    vvfat_close_current_file(s);
2442

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

    
2456
            assert(mapping);
2457
            assert(mapping->begin == begin);
2458
            assert(commit->path == NULL);
2459

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

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

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

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

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

    
2499
            if (commit_one_file(s, i, 0))
2500
                fail = -7;
2501

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

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

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

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

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

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

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

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

    
2569
    return 0;
2570
}
2571

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

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

    
2588
    vvfat_close_current_file(s);
2589

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

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

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

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

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

    
2622
    s->qcow->drv->bdrv_make_empty(s->qcow);
2623

    
2624
    memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
2625

    
2626
DLOG(checkpoint());
2627
    return 0;
2628
}
2629

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

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

    
2645
DLOG(checkpoint());
2646

    
2647
    vvfat_close_current_file(s);
2648

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

    
2655
    if (sector_num < s->first_sectors_number)
2656
        return -1;
2657

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

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

    
2675
                lfn_init(&lfn);
2676

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

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

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

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

    
2723
DLOG(checkpoint());
2724
    /* TODO: add timeout */
2725
    try_commit(s);
2726

    
2727
DLOG(checkpoint());
2728
    return 0;
2729
}
2730

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

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

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

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

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

    
2767
    array_init(&(s->commits), sizeof(commit_t));
2768

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

    
2778
#ifndef _WIN32
2779
    unlink(s->qcow_filename);
2780
#endif
2781

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

    
2786
    return 0;
2787
}
2788

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

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

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

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