Statistics
| Branch: | Revision:

root / block / vvfat.c @ 7267c094

History | View | Annotate | Download (80.6 kB)

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

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

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

    
46
/* #define DEBUG */
47

    
48
#ifdef DEBUG
49

    
50
#define DLOG(a) a
51

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

    
56
static void checkpoint(void);
57

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

    
67
#else
68

    
69
#define DLOG(a)
70

    
71
#endif
72

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

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

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

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

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

    
111
    return 0;
112
}
113

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

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

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

    
124
    return result;
125
}
126

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

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

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

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

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

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

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

    
172
    free(buf);
173

    
174
    return 0;
175
}
176

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

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

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

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

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

    
243
typedef struct {
244
    uint8_t head;
245
    uint8_t sector;
246
    uint8_t cylinder;
247
} mbr_chs_t;
248

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

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

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

    
281
/* this structure are used to transparently access the files */
282

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

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

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

    
318
/* here begins the real VVFAT driver */
319

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

    
325
    int fat_type; /* 16 or 32 */
326
    array_t fat,directory,mapping;
327

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

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

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

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

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

    
385
    memset(s->first_sectors,0,512);
386

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

    
390
    partition->attributes=0x80; /* bootable */
391

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

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

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

    
407
    real_mbr->magic[0]=0x55; real_mbr->magic[1]=0xaa;
408
}
409

    
410
/* direntry functions */
411

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

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

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

    
453
static char is_free(const direntry_t* direntry)
454
{
455
    return direntry->name[0]==0xe5 || direntry->name[0]==0x00;
456
}
457

    
458
static char is_volume_label(const direntry_t* direntry)
459
{
460
    return direntry->attributes == 0x28;
461
}
462

    
463
static char is_long_name(const direntry_t* direntry)
464
{
465
    return direntry->attributes == 0xf;
466
}
467

    
468
static char is_short_name(const direntry_t* direntry)
469
{
470
    return !is_volume_label(direntry) && !is_long_name(direntry)
471
        && !is_free(direntry);
472
}
473

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

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

    
484
static char is_file(const direntry_t* direntry)
485
{
486
    return is_short_name(direntry) && !is_directory(direntry);
487
}
488

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

    
494
static inline uint32_t filesize_of_direntry(const direntry_t* direntry)
495
{
496
    return le32_to_cpu(direntry->size);
497
}
498

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

    
505
/* fat functions */
506

    
507
static inline uint8_t fat_chksum(const direntry_t* entry)
508
{
509
    uint8_t chksum=0;
510
    int i;
511

    
512
    for(i=0;i<11;i++) {
513
        unsigned char c;
514

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

    
519
    return chksum;
520
}
521

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

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

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

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

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

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

    
602
}
603

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

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

    
620
    entry_long=create_long_filename(s,filename);
621

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

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

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

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

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

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

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

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

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

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

    
688
    return entry;
689
}
690

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

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

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

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

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

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

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

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

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

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

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

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

    
868
    /* add volume label */
869
    {
870
        direntry_t* entry=array_get_next(&(s->directory));
871
        entry->attributes=0x28; /* archive | volume label */
872
        memcpy(entry->name,"QEMU VVF",8);
873
        memcpy(entry->extension,"AT ",3);
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 = g_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
        /* MS-DOS expects the FAT to be 0 for the root directory
897
         * (except for the media byte). */
898
        /* LATER TODO: still true for FAT32? */
899
        int fix_fat = (i != 0);
900
        mapping = array_get(&(s->mapping), i);
901

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

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

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

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

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

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

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

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

    
957
    s->current_mapping = NULL;
958

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

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

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

    
988
    return 0;
989
}
990

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

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

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

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

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

    
1013
    s->bs = bs;
1014

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

    
1021
    s->current_cluster=0xffffffff;
1022

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1157
    return NULL;
1158
}
1159

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

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

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

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

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

    
1209
        assert(s->current_fd);
1210

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

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

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

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

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

    
1275
static void print_mapping(const mapping_t* mapping)
1276
{
1277
    fprintf(stderr, "mapping (%p): begin, end = %d, %d, dir_index = %d, "
1278
        "first_mapping_index = %d, name = %s, mode = 0x%x, " ,
1279
        mapping, mapping->begin, mapping->end, mapping->dir_index,
1280
        mapping->first_mapping_index, mapping->path, mapping->mode);
1281

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1478
    return 0;
1479
}
1480

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

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

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

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

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

    
1517
    return 0;
1518
}
1519

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

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

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

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

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

    
1554
    return was_modified;
1555
}
1556

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

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

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

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

    
1617
    vvfat_close_current_file(s);
1618

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

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

    
1627
        mapping = find_mapping_for_cluster(s, cluster_num);
1628

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

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

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

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

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

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

    
1659

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

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

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

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

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

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

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

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

    
1718
        cluster_num = modified_fat_get(s, cluster_num);
1719

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

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

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

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

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

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

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

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

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

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

    
1771
        ret++;
1772

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

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

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

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

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

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

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

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

    
1847
            ret += cluster_count;
1848
        }
1849

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

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

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

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

    
1892
    clear_commits(s);
1893

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

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

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

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

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

    
1929
    return used_clusters_count;
1930
}
1931

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

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

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

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

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

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

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

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

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

    
1989
    return mapping;
1990
}
1991

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

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

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

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

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

    
2011
    return 0;
2012
}
2013

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

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

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

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

    
2063
    vvfat_close_current_file(s);
2064

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

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

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

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

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

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

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

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

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

    
2124
            mapping = next_mapping;
2125
        }
2126

    
2127
        cluster = c1;
2128
    }
2129

    
2130
    return 0;
2131
}
2132

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

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

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

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

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

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

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

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

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

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

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

    
2208
    return 0;
2209
}
2210

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

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

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

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

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

    
2247
        c1 = modified_fat_get(s, c);
2248

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2459
    vvfat_close_current_file(s);
2460

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2590
    return 0;
2591
}
2592

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

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

    
2609
    vvfat_close_current_file(s);
2610

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

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

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

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

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

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

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

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

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

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

    
2666
DLOG(checkpoint());
2667

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

    
2673
    vvfat_close_current_file(s);
2674

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

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

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

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

    
2701
                lfn_init(&lfn);
2702

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

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

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

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

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

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

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

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

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

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

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

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

    
2797
    s->qcow_filename = g_malloc(1024);
2798
    get_tmp_filename(s->qcow_filename, 1024);
2799

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

    
2805
    if (bdrv_create(bdrv_qcow, s->qcow_filename, options) < 0)
2806
        return -1;
2807

    
2808
    s->qcow = bdrv_new("");
2809
    if (s->qcow == NULL) {
2810
        return -1;
2811
    }
2812

    
2813
    ret = bdrv_open(s->qcow, s->qcow_filename,
2814
            BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, bdrv_qcow);
2815
    if (ret < 0) {
2816
        return ret;
2817
    }
2818

    
2819
#ifndef _WIN32
2820
    unlink(s->qcow_filename);
2821
#endif
2822

    
2823
    s->bs->backing_hd = calloc(sizeof(BlockDriverState), 1);
2824
    s->bs->backing_hd->drv = &vvfat_write_target;
2825
    s->bs->backing_hd->opaque = g_malloc(sizeof(void*));
2826
    *(void**)s->bs->backing_hd->opaque = s;
2827

    
2828
    return 0;
2829
}
2830

    
2831
static void vvfat_close(BlockDriverState *bs)
2832
{
2833
    BDRVVVFATState *s = bs->opaque;
2834

    
2835
    vvfat_close_current_file(s);
2836
    array_free(&(s->fat));
2837
    array_free(&(s->directory));
2838
    array_free(&(s->mapping));
2839
    if(s->cluster_buffer)
2840
        free(s->cluster_buffer);
2841
}
2842

    
2843
static BlockDriver bdrv_vvfat = {
2844
    .format_name        = "vvfat",
2845
    .instance_size        = sizeof(BDRVVVFATState),
2846
    .bdrv_file_open        = vvfat_open,
2847
    .bdrv_read                = vvfat_read,
2848
    .bdrv_write                = vvfat_write,
2849
    .bdrv_close                = vvfat_close,
2850
    .bdrv_is_allocated        = vvfat_is_allocated,
2851
    .protocol_name        = "fat",
2852
};
2853

    
2854
static void bdrv_vvfat_init(void)
2855
{
2856
    bdrv_register(&bdrv_vvfat);
2857
}
2858

    
2859
block_init(bdrv_vvfat_init);
2860

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