cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

vvfat.c (103176B)


      1/* vim:set shiftwidth=4 ts=4: */
      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
     26#include "qemu/osdep.h"
     27#include <dirent.h>
     28#include "qapi/error.h"
     29#include "block/block_int.h"
     30#include "block/qdict.h"
     31#include "qemu/module.h"
     32#include "qemu/option.h"
     33#include "qemu/bswap.h"
     34#include "migration/blocker.h"
     35#include "qapi/qmp/qdict.h"
     36#include "qapi/qmp/qstring.h"
     37#include "qemu/ctype.h"
     38#include "qemu/cutils.h"
     39#include "qemu/error-report.h"
     40
     41#ifndef S_IWGRP
     42#define S_IWGRP 0
     43#endif
     44#ifndef S_IWOTH
     45#define S_IWOTH 0
     46#endif
     47
     48/* TODO: add ":bootsector=blabla.img:" */
     49/* LATER TODO: add automatic boot sector generation from
     50    BOOTEASY.ASM and Ranish Partition Manager
     51    Note that DOS assumes the system files to be the first files in the
     52    file system (test if the boot sector still relies on that fact)! */
     53/* MAYBE TODO: write block-visofs.c */
     54/* TODO: call try_commit() only after a timeout */
     55
     56/* #define DEBUG */
     57
     58#ifdef DEBUG
     59
     60#define DLOG(a) a
     61
     62static void checkpoint(void);
     63
     64#else
     65
     66#define DLOG(a)
     67
     68#endif
     69
     70/* bootsector OEM name. see related compatibility problems at:
     71 * https://jdebp.eu/FGA/volume-boot-block-oem-name-field.html
     72 * http://seasip.info/Misc/oemid.html
     73 */
     74#define BOOTSECTOR_OEM_NAME "MSWIN4.1"
     75
     76#define DIR_DELETED 0xe5
     77#define DIR_KANJI DIR_DELETED
     78#define DIR_KANJI_FAKE 0x05
     79#define DIR_FREE 0x00
     80
     81/* dynamic array functions */
     82typedef struct array_t {
     83    char* pointer;
     84    unsigned int size,next,item_size;
     85} array_t;
     86
     87static inline void array_init(array_t* array,unsigned int item_size)
     88{
     89    array->pointer = NULL;
     90    array->size=0;
     91    array->next=0;
     92    array->item_size=item_size;
     93}
     94
     95static inline void array_free(array_t* array)
     96{
     97    g_free(array->pointer);
     98    array->size=array->next=0;
     99}
    100
    101/* does not automatically grow */
    102static inline void* array_get(array_t* array,unsigned int index) {
    103    assert(index < array->next);
    104    assert(array->pointer);
    105    return array->pointer + index * array->item_size;
    106}
    107
    108static inline void array_ensure_allocated(array_t *array, int index)
    109{
    110    if((index + 1) * array->item_size > array->size) {
    111        int new_size = (index + 32) * array->item_size;
    112        array->pointer = g_realloc(array->pointer, new_size);
    113        assert(array->pointer);
    114        memset(array->pointer + array->size, 0, new_size - array->size);
    115        array->size = new_size;
    116        array->next = index + 1;
    117    }
    118}
    119
    120static inline void* array_get_next(array_t* array) {
    121    unsigned int next = array->next;
    122
    123    array_ensure_allocated(array, next);
    124    array->next = next + 1;
    125    return array_get(array, next);
    126}
    127
    128static inline void* array_insert(array_t* array,unsigned int index,unsigned int count) {
    129    if((array->next+count)*array->item_size>array->size) {
    130        int increment=count*array->item_size;
    131        array->pointer=g_realloc(array->pointer,array->size+increment);
    132        if(!array->pointer)
    133            return NULL;
    134        array->size+=increment;
    135    }
    136    memmove(array->pointer+(index+count)*array->item_size,
    137                array->pointer+index*array->item_size,
    138                (array->next-index)*array->item_size);
    139    array->next+=count;
    140    return array->pointer+index*array->item_size;
    141}
    142
    143static inline int array_remove_slice(array_t* array,int index, int count)
    144{
    145    assert(index >=0);
    146    assert(count > 0);
    147    assert(index + count <= array->next);
    148
    149    memmove(array->pointer + index * array->item_size,
    150            array->pointer + (index + count) * array->item_size,
    151            (array->next - index - count) * array->item_size);
    152
    153    array->next -= count;
    154    return 0;
    155}
    156
    157static int array_remove(array_t* array,int index)
    158{
    159    return array_remove_slice(array, index, 1);
    160}
    161
    162/* return the index for a given member */
    163static int array_index(array_t* array, void* pointer)
    164{
    165    size_t offset = (char*)pointer - array->pointer;
    166    assert((offset % array->item_size) == 0);
    167    assert(offset/array->item_size < array->next);
    168    return offset/array->item_size;
    169}
    170
    171/* These structures are used to fake a disk and the VFAT filesystem.
    172 * For this reason we need to use QEMU_PACKED. */
    173
    174typedef struct bootsector_t {
    175    uint8_t jump[3];
    176    uint8_t name[8];
    177    uint16_t sector_size;
    178    uint8_t sectors_per_cluster;
    179    uint16_t reserved_sectors;
    180    uint8_t number_of_fats;
    181    uint16_t root_entries;
    182    uint16_t total_sectors16;
    183    uint8_t media_type;
    184    uint16_t sectors_per_fat;
    185    uint16_t sectors_per_track;
    186    uint16_t number_of_heads;
    187    uint32_t hidden_sectors;
    188    uint32_t total_sectors;
    189    union {
    190        struct {
    191            uint8_t drive_number;
    192            uint8_t reserved1;
    193            uint8_t signature;
    194            uint32_t id;
    195            uint8_t volume_label[11];
    196            uint8_t fat_type[8];
    197            uint8_t ignored[0x1c0];
    198        } QEMU_PACKED fat16;
    199        struct {
    200            uint32_t sectors_per_fat;
    201            uint16_t flags;
    202            uint8_t major,minor;
    203            uint32_t first_cluster_of_root_dir;
    204            uint16_t info_sector;
    205            uint16_t backup_boot_sector;
    206            uint8_t reserved[12];
    207            uint8_t drive_number;
    208            uint8_t reserved1;
    209            uint8_t signature;
    210            uint32_t id;
    211            uint8_t volume_label[11];
    212            uint8_t fat_type[8];
    213            uint8_t ignored[0x1a4];
    214        } QEMU_PACKED fat32;
    215    } u;
    216    uint8_t magic[2];
    217} QEMU_PACKED bootsector_t;
    218
    219typedef struct {
    220    uint8_t head;
    221    uint8_t sector;
    222    uint8_t cylinder;
    223} mbr_chs_t;
    224
    225typedef struct partition_t {
    226    uint8_t attributes; /* 0x80 = bootable */
    227    mbr_chs_t start_CHS;
    228    uint8_t   fs_type; /* 0x1 = FAT12, 0x6 = FAT16, 0xe = FAT16_LBA, 0xb = FAT32, 0xc = FAT32_LBA */
    229    mbr_chs_t end_CHS;
    230    uint32_t start_sector_long;
    231    uint32_t length_sector_long;
    232} QEMU_PACKED partition_t;
    233
    234typedef struct mbr_t {
    235    uint8_t ignored[0x1b8];
    236    uint32_t nt_id;
    237    uint8_t ignored2[2];
    238    partition_t partition[4];
    239    uint8_t magic[2];
    240} QEMU_PACKED mbr_t;
    241
    242typedef struct direntry_t {
    243    uint8_t name[8 + 3];
    244    uint8_t attributes;
    245    uint8_t reserved[2];
    246    uint16_t ctime;
    247    uint16_t cdate;
    248    uint16_t adate;
    249    uint16_t begin_hi;
    250    uint16_t mtime;
    251    uint16_t mdate;
    252    uint16_t begin;
    253    uint32_t size;
    254} QEMU_PACKED direntry_t;
    255
    256/* this structure are used to transparently access the files */
    257
    258typedef struct mapping_t {
    259    /* begin is the first cluster, end is the last+1 */
    260    uint32_t begin,end;
    261    /* as s->directory is growable, no pointer may be used here */
    262    unsigned int dir_index;
    263    /* the clusters of a file may be in any order; this points to the first */
    264    int first_mapping_index;
    265    union {
    266        /* offset is
    267         * - the offset in the file (in clusters) for a file, or
    268         * - the next cluster of the directory for a directory
    269         */
    270        struct {
    271            uint32_t offset;
    272        } file;
    273        struct {
    274            int parent_mapping_index;
    275            int first_dir_index;
    276        } dir;
    277    } info;
    278    /* path contains the full path, i.e. it always starts with s->path */
    279    char* path;
    280
    281    enum {
    282        MODE_UNDEFINED = 0,
    283        MODE_NORMAL = 1,
    284        MODE_MODIFIED = 2,
    285        MODE_DIRECTORY = 4,
    286        MODE_DELETED = 8,
    287    } mode;
    288    int read_only;
    289} mapping_t;
    290
    291#ifdef DEBUG
    292static void print_direntry(const struct direntry_t*);
    293static void print_mapping(const struct mapping_t* mapping);
    294#endif
    295
    296/* here begins the real VVFAT driver */
    297
    298typedef struct BDRVVVFATState {
    299    CoMutex lock;
    300    BlockDriverState* bs; /* pointer to parent */
    301    unsigned char first_sectors[0x40*0x200];
    302
    303    int fat_type; /* 16 or 32 */
    304    array_t fat,directory,mapping;
    305    char volume_label[11];
    306
    307    uint32_t offset_to_bootsector; /* 0 for floppy, 0x3f for disk */
    308
    309    unsigned int cluster_size;
    310    unsigned int sectors_per_cluster;
    311    unsigned int sectors_per_fat;
    312    uint32_t last_cluster_of_root_directory;
    313    /* how many entries are available in root directory (0 for FAT32) */
    314    uint16_t root_entries;
    315    uint32_t sector_count; /* total number of sectors of the partition */
    316    uint32_t cluster_count; /* total number of clusters of this partition */
    317    uint32_t max_fat_value;
    318    uint32_t offset_to_fat;
    319    uint32_t offset_to_root_dir;
    320
    321    int current_fd;
    322    mapping_t* current_mapping;
    323    unsigned char* cluster; /* points to current cluster */
    324    unsigned char* cluster_buffer; /* points to a buffer to hold temp data */
    325    unsigned int current_cluster;
    326
    327    /* write support */
    328    char* qcow_filename;
    329    BdrvChild* qcow;
    330    void* fat2;
    331    char* used_clusters;
    332    array_t commits;
    333    const char* path;
    334    int downcase_short_names;
    335
    336    Error *migration_blocker;
    337} BDRVVVFATState;
    338
    339/* take the sector position spos and convert it to Cylinder/Head/Sector position
    340 * if the position is outside the specified geometry, fill maximum value for CHS
    341 * and return 1 to signal overflow.
    342 */
    343static int sector2CHS(mbr_chs_t *chs, int spos, int cyls, int heads, int secs)
    344{
    345    int head,sector;
    346    sector   = spos % secs;  spos /= secs;
    347    head     = spos % heads; spos /= heads;
    348    if (spos >= cyls) {
    349        /* Overflow,
    350        it happens if 32bit sector positions are used, while CHS is only 24bit.
    351        Windows/Dos is said to take 1023/255/63 as nonrepresentable CHS */
    352        chs->head     = 0xFF;
    353        chs->sector   = 0xFF;
    354        chs->cylinder = 0xFF;
    355        return 1;
    356    }
    357    chs->head     = (uint8_t)head;
    358    chs->sector   = (uint8_t)( (sector+1) | ((spos>>8)<<6) );
    359    chs->cylinder = (uint8_t)spos;
    360    return 0;
    361}
    362
    363static void init_mbr(BDRVVVFATState *s, int cyls, int heads, int secs)
    364{
    365    /* TODO: if the files mbr.img and bootsect.img exist, use them */
    366    mbr_t* real_mbr=(mbr_t*)s->first_sectors;
    367    partition_t* partition = &(real_mbr->partition[0]);
    368    int lba;
    369
    370    memset(s->first_sectors,0,512);
    371
    372    /* Win NT Disk Signature */
    373    real_mbr->nt_id= cpu_to_le32(0xbe1afdfa);
    374
    375    partition->attributes=0x80; /* bootable */
    376
    377    /* LBA is used when partition is outside the CHS geometry */
    378    lba  = sector2CHS(&partition->start_CHS, s->offset_to_bootsector,
    379                     cyls, heads, secs);
    380    lba |= sector2CHS(&partition->end_CHS,   s->bs->total_sectors - 1,
    381                     cyls, heads, secs);
    382
    383    /*LBA partitions are identified only by start/length_sector_long not by CHS*/
    384    partition->start_sector_long  = cpu_to_le32(s->offset_to_bootsector);
    385    partition->length_sector_long = cpu_to_le32(s->bs->total_sectors
    386                                                - s->offset_to_bootsector);
    387
    388    /* FAT12/FAT16/FAT32 */
    389    /* DOS uses different types when partition is LBA,
    390       probably to prevent older versions from using CHS on them */
    391    partition->fs_type = s->fat_type == 12 ? 0x1 :
    392                         s->fat_type == 16 ? (lba ? 0xe : 0x06) :
    393                       /*s->fat_type == 32*/ (lba ? 0xc : 0x0b);
    394
    395    real_mbr->magic[0]=0x55; real_mbr->magic[1]=0xaa;
    396}
    397
    398/* direntry functions */
    399
    400static direntry_t *create_long_filename(BDRVVVFATState *s, const char *filename)
    401{
    402    int number_of_entries, i;
    403    glong length;
    404    direntry_t *entry;
    405
    406    gunichar2 *longname = g_utf8_to_utf16(filename, -1, NULL, &length, NULL);
    407    if (!longname) {
    408        fprintf(stderr, "vvfat: invalid UTF-8 name: %s\n", filename);
    409        return NULL;
    410    }
    411
    412    number_of_entries = DIV_ROUND_UP(length * 2, 26);
    413
    414    for(i=0;i<number_of_entries;i++) {
    415        entry=array_get_next(&(s->directory));
    416        entry->attributes=0xf;
    417        entry->reserved[0]=0;
    418        entry->begin=0;
    419        entry->name[0]=(number_of_entries-i)|(i==0?0x40:0);
    420    }
    421    for(i=0;i<26*number_of_entries;i++) {
    422        int offset=(i%26);
    423        if(offset<10) offset=1+offset;
    424        else if(offset<22) offset=14+offset-10;
    425        else offset=28+offset-22;
    426        entry=array_get(&(s->directory),s->directory.next-1-(i/26));
    427        if (i >= 2 * length + 2) {
    428            entry->name[offset] = 0xff;
    429        } else if (i % 2 == 0) {
    430            entry->name[offset] = longname[i / 2] & 0xff;
    431        } else {
    432            entry->name[offset] = longname[i / 2] >> 8;
    433        }
    434    }
    435    g_free(longname);
    436    return array_get(&(s->directory),s->directory.next-number_of_entries);
    437}
    438
    439static char is_free(const direntry_t* direntry)
    440{
    441    return direntry->name[0] == DIR_DELETED || direntry->name[0] == DIR_FREE;
    442}
    443
    444static char is_volume_label(const direntry_t* direntry)
    445{
    446    return direntry->attributes == 0x28;
    447}
    448
    449static char is_long_name(const direntry_t* direntry)
    450{
    451    return direntry->attributes == 0xf;
    452}
    453
    454static char is_short_name(const direntry_t* direntry)
    455{
    456    return !is_volume_label(direntry) && !is_long_name(direntry)
    457        && !is_free(direntry);
    458}
    459
    460static char is_directory(const direntry_t* direntry)
    461{
    462    return direntry->attributes & 0x10 && direntry->name[0] != DIR_DELETED;
    463}
    464
    465static inline char is_dot(const direntry_t* direntry)
    466{
    467    return is_short_name(direntry) && direntry->name[0] == '.';
    468}
    469
    470static char is_file(const direntry_t* direntry)
    471{
    472    return is_short_name(direntry) && !is_directory(direntry);
    473}
    474
    475static inline uint32_t begin_of_direntry(const direntry_t* direntry)
    476{
    477    return le16_to_cpu(direntry->begin)|(le16_to_cpu(direntry->begin_hi)<<16);
    478}
    479
    480static inline uint32_t filesize_of_direntry(const direntry_t* direntry)
    481{
    482    return le32_to_cpu(direntry->size);
    483}
    484
    485static void set_begin_of_direntry(direntry_t* direntry, uint32_t begin)
    486{
    487    direntry->begin = cpu_to_le16(begin & 0xffff);
    488    direntry->begin_hi = cpu_to_le16((begin >> 16) & 0xffff);
    489}
    490
    491static bool valid_filename(const unsigned char *name)
    492{
    493    unsigned char c;
    494    if (!strcmp((const char*)name, ".") || !strcmp((const char*)name, "..")) {
    495        return false;
    496    }
    497    for (; (c = *name); name++) {
    498        if (!((c >= '0' && c <= '9') ||
    499              (c >= 'A' && c <= 'Z') ||
    500              (c >= 'a' && c <= 'z') ||
    501              c > 127 ||
    502              strchr("$%'-_@~`!(){}^#&.+,;=[]", c) != NULL))
    503        {
    504            return false;
    505        }
    506    }
    507    return true;
    508}
    509
    510static uint8_t to_valid_short_char(gunichar c)
    511{
    512    c = g_unichar_toupper(c);
    513    if ((c >= '0' && c <= '9') ||
    514        (c >= 'A' && c <= 'Z') ||
    515        strchr("$%'-_@~`!(){}^#&", c) != NULL) {
    516        return c;
    517    } else {
    518        return 0;
    519    }
    520}
    521
    522static direntry_t *create_short_filename(BDRVVVFATState *s,
    523                                         const char *filename,
    524                                         unsigned int directory_start)
    525{
    526    int i, j = 0;
    527    direntry_t *entry = array_get_next(&(s->directory));
    528    const gchar *p, *last_dot = NULL;
    529    gunichar c;
    530    bool lossy_conversion = false;
    531    char tail[8];
    532
    533    if (!entry) {
    534        return NULL;
    535    }
    536    memset(entry->name, 0x20, sizeof(entry->name));
    537
    538    /* copy filename and search last dot */
    539    for (p = filename; ; p = g_utf8_next_char(p)) {
    540        c = g_utf8_get_char(p);
    541        if (c == '\0') {
    542            break;
    543        } else if (c == '.') {
    544            if (j == 0) {
    545                /* '.' at start of filename */
    546                lossy_conversion = true;
    547            } else {
    548                if (last_dot) {
    549                    lossy_conversion = true;
    550                }
    551                last_dot = p;
    552            }
    553        } else if (!last_dot) {
    554            /* first part of the name; copy it */
    555            uint8_t v = to_valid_short_char(c);
    556            if (j < 8 && v) {
    557                entry->name[j++] = v;
    558            } else {
    559                lossy_conversion = true;
    560            }
    561        }
    562    }
    563
    564    /* copy extension (if any) */
    565    if (last_dot) {
    566        j = 0;
    567        for (p = g_utf8_next_char(last_dot); ; p = g_utf8_next_char(p)) {
    568            c = g_utf8_get_char(p);
    569            if (c == '\0') {
    570                break;
    571            } else {
    572                /* extension; copy it */
    573                uint8_t v = to_valid_short_char(c);
    574                if (j < 3 && v) {
    575                    entry->name[8 + (j++)] = v;
    576                } else {
    577                    lossy_conversion = true;
    578                }
    579            }
    580        }
    581    }
    582
    583    if (entry->name[0] == DIR_KANJI) {
    584        entry->name[0] = DIR_KANJI_FAKE;
    585    }
    586
    587    /* numeric-tail generation */
    588    for (j = 0; j < 8; j++) {
    589        if (entry->name[j] == ' ') {
    590            break;
    591        }
    592    }
    593    for (i = lossy_conversion ? 1 : 0; i < 999999; i++) {
    594        direntry_t *entry1;
    595        if (i > 0) {
    596            int len = snprintf(tail, sizeof(tail), "~%u", (unsigned)i);
    597            assert(len <= 7);
    598            memcpy(entry->name + MIN(j, 8 - len), tail, len);
    599        }
    600        for (entry1 = array_get(&(s->directory), directory_start);
    601             entry1 < entry; entry1++) {
    602            if (!is_long_name(entry1) &&
    603                !memcmp(entry1->name, entry->name, 11)) {
    604                break; /* found dupe */
    605            }
    606        }
    607        if (entry1 == entry) {
    608            /* no dupe found */
    609            return entry;
    610        }
    611    }
    612    return NULL;
    613}
    614
    615/* fat functions */
    616
    617static inline uint8_t fat_chksum(const direntry_t* entry)
    618{
    619    uint8_t chksum=0;
    620    int i;
    621
    622    for (i = 0; i < ARRAY_SIZE(entry->name); i++) {
    623        chksum = (((chksum & 0xfe) >> 1) |
    624                  ((chksum & 0x01) ? 0x80 : 0)) + entry->name[i];
    625    }
    626
    627    return chksum;
    628}
    629
    630/* if return_time==0, this returns the fat_date, else the fat_time */
    631static uint16_t fat_datetime(time_t time,int return_time) {
    632    struct tm* t;
    633    struct tm t1;
    634    t = &t1;
    635    localtime_r(&time,t);
    636    if(return_time)
    637        return cpu_to_le16((t->tm_sec/2)|(t->tm_min<<5)|(t->tm_hour<<11));
    638    return cpu_to_le16((t->tm_mday)|((t->tm_mon+1)<<5)|((t->tm_year-80)<<9));
    639}
    640
    641static inline void fat_set(BDRVVVFATState* s,unsigned int cluster,uint32_t value)
    642{
    643    if(s->fat_type==32) {
    644        uint32_t* entry=array_get(&(s->fat),cluster);
    645        *entry=cpu_to_le32(value);
    646    } else if(s->fat_type==16) {
    647        uint16_t* entry=array_get(&(s->fat),cluster);
    648        *entry=cpu_to_le16(value&0xffff);
    649    } else {
    650        int offset = (cluster*3/2);
    651        unsigned char* p = array_get(&(s->fat), offset);
    652        switch (cluster&1) {
    653        case 0:
    654                p[0] = value&0xff;
    655                p[1] = (p[1]&0xf0) | ((value>>8)&0xf);
    656                break;
    657        case 1:
    658                p[0] = (p[0]&0xf) | ((value&0xf)<<4);
    659                p[1] = (value>>4);
    660                break;
    661        }
    662    }
    663}
    664
    665static inline uint32_t fat_get(BDRVVVFATState* s,unsigned int cluster)
    666{
    667    if(s->fat_type==32) {
    668        uint32_t* entry=array_get(&(s->fat),cluster);
    669        return le32_to_cpu(*entry);
    670    } else if(s->fat_type==16) {
    671        uint16_t* entry=array_get(&(s->fat),cluster);
    672        return le16_to_cpu(*entry);
    673    } else {
    674        const uint8_t* x=(uint8_t*)(s->fat.pointer)+cluster*3/2;
    675        return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
    676    }
    677}
    678
    679static inline int fat_eof(BDRVVVFATState* s,uint32_t fat_entry)
    680{
    681    if(fat_entry>s->max_fat_value-8)
    682        return -1;
    683    return 0;
    684}
    685
    686static inline void init_fat(BDRVVVFATState* s)
    687{
    688    if (s->fat_type == 12) {
    689        array_init(&(s->fat),1);
    690        array_ensure_allocated(&(s->fat),
    691                s->sectors_per_fat * 0x200 * 3 / 2 - 1);
    692    } else {
    693        array_init(&(s->fat),(s->fat_type==32?4:2));
    694        array_ensure_allocated(&(s->fat),
    695                s->sectors_per_fat * 0x200 / s->fat.item_size - 1);
    696    }
    697    memset(s->fat.pointer,0,s->fat.size);
    698
    699    switch(s->fat_type) {
    700        case 12: s->max_fat_value=0xfff; break;
    701        case 16: s->max_fat_value=0xffff; break;
    702        case 32: s->max_fat_value=0x0fffffff; break;
    703        default: s->max_fat_value=0; /* error... */
    704    }
    705
    706}
    707
    708static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,
    709        unsigned int directory_start, const char* filename, int is_dot)
    710{
    711    int long_index = s->directory.next;
    712    direntry_t* entry = NULL;
    713    direntry_t* entry_long = NULL;
    714
    715    if(is_dot) {
    716        entry=array_get_next(&(s->directory));
    717        memset(entry->name, 0x20, sizeof(entry->name));
    718        memcpy(entry->name,filename,strlen(filename));
    719        return entry;
    720    }
    721
    722    entry_long=create_long_filename(s,filename);
    723    entry = create_short_filename(s, filename, directory_start);
    724
    725    /* calculate checksum; propagate to long name */
    726    if(entry_long) {
    727        uint8_t chksum=fat_chksum(entry);
    728
    729        /* calculate anew, because realloc could have taken place */
    730        entry_long=array_get(&(s->directory),long_index);
    731        while(entry_long<entry && is_long_name(entry_long)) {
    732            entry_long->reserved[1]=chksum;
    733            entry_long++;
    734        }
    735    }
    736
    737    return entry;
    738}
    739
    740/*
    741 * Read a directory. (the index of the corresponding mapping must be passed).
    742 */
    743static int read_directory(BDRVVVFATState* s, int mapping_index)
    744{
    745    mapping_t* mapping = array_get(&(s->mapping), mapping_index);
    746    direntry_t* direntry;
    747    const char* dirname = mapping->path;
    748    int first_cluster = mapping->begin;
    749    int parent_index = mapping->info.dir.parent_mapping_index;
    750    mapping_t* parent_mapping = (mapping_t*)
    751        (parent_index >= 0 ? array_get(&(s->mapping), parent_index) : NULL);
    752    int first_cluster_of_parent = parent_mapping ? parent_mapping->begin : -1;
    753
    754    DIR* dir=opendir(dirname);
    755    struct dirent* entry;
    756    int i;
    757
    758    assert(mapping->mode & MODE_DIRECTORY);
    759
    760    if(!dir) {
    761        mapping->end = mapping->begin;
    762        return -1;
    763    }
    764
    765    i = mapping->info.dir.first_dir_index =
    766            first_cluster == 0 ? 0 : s->directory.next;
    767
    768    if (first_cluster != 0) {
    769        /* create the top entries of a subdirectory */
    770        (void)create_short_and_long_name(s, i, ".", 1);
    771        (void)create_short_and_long_name(s, i, "..", 1);
    772    }
    773
    774    /* actually read the directory, and allocate the mappings */
    775    while((entry=readdir(dir))) {
    776        unsigned int length=strlen(dirname)+2+strlen(entry->d_name);
    777        char* buffer;
    778        direntry_t* direntry;
    779        struct stat st;
    780        int is_dot=!strcmp(entry->d_name,".");
    781        int is_dotdot=!strcmp(entry->d_name,"..");
    782
    783        if (first_cluster == 0 && s->directory.next >= s->root_entries - 1) {
    784            fprintf(stderr, "Too many entries in root directory\n");
    785            closedir(dir);
    786            return -2;
    787        }
    788
    789        if(first_cluster == 0 && (is_dotdot || is_dot))
    790            continue;
    791
    792        buffer = g_malloc(length);
    793        snprintf(buffer,length,"%s/%s",dirname,entry->d_name);
    794
    795        if(stat(buffer,&st)<0) {
    796            g_free(buffer);
    797            continue;
    798        }
    799
    800        /* create directory entry for this file */
    801        if (!is_dot && !is_dotdot) {
    802            direntry = create_short_and_long_name(s, i, entry->d_name, 0);
    803        } else {
    804            direntry = array_get(&(s->directory), is_dot ? i : i + 1);
    805        }
    806        direntry->attributes=(S_ISDIR(st.st_mode)?0x10:0x20);
    807        direntry->reserved[0]=direntry->reserved[1]=0;
    808        direntry->ctime=fat_datetime(st.st_ctime,1);
    809        direntry->cdate=fat_datetime(st.st_ctime,0);
    810        direntry->adate=fat_datetime(st.st_atime,0);
    811        direntry->begin_hi=0;
    812        direntry->mtime=fat_datetime(st.st_mtime,1);
    813        direntry->mdate=fat_datetime(st.st_mtime,0);
    814        if(is_dotdot)
    815            set_begin_of_direntry(direntry, first_cluster_of_parent);
    816        else if(is_dot)
    817            set_begin_of_direntry(direntry, first_cluster);
    818        else
    819            direntry->begin=0; /* do that later */
    820        if (st.st_size > 0x7fffffff) {
    821            fprintf(stderr, "File %s is larger than 2GB\n", buffer);
    822            g_free(buffer);
    823            closedir(dir);
    824            return -2;
    825        }
    826        direntry->size=cpu_to_le32(S_ISDIR(st.st_mode)?0:st.st_size);
    827
    828        /* create mapping for this file */
    829        if(!is_dot && !is_dotdot && (S_ISDIR(st.st_mode) || st.st_size)) {
    830            s->current_mapping = array_get_next(&(s->mapping));
    831            s->current_mapping->begin=0;
    832            s->current_mapping->end=st.st_size;
    833            /*
    834             * we get the direntry of the most recent direntry, which
    835             * contains the short name and all the relevant information.
    836             */
    837            s->current_mapping->dir_index=s->directory.next-1;
    838            s->current_mapping->first_mapping_index = -1;
    839            if (S_ISDIR(st.st_mode)) {
    840                s->current_mapping->mode = MODE_DIRECTORY;
    841                s->current_mapping->info.dir.parent_mapping_index =
    842                    mapping_index;
    843            } else {
    844                s->current_mapping->mode = MODE_UNDEFINED;
    845                s->current_mapping->info.file.offset = 0;
    846            }
    847            s->current_mapping->path=buffer;
    848            s->current_mapping->read_only =
    849                (st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0;
    850        } else {
    851            g_free(buffer);
    852        }
    853    }
    854    closedir(dir);
    855
    856    /* fill with zeroes up to the end of the cluster */
    857    while(s->directory.next%(0x10*s->sectors_per_cluster)) {
    858        direntry_t* direntry=array_get_next(&(s->directory));
    859        memset(direntry,0,sizeof(direntry_t));
    860    }
    861
    862    if (s->fat_type != 32 &&
    863        mapping_index == 0 &&
    864        s->directory.next < s->root_entries) {
    865        /* root directory */
    866        int cur = s->directory.next;
    867        array_ensure_allocated(&(s->directory), s->root_entries - 1);
    868        s->directory.next = s->root_entries;
    869        memset(array_get(&(s->directory), cur), 0,
    870                (s->root_entries - cur) * sizeof(direntry_t));
    871    }
    872
    873    /* re-get the mapping, since s->mapping was possibly realloc()ed */
    874    mapping = array_get(&(s->mapping), mapping_index);
    875    first_cluster += (s->directory.next - mapping->info.dir.first_dir_index)
    876        * 0x20 / s->cluster_size;
    877    mapping->end = first_cluster;
    878
    879    direntry = array_get(&(s->directory), mapping->dir_index);
    880    set_begin_of_direntry(direntry, mapping->begin);
    881
    882    return 0;
    883}
    884
    885static inline uint32_t sector2cluster(BDRVVVFATState* s,off_t sector_num)
    886{
    887    return (sector_num - s->offset_to_root_dir) / s->sectors_per_cluster;
    888}
    889
    890static inline off_t cluster2sector(BDRVVVFATState* s, uint32_t cluster_num)
    891{
    892    return s->offset_to_root_dir + s->sectors_per_cluster * cluster_num;
    893}
    894
    895static int init_directories(BDRVVVFATState* s,
    896                            const char *dirname, int heads, int secs,
    897                            Error **errp)
    898{
    899    bootsector_t* bootsector;
    900    mapping_t* mapping;
    901    unsigned int i;
    902    unsigned int cluster;
    903
    904    memset(&(s->first_sectors[0]),0,0x40*0x200);
    905
    906    s->cluster_size=s->sectors_per_cluster*0x200;
    907    s->cluster_buffer=g_malloc(s->cluster_size);
    908
    909    /*
    910     * The formula: sc = spf+1+spf*spc*(512*8/fat_type),
    911     * where sc is sector_count,
    912     * spf is sectors_per_fat,
    913     * spc is sectors_per_clusters, and
    914     * fat_type = 12, 16 or 32.
    915     */
    916    i = 1+s->sectors_per_cluster*0x200*8/s->fat_type;
    917    s->sectors_per_fat=(s->sector_count+i)/i; /* round up */
    918
    919    s->offset_to_fat = s->offset_to_bootsector + 1;
    920    s->offset_to_root_dir = s->offset_to_fat + s->sectors_per_fat * 2;
    921
    922    array_init(&(s->mapping),sizeof(mapping_t));
    923    array_init(&(s->directory),sizeof(direntry_t));
    924
    925    /* add volume label */
    926    {
    927        direntry_t* entry=array_get_next(&(s->directory));
    928        entry->attributes=0x28; /* archive | volume label */
    929        memcpy(entry->name, s->volume_label, sizeof(entry->name));
    930    }
    931
    932    /* Now build FAT, and write back information into directory */
    933    init_fat(s);
    934
    935    /* TODO: if there are more entries, bootsector has to be adjusted! */
    936    s->root_entries = 0x02 * 0x10 * s->sectors_per_cluster;
    937    s->cluster_count=sector2cluster(s, s->sector_count);
    938
    939    mapping = array_get_next(&(s->mapping));
    940    mapping->begin = 0;
    941    mapping->dir_index = 0;
    942    mapping->info.dir.parent_mapping_index = -1;
    943    mapping->first_mapping_index = -1;
    944    mapping->path = g_strdup(dirname);
    945    i = strlen(mapping->path);
    946    if (i > 0 && mapping->path[i - 1] == '/')
    947        mapping->path[i - 1] = '\0';
    948    mapping->mode = MODE_DIRECTORY;
    949    mapping->read_only = 0;
    950    s->path = mapping->path;
    951
    952    for (i = 0, cluster = 0; i < s->mapping.next; i++) {
    953        /* MS-DOS expects the FAT to be 0 for the root directory
    954         * (except for the media byte). */
    955        /* LATER TODO: still true for FAT32? */
    956        int fix_fat = (i != 0);
    957        mapping = array_get(&(s->mapping), i);
    958
    959        if (mapping->mode & MODE_DIRECTORY) {
    960            char *path = mapping->path;
    961            mapping->begin = cluster;
    962            if(read_directory(s, i)) {
    963                error_setg(errp, "Could not read directory %s", path);
    964                return -1;
    965            }
    966            mapping = array_get(&(s->mapping), i);
    967        } else {
    968            assert(mapping->mode == MODE_UNDEFINED);
    969            mapping->mode=MODE_NORMAL;
    970            mapping->begin = cluster;
    971            if (mapping->end > 0) {
    972                direntry_t* direntry = array_get(&(s->directory),
    973                        mapping->dir_index);
    974
    975                mapping->end = cluster + 1 + (mapping->end-1)/s->cluster_size;
    976                set_begin_of_direntry(direntry, mapping->begin);
    977            } else {
    978                mapping->end = cluster + 1;
    979                fix_fat = 0;
    980            }
    981        }
    982
    983        assert(mapping->begin < mapping->end);
    984
    985        /* next free cluster */
    986        cluster = mapping->end;
    987
    988        if(cluster > s->cluster_count) {
    989            error_setg(errp,
    990                       "Directory does not fit in FAT%d (capacity %.2f MB)",
    991                       s->fat_type, s->sector_count / 2000.0);
    992            return -1;
    993        }
    994
    995        /* fix fat for entry */
    996        if (fix_fat) {
    997            int j;
    998            for(j = mapping->begin; j < mapping->end - 1; j++)
    999                fat_set(s, j, j+1);
   1000            fat_set(s, mapping->end - 1, s->max_fat_value);
   1001        }
   1002    }
   1003
   1004    mapping = array_get(&(s->mapping), 0);
   1005    s->last_cluster_of_root_directory = mapping->end;
   1006
   1007    /* the FAT signature */
   1008    fat_set(s,0,s->max_fat_value);
   1009    fat_set(s,1,s->max_fat_value);
   1010
   1011    s->current_mapping = NULL;
   1012
   1013    bootsector = (bootsector_t *)(s->first_sectors
   1014                                  + s->offset_to_bootsector * 0x200);
   1015    bootsector->jump[0]=0xeb;
   1016    bootsector->jump[1]=0x3e;
   1017    bootsector->jump[2]=0x90;
   1018    memcpy(bootsector->name, BOOTSECTOR_OEM_NAME, 8);
   1019    bootsector->sector_size=cpu_to_le16(0x200);
   1020    bootsector->sectors_per_cluster=s->sectors_per_cluster;
   1021    bootsector->reserved_sectors=cpu_to_le16(1);
   1022    bootsector->number_of_fats=0x2; /* number of FATs */
   1023    bootsector->root_entries = cpu_to_le16(s->root_entries);
   1024    bootsector->total_sectors16=s->sector_count>0xffff?0:cpu_to_le16(s->sector_count);
   1025    /* media descriptor: hard disk=0xf8, floppy=0xf0 */
   1026    bootsector->media_type = (s->offset_to_bootsector > 0 ? 0xf8 : 0xf0);
   1027    s->fat.pointer[0] = bootsector->media_type;
   1028    bootsector->sectors_per_fat=cpu_to_le16(s->sectors_per_fat);
   1029    bootsector->sectors_per_track = cpu_to_le16(secs);
   1030    bootsector->number_of_heads = cpu_to_le16(heads);
   1031    bootsector->hidden_sectors = cpu_to_le32(s->offset_to_bootsector);
   1032    bootsector->total_sectors=cpu_to_le32(s->sector_count>0xffff?s->sector_count:0);
   1033
   1034    /* LATER TODO: if FAT32, this is wrong */
   1035    /* drive_number: fda=0, hda=0x80 */
   1036    bootsector->u.fat16.drive_number = s->offset_to_bootsector == 0 ? 0 : 0x80;
   1037    bootsector->u.fat16.signature=0x29;
   1038    bootsector->u.fat16.id=cpu_to_le32(0xfabe1afd);
   1039
   1040    memcpy(bootsector->u.fat16.volume_label, s->volume_label,
   1041           sizeof(bootsector->u.fat16.volume_label));
   1042    memcpy(bootsector->u.fat16.fat_type,
   1043           s->fat_type == 12 ? "FAT12   " : "FAT16   ", 8);
   1044    bootsector->magic[0]=0x55; bootsector->magic[1]=0xaa;
   1045
   1046    return 0;
   1047}
   1048
   1049#ifdef DEBUG
   1050static BDRVVVFATState *vvv = NULL;
   1051#endif
   1052
   1053static int enable_write_target(BlockDriverState *bs, Error **errp);
   1054static int is_consistent(BDRVVVFATState *s);
   1055
   1056static QemuOptsList runtime_opts = {
   1057    .name = "vvfat",
   1058    .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
   1059    .desc = {
   1060        {
   1061            .name = "dir",
   1062            .type = QEMU_OPT_STRING,
   1063            .help = "Host directory to map to the vvfat device",
   1064        },
   1065        {
   1066            .name = "fat-type",
   1067            .type = QEMU_OPT_NUMBER,
   1068            .help = "FAT type (12, 16 or 32)",
   1069        },
   1070        {
   1071            .name = "floppy",
   1072            .type = QEMU_OPT_BOOL,
   1073            .help = "Create a floppy rather than a hard disk image",
   1074        },
   1075        {
   1076            .name = "label",
   1077            .type = QEMU_OPT_STRING,
   1078            .help = "Use a volume label other than QEMU VVFAT",
   1079        },
   1080        {
   1081            .name = "rw",
   1082            .type = QEMU_OPT_BOOL,
   1083            .help = "Make the image writable",
   1084        },
   1085        { /* end of list */ }
   1086    },
   1087};
   1088
   1089static void vvfat_parse_filename(const char *filename, QDict *options,
   1090                                 Error **errp)
   1091{
   1092    int fat_type = 0;
   1093    bool floppy = false;
   1094    bool rw = false;
   1095    int i;
   1096
   1097    if (!strstart(filename, "fat:", NULL)) {
   1098        error_setg(errp, "File name string must start with 'fat:'");
   1099        return;
   1100    }
   1101
   1102    /* Parse options */
   1103    if (strstr(filename, ":32:")) {
   1104        fat_type = 32;
   1105    } else if (strstr(filename, ":16:")) {
   1106        fat_type = 16;
   1107    } else if (strstr(filename, ":12:")) {
   1108        fat_type = 12;
   1109    }
   1110
   1111    if (strstr(filename, ":floppy:")) {
   1112        floppy = true;
   1113    }
   1114
   1115    if (strstr(filename, ":rw:")) {
   1116        rw = true;
   1117    }
   1118
   1119    /* Get the directory name without options */
   1120    i = strrchr(filename, ':') - filename;
   1121    assert(i >= 3);
   1122    if (filename[i - 2] == ':' && qemu_isalpha(filename[i - 1])) {
   1123        /* workaround for DOS drive names */
   1124        filename += i - 1;
   1125    } else {
   1126        filename += i + 1;
   1127    }
   1128
   1129    /* Fill in the options QDict */
   1130    qdict_put_str(options, "dir", filename);
   1131    qdict_put_int(options, "fat-type", fat_type);
   1132    qdict_put_bool(options, "floppy", floppy);
   1133    qdict_put_bool(options, "rw", rw);
   1134}
   1135
   1136static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
   1137                      Error **errp)
   1138{
   1139    BDRVVVFATState *s = bs->opaque;
   1140    int cyls, heads, secs;
   1141    bool floppy;
   1142    const char *dirname, *label;
   1143    QemuOpts *opts;
   1144    int ret;
   1145
   1146#ifdef DEBUG
   1147    vvv = s;
   1148#endif
   1149
   1150    opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
   1151    if (!qemu_opts_absorb_qdict(opts, options, errp)) {
   1152        ret = -EINVAL;
   1153        goto fail;
   1154    }
   1155
   1156    dirname = qemu_opt_get(opts, "dir");
   1157    if (!dirname) {
   1158        error_setg(errp, "vvfat block driver requires a 'dir' option");
   1159        ret = -EINVAL;
   1160        goto fail;
   1161    }
   1162
   1163    s->fat_type = qemu_opt_get_number(opts, "fat-type", 0);
   1164    floppy = qemu_opt_get_bool(opts, "floppy", false);
   1165
   1166    memset(s->volume_label, ' ', sizeof(s->volume_label));
   1167    label = qemu_opt_get(opts, "label");
   1168    if (label) {
   1169        size_t label_length = strlen(label);
   1170        if (label_length > 11) {
   1171            error_setg(errp, "vvfat label cannot be longer than 11 bytes");
   1172            ret = -EINVAL;
   1173            goto fail;
   1174        }
   1175        memcpy(s->volume_label, label, label_length);
   1176    } else {
   1177        memcpy(s->volume_label, "QEMU VVFAT", 10);
   1178    }
   1179
   1180    if (floppy) {
   1181        /* 1.44MB or 2.88MB floppy.  2.88MB can be FAT12 (default) or FAT16. */
   1182        if (!s->fat_type) {
   1183            s->fat_type = 12;
   1184            secs = 36;
   1185            s->sectors_per_cluster = 2;
   1186        } else {
   1187            secs = s->fat_type == 12 ? 18 : 36;
   1188            s->sectors_per_cluster = 1;
   1189        }
   1190        cyls = 80;
   1191        heads = 2;
   1192    } else {
   1193        /* 32MB or 504MB disk*/
   1194        if (!s->fat_type) {
   1195            s->fat_type = 16;
   1196        }
   1197        s->offset_to_bootsector = 0x3f;
   1198        cyls = s->fat_type == 12 ? 64 : 1024;
   1199        heads = 16;
   1200        secs = 63;
   1201    }
   1202
   1203    switch (s->fat_type) {
   1204    case 32:
   1205        warn_report("FAT32 has not been tested. You are welcome to do so!");
   1206        break;
   1207    case 16:
   1208    case 12:
   1209        break;
   1210    default:
   1211        error_setg(errp, "Valid FAT types are only 12, 16 and 32");
   1212        ret = -EINVAL;
   1213        goto fail;
   1214    }
   1215
   1216
   1217    s->bs = bs;
   1218
   1219    /* LATER TODO: if FAT32, adjust */
   1220    s->sectors_per_cluster=0x10;
   1221
   1222    s->current_cluster=0xffffffff;
   1223
   1224    s->qcow = NULL;
   1225    s->qcow_filename = NULL;
   1226    s->fat2 = NULL;
   1227    s->downcase_short_names = 1;
   1228
   1229    DLOG(fprintf(stderr, "vvfat %s chs %d,%d,%d\n",
   1230                 dirname, cyls, heads, secs));
   1231
   1232    s->sector_count = cyls * heads * secs - s->offset_to_bootsector;
   1233
   1234    if (qemu_opt_get_bool(opts, "rw", false)) {
   1235        if (!bdrv_is_read_only(bs)) {
   1236            ret = enable_write_target(bs, errp);
   1237            if (ret < 0) {
   1238                goto fail;
   1239            }
   1240        } else {
   1241            ret = -EPERM;
   1242            error_setg(errp,
   1243                       "Unable to set VVFAT to 'rw' when drive is read-only");
   1244            goto fail;
   1245        }
   1246    } else {
   1247        ret = bdrv_apply_auto_read_only(bs, NULL, errp);
   1248        if (ret < 0) {
   1249            goto fail;
   1250        }
   1251    }
   1252
   1253    bs->total_sectors = cyls * heads * secs;
   1254
   1255    if (init_directories(s, dirname, heads, secs, errp)) {
   1256        ret = -EIO;
   1257        goto fail;
   1258    }
   1259
   1260    s->sector_count = s->offset_to_root_dir
   1261                    + s->sectors_per_cluster * s->cluster_count;
   1262
   1263    /* Disable migration when vvfat is used rw */
   1264    if (s->qcow) {
   1265        error_setg(&s->migration_blocker,
   1266                   "The vvfat (rw) format used by node '%s' "
   1267                   "does not support live migration",
   1268                   bdrv_get_device_or_node_name(bs));
   1269        ret = migrate_add_blocker(s->migration_blocker, errp);
   1270        if (ret < 0) {
   1271            error_free(s->migration_blocker);
   1272            goto fail;
   1273        }
   1274    }
   1275
   1276    if (s->offset_to_bootsector > 0) {
   1277        init_mbr(s, cyls, heads, secs);
   1278    }
   1279
   1280    qemu_co_mutex_init(&s->lock);
   1281
   1282    ret = 0;
   1283fail:
   1284    qemu_opts_del(opts);
   1285    return ret;
   1286}
   1287
   1288static void vvfat_refresh_limits(BlockDriverState *bs, Error **errp)
   1289{
   1290    bs->bl.request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O */
   1291}
   1292
   1293static inline void vvfat_close_current_file(BDRVVVFATState *s)
   1294{
   1295    if(s->current_mapping) {
   1296        s->current_mapping = NULL;
   1297        if (s->current_fd) {
   1298                qemu_close(s->current_fd);
   1299                s->current_fd = 0;
   1300        }
   1301    }
   1302    s->current_cluster = -1;
   1303}
   1304
   1305/* mappings between index1 and index2-1 are supposed to be ordered
   1306 * return value is the index of the last mapping for which end>cluster_num
   1307 */
   1308static inline int find_mapping_for_cluster_aux(BDRVVVFATState* s,int cluster_num,int index1,int index2)
   1309{
   1310    while(1) {
   1311        int index3;
   1312        mapping_t* mapping;
   1313        index3=(index1+index2)/2;
   1314        mapping=array_get(&(s->mapping),index3);
   1315        assert(mapping->begin < mapping->end);
   1316        if(mapping->begin>=cluster_num) {
   1317            assert(index2!=index3 || index2==0);
   1318            if(index2==index3)
   1319                return index1;
   1320            index2=index3;
   1321        } else {
   1322            if(index1==index3)
   1323                return mapping->end<=cluster_num ? index2 : index1;
   1324            index1=index3;
   1325        }
   1326        assert(index1<=index2);
   1327        DLOG(mapping=array_get(&(s->mapping),index1);
   1328        assert(mapping->begin<=cluster_num);
   1329        assert(index2 >= s->mapping.next ||
   1330                ((mapping = array_get(&(s->mapping),index2)) &&
   1331                mapping->end>cluster_num)));
   1332    }
   1333}
   1334
   1335static inline mapping_t* find_mapping_for_cluster(BDRVVVFATState* s,int cluster_num)
   1336{
   1337    int index=find_mapping_for_cluster_aux(s,cluster_num,0,s->mapping.next);
   1338    mapping_t* mapping;
   1339    if(index>=s->mapping.next)
   1340        return NULL;
   1341    mapping=array_get(&(s->mapping),index);
   1342    if(mapping->begin>cluster_num)
   1343        return NULL;
   1344    assert(mapping->begin<=cluster_num && mapping->end>cluster_num);
   1345    return mapping;
   1346}
   1347
   1348static int open_file(BDRVVVFATState* s,mapping_t* mapping)
   1349{
   1350    if(!mapping)
   1351        return -1;
   1352    if(!s->current_mapping ||
   1353            strcmp(s->current_mapping->path,mapping->path)) {
   1354        /* open file */
   1355        int fd = qemu_open_old(mapping->path,
   1356                               O_RDONLY | O_BINARY | O_LARGEFILE);
   1357        if(fd<0)
   1358            return -1;
   1359        vvfat_close_current_file(s);
   1360        s->current_fd = fd;
   1361        s->current_mapping = mapping;
   1362    }
   1363    return 0;
   1364}
   1365
   1366static inline int read_cluster(BDRVVVFATState *s,int cluster_num)
   1367{
   1368    if(s->current_cluster != cluster_num) {
   1369        int result=0;
   1370        off_t offset;
   1371        assert(!s->current_mapping || s->current_fd || (s->current_mapping->mode & MODE_DIRECTORY));
   1372        if(!s->current_mapping
   1373                || s->current_mapping->begin>cluster_num
   1374                || s->current_mapping->end<=cluster_num) {
   1375            /* binary search of mappings for file */
   1376            mapping_t* mapping=find_mapping_for_cluster(s,cluster_num);
   1377
   1378            assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
   1379
   1380            if (mapping && mapping->mode & MODE_DIRECTORY) {
   1381                vvfat_close_current_file(s);
   1382                s->current_mapping = mapping;
   1383read_cluster_directory:
   1384                offset = s->cluster_size*(cluster_num-s->current_mapping->begin);
   1385                s->cluster = (unsigned char*)s->directory.pointer+offset
   1386                        + 0x20*s->current_mapping->info.dir.first_dir_index;
   1387                assert(((s->cluster-(unsigned char*)s->directory.pointer)%s->cluster_size)==0);
   1388                assert((char*)s->cluster+s->cluster_size <= s->directory.pointer+s->directory.next*s->directory.item_size);
   1389                s->current_cluster = cluster_num;
   1390                return 0;
   1391            }
   1392
   1393            if(open_file(s,mapping))
   1394                return -2;
   1395        } else if (s->current_mapping->mode & MODE_DIRECTORY)
   1396            goto read_cluster_directory;
   1397
   1398        assert(s->current_fd);
   1399
   1400        offset=s->cluster_size*(cluster_num-s->current_mapping->begin)+s->current_mapping->info.file.offset;
   1401        if(lseek(s->current_fd, offset, SEEK_SET)!=offset)
   1402            return -3;
   1403        s->cluster=s->cluster_buffer;
   1404        result=read(s->current_fd,s->cluster,s->cluster_size);
   1405        if(result<0) {
   1406            s->current_cluster = -1;
   1407            return -1;
   1408        }
   1409        s->current_cluster = cluster_num;
   1410    }
   1411    return 0;
   1412}
   1413
   1414#ifdef DEBUG
   1415static void print_direntry(const direntry_t* direntry)
   1416{
   1417    int j = 0;
   1418    char buffer[1024];
   1419
   1420    fprintf(stderr, "direntry %p: ", direntry);
   1421    if(!direntry)
   1422        return;
   1423    if(is_long_name(direntry)) {
   1424        unsigned char* c=(unsigned char*)direntry;
   1425        int i;
   1426        for(i=1;i<11 && c[i] && c[i]!=0xff;i+=2)
   1427#define ADD_CHAR(c) {buffer[j] = (c); if (buffer[j] < ' ') buffer[j] = 0xb0; j++;}
   1428            ADD_CHAR(c[i]);
   1429        for(i=14;i<26 && c[i] && c[i]!=0xff;i+=2)
   1430            ADD_CHAR(c[i]);
   1431        for(i=28;i<32 && c[i] && c[i]!=0xff;i+=2)
   1432            ADD_CHAR(c[i]);
   1433        buffer[j] = 0;
   1434        fprintf(stderr, "%s\n", buffer);
   1435    } else {
   1436        int i;
   1437        for(i=0;i<11;i++)
   1438            ADD_CHAR(direntry->name[i]);
   1439        buffer[j] = 0;
   1440        fprintf(stderr, "%s attributes=0x%02x begin=%u size=%u\n",
   1441                buffer,
   1442                direntry->attributes,
   1443                begin_of_direntry(direntry),le32_to_cpu(direntry->size));
   1444    }
   1445}
   1446
   1447static void print_mapping(const mapping_t* mapping)
   1448{
   1449    fprintf(stderr, "mapping (%p): begin, end = %u, %u, dir_index = %u, "
   1450        "first_mapping_index = %d, name = %s, mode = 0x%x, " ,
   1451        mapping, mapping->begin, mapping->end, mapping->dir_index,
   1452        mapping->first_mapping_index, mapping->path, mapping->mode);
   1453
   1454    if (mapping->mode & MODE_DIRECTORY)
   1455        fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
   1456    else
   1457        fprintf(stderr, "offset = %u\n", mapping->info.file.offset);
   1458}
   1459#endif
   1460
   1461static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
   1462                    uint8_t *buf, int nb_sectors)
   1463{
   1464    BDRVVVFATState *s = bs->opaque;
   1465    int i;
   1466
   1467    for(i=0;i<nb_sectors;i++,sector_num++) {
   1468        if (sector_num >= bs->total_sectors)
   1469           return -1;
   1470        if (s->qcow) {
   1471            int64_t n;
   1472            int ret;
   1473            ret = bdrv_is_allocated(s->qcow->bs, sector_num * BDRV_SECTOR_SIZE,
   1474                                    (nb_sectors - i) * BDRV_SECTOR_SIZE, &n);
   1475            if (ret < 0) {
   1476                return ret;
   1477            }
   1478            if (ret) {
   1479                DLOG(fprintf(stderr, "sectors %" PRId64 "+%" PRId64
   1480                             " allocated\n", sector_num,
   1481                             n >> BDRV_SECTOR_BITS));
   1482                if (bdrv_pread(s->qcow, sector_num * BDRV_SECTOR_SIZE,
   1483                               buf + i * 0x200, n) < 0) {
   1484                    return -1;
   1485                }
   1486                i += (n >> BDRV_SECTOR_BITS) - 1;
   1487                sector_num += (n >> BDRV_SECTOR_BITS) - 1;
   1488                continue;
   1489            }
   1490            DLOG(fprintf(stderr, "sector %" PRId64 " not allocated\n",
   1491                         sector_num));
   1492        }
   1493        if (sector_num < s->offset_to_root_dir) {
   1494            if (sector_num < s->offset_to_fat) {
   1495                memcpy(buf + i * 0x200,
   1496                       &(s->first_sectors[sector_num * 0x200]),
   1497                       0x200);
   1498            } else if (sector_num < s->offset_to_fat + s->sectors_per_fat) {
   1499                memcpy(buf + i * 0x200,
   1500                       &(s->fat.pointer[(sector_num
   1501                                       - s->offset_to_fat) * 0x200]),
   1502                       0x200);
   1503            } else if (sector_num < s->offset_to_root_dir) {
   1504                memcpy(buf + i * 0x200,
   1505                       &(s->fat.pointer[(sector_num - s->offset_to_fat
   1506                                       - s->sectors_per_fat) * 0x200]),
   1507                       0x200);
   1508            }
   1509        } else {
   1510            uint32_t sector = sector_num - s->offset_to_root_dir,
   1511            sector_offset_in_cluster=(sector%s->sectors_per_cluster),
   1512            cluster_num=sector/s->sectors_per_cluster;
   1513            if(cluster_num > s->cluster_count || read_cluster(s, cluster_num) != 0) {
   1514                /* LATER TODO: strict: return -1; */
   1515                memset(buf+i*0x200,0,0x200);
   1516                continue;
   1517            }
   1518            memcpy(buf+i*0x200,s->cluster+sector_offset_in_cluster*0x200,0x200);
   1519        }
   1520    }
   1521    return 0;
   1522}
   1523
   1524static int coroutine_fn
   1525vvfat_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
   1526                QEMUIOVector *qiov, BdrvRequestFlags flags)
   1527{
   1528    int ret;
   1529    BDRVVVFATState *s = bs->opaque;
   1530    uint64_t sector_num = offset >> BDRV_SECTOR_BITS;
   1531    int nb_sectors = bytes >> BDRV_SECTOR_BITS;
   1532    void *buf;
   1533
   1534    assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
   1535    assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
   1536
   1537    buf = g_try_malloc(bytes);
   1538    if (bytes && buf == NULL) {
   1539        return -ENOMEM;
   1540    }
   1541
   1542    qemu_co_mutex_lock(&s->lock);
   1543    ret = vvfat_read(bs, sector_num, buf, nb_sectors);
   1544    qemu_co_mutex_unlock(&s->lock);
   1545
   1546    qemu_iovec_from_buf(qiov, 0, buf, bytes);
   1547    g_free(buf);
   1548
   1549    return ret;
   1550}
   1551
   1552/* LATER TODO: statify all functions */
   1553
   1554/*
   1555 * Idea of the write support (use snapshot):
   1556 *
   1557 * 1. check if all data is consistent, recording renames, modifications,
   1558 *    new files and directories (in s->commits).
   1559 *
   1560 * 2. if the data is not consistent, stop committing
   1561 *
   1562 * 3. handle renames, and create new files and directories (do not yet
   1563 *    write their contents)
   1564 *
   1565 * 4. walk the directories, fixing the mapping and direntries, and marking
   1566 *    the handled mappings as not deleted
   1567 *
   1568 * 5. commit the contents of the files
   1569 *
   1570 * 6. handle deleted files and directories
   1571 *
   1572 */
   1573
   1574typedef struct commit_t {
   1575    char* path;
   1576    union {
   1577        struct { uint32_t cluster; } rename;
   1578        struct { int dir_index; uint32_t modified_offset; } writeout;
   1579        struct { uint32_t first_cluster; } new_file;
   1580        struct { uint32_t cluster; } mkdir;
   1581    } param;
   1582    /* DELETEs and RMDIRs are handled differently: see handle_deletes() */
   1583    enum {
   1584        ACTION_RENAME, ACTION_WRITEOUT, ACTION_NEW_FILE, ACTION_MKDIR
   1585    } action;
   1586} commit_t;
   1587
   1588static void clear_commits(BDRVVVFATState* s)
   1589{
   1590    int i;
   1591DLOG(fprintf(stderr, "clear_commits (%u commits)\n", s->commits.next));
   1592    for (i = 0; i < s->commits.next; i++) {
   1593        commit_t* commit = array_get(&(s->commits), i);
   1594        assert(commit->path || commit->action == ACTION_WRITEOUT);
   1595        if (commit->action != ACTION_WRITEOUT) {
   1596            assert(commit->path);
   1597            g_free(commit->path);
   1598        } else
   1599            assert(commit->path == NULL);
   1600    }
   1601    s->commits.next = 0;
   1602}
   1603
   1604static void schedule_rename(BDRVVVFATState* s,
   1605        uint32_t cluster, char* new_path)
   1606{
   1607    commit_t* commit = array_get_next(&(s->commits));
   1608    commit->path = new_path;
   1609    commit->param.rename.cluster = cluster;
   1610    commit->action = ACTION_RENAME;
   1611}
   1612
   1613static void schedule_writeout(BDRVVVFATState* s,
   1614        int dir_index, uint32_t modified_offset)
   1615{
   1616    commit_t* commit = array_get_next(&(s->commits));
   1617    commit->path = NULL;
   1618    commit->param.writeout.dir_index = dir_index;
   1619    commit->param.writeout.modified_offset = modified_offset;
   1620    commit->action = ACTION_WRITEOUT;
   1621}
   1622
   1623static void schedule_new_file(BDRVVVFATState* s,
   1624        char* path, uint32_t first_cluster)
   1625{
   1626    commit_t* commit = array_get_next(&(s->commits));
   1627    commit->path = path;
   1628    commit->param.new_file.first_cluster = first_cluster;
   1629    commit->action = ACTION_NEW_FILE;
   1630}
   1631
   1632static void schedule_mkdir(BDRVVVFATState* s, uint32_t cluster, char* path)
   1633{
   1634    commit_t* commit = array_get_next(&(s->commits));
   1635    commit->path = path;
   1636    commit->param.mkdir.cluster = cluster;
   1637    commit->action = ACTION_MKDIR;
   1638}
   1639
   1640typedef struct {
   1641    /*
   1642     * Since the sequence number is at most 0x3f, and the filename
   1643     * length is at most 13 times the sequence number, the maximal
   1644     * filename length is 0x3f * 13 bytes.
   1645     */
   1646    unsigned char name[0x3f * 13 + 1];
   1647    gunichar2 name2[0x3f * 13 + 1];
   1648    int checksum, len;
   1649    int sequence_number;
   1650} long_file_name;
   1651
   1652static void lfn_init(long_file_name* lfn)
   1653{
   1654   lfn->sequence_number = lfn->len = 0;
   1655   lfn->checksum = 0x100;
   1656}
   1657
   1658/* return 0 if parsed successfully, > 0 if no long name, < 0 if error */
   1659static int parse_long_name(long_file_name* lfn,
   1660        const direntry_t* direntry)
   1661{
   1662    int i, j, offset;
   1663    const unsigned char* pointer = (const unsigned char*)direntry;
   1664
   1665    if (!is_long_name(direntry))
   1666        return 1;
   1667
   1668    if (pointer[0] & 0x40) {
   1669        /* first entry; do some initialization */
   1670        lfn->sequence_number = pointer[0] & 0x3f;
   1671        lfn->checksum = pointer[13];
   1672        lfn->name[0] = 0;
   1673        lfn->name[lfn->sequence_number * 13] = 0;
   1674    } else if ((pointer[0] & 0x3f) != --lfn->sequence_number) {
   1675        /* not the expected sequence number */
   1676        return -1;
   1677    } else if (pointer[13] != lfn->checksum) {
   1678        /* not the expected checksum */
   1679        return -2;
   1680    } else if (pointer[12] || pointer[26] || pointer[27]) {
   1681        /* invalid zero fields */
   1682        return -3;
   1683    }
   1684
   1685    offset = 13 * (lfn->sequence_number - 1);
   1686    for (i = 0, j = 1; i < 13; i++, j+=2) {
   1687        if (j == 11)
   1688            j = 14;
   1689        else if (j == 26)
   1690            j = 28;
   1691
   1692        if (pointer[j] == 0 && pointer[j + 1] == 0) {
   1693            /* end of long file name */
   1694            break;
   1695        }
   1696        gunichar2 c = (pointer[j + 1] << 8) + pointer[j];
   1697        lfn->name2[offset + i] = c;
   1698    }
   1699
   1700    if (pointer[0] & 0x40) {
   1701        /* first entry; set len */
   1702        lfn->len = offset + i;
   1703    }
   1704    if ((pointer[0] & 0x3f) == 0x01) {
   1705        /* last entry; finalize entry */
   1706        glong olen;
   1707        gchar *utf8 = g_utf16_to_utf8(lfn->name2, lfn->len, NULL, &olen, NULL);
   1708        if (!utf8) {
   1709            return -4;
   1710        }
   1711        lfn->len = olen;
   1712        memcpy(lfn->name, utf8, olen + 1);
   1713        g_free(utf8);
   1714    }
   1715
   1716    return 0;
   1717}
   1718
   1719/* returns 0 if successful, >0 if no short_name, and <0 on error */
   1720static int parse_short_name(BDRVVVFATState* s,
   1721        long_file_name* lfn, direntry_t* direntry)
   1722{
   1723    int i, j;
   1724
   1725    if (!is_short_name(direntry))
   1726        return 1;
   1727
   1728    for (j = 7; j >= 0 && direntry->name[j] == ' '; j--);
   1729    for (i = 0; i <= j; i++) {
   1730        uint8_t c = direntry->name[i];
   1731        if (c != to_valid_short_char(c)) {
   1732            return -1;
   1733        } else if (s->downcase_short_names) {
   1734            lfn->name[i] = qemu_tolower(direntry->name[i]);
   1735        } else {
   1736            lfn->name[i] = direntry->name[i];
   1737        }
   1738    }
   1739
   1740    for (j = 2; j >= 0 && direntry->name[8 + j] == ' '; j--) {
   1741    }
   1742    if (j >= 0) {
   1743        lfn->name[i++] = '.';
   1744        lfn->name[i + j + 1] = '\0';
   1745        for (;j >= 0; j--) {
   1746            uint8_t c = direntry->name[8 + j];
   1747            if (c != to_valid_short_char(c)) {
   1748                return -2;
   1749            } else if (s->downcase_short_names) {
   1750                lfn->name[i + j] = qemu_tolower(c);
   1751            } else {
   1752                lfn->name[i + j] = c;
   1753            }
   1754        }
   1755    } else
   1756        lfn->name[i + j + 1] = '\0';
   1757
   1758    if (lfn->name[0] == DIR_KANJI_FAKE) {
   1759        lfn->name[0] = DIR_KANJI;
   1760    }
   1761    lfn->len = strlen((char*)lfn->name);
   1762
   1763    return 0;
   1764}
   1765
   1766static inline uint32_t modified_fat_get(BDRVVVFATState* s,
   1767        unsigned int cluster)
   1768{
   1769    if (cluster < s->last_cluster_of_root_directory) {
   1770        if (cluster + 1 == s->last_cluster_of_root_directory)
   1771            return s->max_fat_value;
   1772        else
   1773            return cluster + 1;
   1774    }
   1775
   1776    if (s->fat_type==32) {
   1777        uint32_t* entry=((uint32_t*)s->fat2)+cluster;
   1778        return le32_to_cpu(*entry);
   1779    } else if (s->fat_type==16) {
   1780        uint16_t* entry=((uint16_t*)s->fat2)+cluster;
   1781        return le16_to_cpu(*entry);
   1782    } else {
   1783        const uint8_t* x=s->fat2+cluster*3/2;
   1784        return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
   1785    }
   1786}
   1787
   1788static inline bool cluster_was_modified(BDRVVVFATState *s,
   1789                                        uint32_t cluster_num)
   1790{
   1791    int was_modified = 0;
   1792    int i;
   1793
   1794    if (s->qcow == NULL) {
   1795        return 0;
   1796    }
   1797
   1798    for (i = 0; !was_modified && i < s->sectors_per_cluster; i++) {
   1799        was_modified = bdrv_is_allocated(s->qcow->bs,
   1800                                         (cluster2sector(s, cluster_num) +
   1801                                          i) * BDRV_SECTOR_SIZE,
   1802                                         BDRV_SECTOR_SIZE, NULL);
   1803    }
   1804
   1805    /*
   1806     * Note that this treats failures to learn allocation status the
   1807     * same as if an allocation has occurred.  It's as safe as
   1808     * anything else, given that a failure to learn allocation status
   1809     * will probably result in more failures.
   1810     */
   1811    return !!was_modified;
   1812}
   1813
   1814static const char* get_basename(const char* path)
   1815{
   1816    char* basename = strrchr(path, '/');
   1817    if (basename == NULL)
   1818        return path;
   1819    else
   1820        return basename + 1; /* strip '/' */
   1821}
   1822
   1823/*
   1824 * The array s->used_clusters holds the states of the clusters. If it is
   1825 * part of a file, it has bit 2 set, in case of a directory, bit 1. If it
   1826 * was modified, bit 3 is set.
   1827 * If any cluster is allocated, but not part of a file or directory, this
   1828 * driver refuses to commit.
   1829 */
   1830typedef enum {
   1831     USED_DIRECTORY = 1, USED_FILE = 2, USED_ANY = 3, USED_ALLOCATED = 4
   1832} used_t;
   1833
   1834/*
   1835 * get_cluster_count_for_direntry() not only determines how many clusters
   1836 * are occupied by direntry, but also if it was renamed or modified.
   1837 *
   1838 * A file is thought to be renamed *only* if there already was a file with
   1839 * exactly the same first cluster, but a different name.
   1840 *
   1841 * Further, the files/directories handled by this function are
   1842 * assumed to be *not* deleted (and *only* those).
   1843 */
   1844static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
   1845        direntry_t* direntry, const char* path)
   1846{
   1847    /*
   1848     * This is a little bit tricky:
   1849     * IF the guest OS just inserts a cluster into the file chain,
   1850     * and leaves the rest alone, (i.e. the original file had clusters
   1851     * 15 -> 16, but now has 15 -> 32 -> 16), then the following happens:
   1852     *
   1853     * - do_commit will write the cluster into the file at the given
   1854     *   offset, but
   1855     *
   1856     * - the cluster which is overwritten should be moved to a later
   1857     *   position in the file.
   1858     *
   1859     * I am not aware that any OS does something as braindead, but this
   1860     * situation could happen anyway when not committing for a long time.
   1861     * Just to be sure that this does not bite us, detect it, and copy the
   1862     * contents of the clusters to-be-overwritten into the qcow.
   1863     */
   1864    int copy_it = 0;
   1865    int was_modified = 0;
   1866    int32_t ret = 0;
   1867
   1868    uint32_t cluster_num = begin_of_direntry(direntry);
   1869    uint32_t offset = 0;
   1870    int first_mapping_index = -1;
   1871    mapping_t* mapping = NULL;
   1872    const char* basename2 = NULL;
   1873
   1874    vvfat_close_current_file(s);
   1875
   1876    /* the root directory */
   1877    if (cluster_num == 0)
   1878        return 0;
   1879
   1880    /* write support */
   1881    if (s->qcow) {
   1882        basename2 = get_basename(path);
   1883
   1884        mapping = find_mapping_for_cluster(s, cluster_num);
   1885
   1886        if (mapping) {
   1887            const char* basename;
   1888
   1889            assert(mapping->mode & MODE_DELETED);
   1890            mapping->mode &= ~MODE_DELETED;
   1891
   1892            basename = get_basename(mapping->path);
   1893
   1894            assert(mapping->mode & MODE_NORMAL);
   1895
   1896            /* rename */
   1897            if (strcmp(basename, basename2))
   1898                schedule_rename(s, cluster_num, g_strdup(path));
   1899        } else if (is_file(direntry))
   1900            /* new file */
   1901            schedule_new_file(s, g_strdup(path), cluster_num);
   1902        else {
   1903            abort();
   1904            return 0;
   1905        }
   1906    }
   1907
   1908    while(1) {
   1909        if (s->qcow) {
   1910            if (!copy_it && cluster_was_modified(s, cluster_num)) {
   1911                if (mapping == NULL ||
   1912                        mapping->begin > cluster_num ||
   1913                        mapping->end <= cluster_num)
   1914                mapping = find_mapping_for_cluster(s, cluster_num);
   1915
   1916
   1917                if (mapping &&
   1918                        (mapping->mode & MODE_DIRECTORY) == 0) {
   1919
   1920                    /* was modified in qcow */
   1921                    if (offset != mapping->info.file.offset + s->cluster_size
   1922                            * (cluster_num - mapping->begin)) {
   1923                        /* offset of this cluster in file chain has changed */
   1924                        abort();
   1925                        copy_it = 1;
   1926                    } else if (offset == 0) {
   1927                        const char* basename = get_basename(mapping->path);
   1928
   1929                        if (strcmp(basename, basename2))
   1930                            copy_it = 1;
   1931                        first_mapping_index = array_index(&(s->mapping), mapping);
   1932                    }
   1933
   1934                    if (mapping->first_mapping_index != first_mapping_index
   1935                            && mapping->info.file.offset > 0) {
   1936                        abort();
   1937                        copy_it = 1;
   1938                    }
   1939
   1940                    /* need to write out? */
   1941                    if (!was_modified && is_file(direntry)) {
   1942                        was_modified = 1;
   1943                        schedule_writeout(s, mapping->dir_index, offset);
   1944                    }
   1945                }
   1946            }
   1947
   1948            if (copy_it) {
   1949                int i;
   1950                /*
   1951                 * This is horribly inefficient, but that is okay, since
   1952                 * it is rarely executed, if at all.
   1953                 */
   1954                int64_t offset = cluster2sector(s, cluster_num);
   1955
   1956                vvfat_close_current_file(s);
   1957                for (i = 0; i < s->sectors_per_cluster; i++) {
   1958                    int res;
   1959
   1960                    res = bdrv_is_allocated(s->qcow->bs,
   1961                                            (offset + i) * BDRV_SECTOR_SIZE,
   1962                                            BDRV_SECTOR_SIZE, NULL);
   1963                    if (res < 0) {
   1964                        return -1;
   1965                    }
   1966                    if (!res) {
   1967                        res = vvfat_read(s->bs, offset, s->cluster_buffer, 1);
   1968                        if (res) {
   1969                            return -1;
   1970                        }
   1971                        res = bdrv_pwrite(s->qcow, offset * BDRV_SECTOR_SIZE,
   1972                                          s->cluster_buffer, BDRV_SECTOR_SIZE);
   1973                        if (res < 0) {
   1974                            return -2;
   1975                        }
   1976                    }
   1977                }
   1978            }
   1979        }
   1980
   1981        ret++;
   1982        if (s->used_clusters[cluster_num] & USED_ANY)
   1983            return 0;
   1984        s->used_clusters[cluster_num] = USED_FILE;
   1985
   1986        cluster_num = modified_fat_get(s, cluster_num);
   1987
   1988        if (fat_eof(s, cluster_num))
   1989            return ret;
   1990        else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
   1991            return -1;
   1992
   1993        offset += s->cluster_size;
   1994    }
   1995}
   1996
   1997/*
   1998 * This function looks at the modified data (qcow).
   1999 * It returns 0 upon inconsistency or error, and the number of clusters
   2000 * used by the directory, its subdirectories and their files.
   2001 */
   2002static int check_directory_consistency(BDRVVVFATState *s,
   2003        int cluster_num, const char* path)
   2004{
   2005    int ret = 0;
   2006    unsigned char* cluster = g_malloc(s->cluster_size);
   2007    direntry_t* direntries = (direntry_t*)cluster;
   2008    mapping_t* mapping = find_mapping_for_cluster(s, cluster_num);
   2009
   2010    long_file_name lfn;
   2011    int path_len = strlen(path);
   2012    char path2[PATH_MAX + 1];
   2013
   2014    assert(path_len < PATH_MAX); /* len was tested before! */
   2015    pstrcpy(path2, sizeof(path2), path);
   2016    path2[path_len] = '/';
   2017    path2[path_len + 1] = '\0';
   2018
   2019    if (mapping) {
   2020        const char* basename = get_basename(mapping->path);
   2021        const char* basename2 = get_basename(path);
   2022
   2023        assert(mapping->mode & MODE_DIRECTORY);
   2024
   2025        assert(mapping->mode & MODE_DELETED);
   2026        mapping->mode &= ~MODE_DELETED;
   2027
   2028        if (strcmp(basename, basename2))
   2029            schedule_rename(s, cluster_num, g_strdup(path));
   2030    } else
   2031        /* new directory */
   2032        schedule_mkdir(s, cluster_num, g_strdup(path));
   2033
   2034    lfn_init(&lfn);
   2035    do {
   2036        int i;
   2037        int subret = 0;
   2038
   2039        ret++;
   2040
   2041        if (s->used_clusters[cluster_num] & USED_ANY) {
   2042            fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
   2043            goto fail;
   2044        }
   2045        s->used_clusters[cluster_num] = USED_DIRECTORY;
   2046
   2047DLOG(fprintf(stderr, "read cluster %d (sector %d)\n", (int)cluster_num, (int)cluster2sector(s, cluster_num)));
   2048        subret = vvfat_read(s->bs, cluster2sector(s, cluster_num), cluster,
   2049                s->sectors_per_cluster);
   2050        if (subret) {
   2051            fprintf(stderr, "Error fetching direntries\n");
   2052        fail:
   2053            g_free(cluster);
   2054            return 0;
   2055        }
   2056
   2057        for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
   2058            int cluster_count = 0;
   2059
   2060DLOG(fprintf(stderr, "check direntry %d:\n", i); print_direntry(direntries + i));
   2061            if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
   2062                    is_free(direntries + i))
   2063                continue;
   2064
   2065            subret = parse_long_name(&lfn, direntries + i);
   2066            if (subret < 0) {
   2067                fprintf(stderr, "Error in long name\n");
   2068                goto fail;
   2069            }
   2070            if (subret == 0 || is_free(direntries + i))
   2071                continue;
   2072
   2073            if (fat_chksum(direntries+i) != lfn.checksum) {
   2074                subret = parse_short_name(s, &lfn, direntries + i);
   2075                if (subret < 0) {
   2076                    fprintf(stderr, "Error in short name (%d)\n", subret);
   2077                    goto fail;
   2078                }
   2079                if (subret > 0 || !strcmp((char*)lfn.name, ".")
   2080                        || !strcmp((char*)lfn.name, ".."))
   2081                    continue;
   2082            }
   2083            lfn.checksum = 0x100; /* cannot use long name twice */
   2084
   2085            if (!valid_filename(lfn.name)) {
   2086                fprintf(stderr, "Invalid file name\n");
   2087                goto fail;
   2088            }
   2089            if (path_len + 1 + lfn.len >= PATH_MAX) {
   2090                fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
   2091                goto fail;
   2092            }
   2093            pstrcpy(path2 + path_len + 1, sizeof(path2) - path_len - 1,
   2094                    (char*)lfn.name);
   2095
   2096            if (is_directory(direntries + i)) {
   2097                if (begin_of_direntry(direntries + i) == 0) {
   2098                    DLOG(fprintf(stderr, "invalid begin for directory: %s\n", path2); print_direntry(direntries + i));
   2099                    goto fail;
   2100                }
   2101                cluster_count = check_directory_consistency(s,
   2102                        begin_of_direntry(direntries + i), path2);
   2103                if (cluster_count == 0) {
   2104                    DLOG(fprintf(stderr, "problem in directory %s:\n", path2); print_direntry(direntries + i));
   2105                    goto fail;
   2106                }
   2107            } else if (is_file(direntries + i)) {
   2108                /* check file size with FAT */
   2109                cluster_count = get_cluster_count_for_direntry(s, direntries + i, path2);
   2110                if (cluster_count !=
   2111            DIV_ROUND_UP(le32_to_cpu(direntries[i].size), s->cluster_size)) {
   2112                    DLOG(fprintf(stderr, "Cluster count mismatch\n"));
   2113                    goto fail;
   2114                }
   2115            } else
   2116                abort(); /* cluster_count = 0; */
   2117
   2118            ret += cluster_count;
   2119        }
   2120
   2121        cluster_num = modified_fat_get(s, cluster_num);
   2122    } while(!fat_eof(s, cluster_num));
   2123
   2124    g_free(cluster);
   2125    return ret;
   2126}
   2127
   2128/* returns 1 on success */
   2129static int is_consistent(BDRVVVFATState* s)
   2130{
   2131    int i, check;
   2132    int used_clusters_count = 0;
   2133
   2134DLOG(checkpoint());
   2135    /*
   2136     * - get modified FAT
   2137     * - compare the two FATs (TODO)
   2138     * - get buffer for marking used clusters
   2139     * - recurse direntries from root (using bs->bdrv_pread to make
   2140     *    sure to get the new data)
   2141     *   - check that the FAT agrees with the size
   2142     *   - count the number of clusters occupied by this directory and
   2143     *     its files
   2144     * - check that the cumulative used cluster count agrees with the
   2145     *   FAT
   2146     * - if all is fine, return number of used clusters
   2147     */
   2148    if (s->fat2 == NULL) {
   2149        int size = 0x200 * s->sectors_per_fat;
   2150        s->fat2 = g_malloc(size);
   2151        memcpy(s->fat2, s->fat.pointer, size);
   2152    }
   2153    check = vvfat_read(s->bs,
   2154            s->offset_to_fat, s->fat2, s->sectors_per_fat);
   2155    if (check) {
   2156        fprintf(stderr, "Could not copy fat\n");
   2157        return 0;
   2158    }
   2159    assert (s->used_clusters);
   2160    for (i = 0; i < sector2cluster(s, s->sector_count); i++)
   2161        s->used_clusters[i] &= ~USED_ANY;
   2162
   2163    clear_commits(s);
   2164
   2165    /* mark every mapped file/directory as deleted.
   2166     * (check_directory_consistency() will unmark those still present). */
   2167    if (s->qcow)
   2168        for (i = 0; i < s->mapping.next; i++) {
   2169            mapping_t* mapping = array_get(&(s->mapping), i);
   2170            if (mapping->first_mapping_index < 0)
   2171                mapping->mode |= MODE_DELETED;
   2172        }
   2173
   2174    used_clusters_count = check_directory_consistency(s, 0, s->path);
   2175    if (used_clusters_count <= 0) {
   2176        DLOG(fprintf(stderr, "problem in directory\n"));
   2177        return 0;
   2178    }
   2179
   2180    check = s->last_cluster_of_root_directory;
   2181    for (i = check; i < sector2cluster(s, s->sector_count); i++) {
   2182        if (modified_fat_get(s, i)) {
   2183            if(!s->used_clusters[i]) {
   2184                DLOG(fprintf(stderr, "FAT was modified (%d), but cluster is not used?\n", i));
   2185                return 0;
   2186            }
   2187            check++;
   2188        }
   2189
   2190        if (s->used_clusters[i] == USED_ALLOCATED) {
   2191            /* allocated, but not used... */
   2192            DLOG(fprintf(stderr, "unused, modified cluster: %d\n", i));
   2193            return 0;
   2194        }
   2195    }
   2196
   2197    if (check != used_clusters_count)
   2198        return 0;
   2199
   2200    return used_clusters_count;
   2201}
   2202
   2203static inline void adjust_mapping_indices(BDRVVVFATState* s,
   2204        int offset, int adjust)
   2205{
   2206    int i;
   2207
   2208    for (i = 0; i < s->mapping.next; i++) {
   2209        mapping_t* mapping = array_get(&(s->mapping), i);
   2210
   2211#define ADJUST_MAPPING_INDEX(name) \
   2212        if (mapping->name >= offset) \
   2213            mapping->name += adjust
   2214
   2215        ADJUST_MAPPING_INDEX(first_mapping_index);
   2216        if (mapping->mode & MODE_DIRECTORY)
   2217            ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
   2218    }
   2219}
   2220
   2221/* insert or update mapping */
   2222static mapping_t* insert_mapping(BDRVVVFATState* s,
   2223        uint32_t begin, uint32_t end)
   2224{
   2225    /*
   2226     * - find mapping where mapping->begin >= begin,
   2227     * - if mapping->begin > begin: insert
   2228     *   - adjust all references to mappings!
   2229     * - else: adjust
   2230     * - replace name
   2231     */
   2232    int index = find_mapping_for_cluster_aux(s, begin, 0, s->mapping.next);
   2233    mapping_t* mapping = NULL;
   2234    mapping_t* first_mapping = array_get(&(s->mapping), 0);
   2235
   2236    if (index < s->mapping.next && (mapping = array_get(&(s->mapping), index))
   2237            && mapping->begin < begin) {
   2238        mapping->end = begin;
   2239        index++;
   2240        mapping = array_get(&(s->mapping), index);
   2241    }
   2242    if (index >= s->mapping.next || mapping->begin > begin) {
   2243        mapping = array_insert(&(s->mapping), index, 1);
   2244        mapping->path = NULL;
   2245        adjust_mapping_indices(s, index, +1);
   2246    }
   2247
   2248    mapping->begin = begin;
   2249    mapping->end = end;
   2250
   2251DLOG(mapping_t* next_mapping;
   2252assert(index + 1 >= s->mapping.next ||
   2253((next_mapping = array_get(&(s->mapping), index + 1)) &&
   2254 next_mapping->begin >= end)));
   2255
   2256    if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
   2257        s->current_mapping = array_get(&(s->mapping),
   2258                s->current_mapping - first_mapping);
   2259
   2260    return mapping;
   2261}
   2262
   2263static int remove_mapping(BDRVVVFATState* s, int mapping_index)
   2264{
   2265    mapping_t* mapping = array_get(&(s->mapping), mapping_index);
   2266    mapping_t* first_mapping = array_get(&(s->mapping), 0);
   2267
   2268    /* free mapping */
   2269    if (mapping->first_mapping_index < 0) {
   2270        g_free(mapping->path);
   2271    }
   2272
   2273    /* remove from s->mapping */
   2274    array_remove(&(s->mapping), mapping_index);
   2275
   2276    /* adjust all references to mappings */
   2277    adjust_mapping_indices(s, mapping_index, -1);
   2278
   2279    if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
   2280        s->current_mapping = array_get(&(s->mapping),
   2281                s->current_mapping - first_mapping);
   2282
   2283    return 0;
   2284}
   2285
   2286static void adjust_dirindices(BDRVVVFATState* s, int offset, int adjust)
   2287{
   2288    int i;
   2289    for (i = 0; i < s->mapping.next; i++) {
   2290        mapping_t* mapping = array_get(&(s->mapping), i);
   2291        if (mapping->dir_index >= offset)
   2292            mapping->dir_index += adjust;
   2293        if ((mapping->mode & MODE_DIRECTORY) &&
   2294                mapping->info.dir.first_dir_index >= offset)
   2295            mapping->info.dir.first_dir_index += adjust;
   2296    }
   2297}
   2298
   2299static direntry_t* insert_direntries(BDRVVVFATState* s,
   2300        int dir_index, int count)
   2301{
   2302    /*
   2303     * make room in s->directory,
   2304     * adjust_dirindices
   2305     */
   2306    direntry_t* result = array_insert(&(s->directory), dir_index, count);
   2307    if (result == NULL)
   2308        return NULL;
   2309    adjust_dirindices(s, dir_index, count);
   2310    return result;
   2311}
   2312
   2313static int remove_direntries(BDRVVVFATState* s, int dir_index, int count)
   2314{
   2315    int ret = array_remove_slice(&(s->directory), dir_index, count);
   2316    if (ret)
   2317        return ret;
   2318    adjust_dirindices(s, dir_index, -count);
   2319    return 0;
   2320}
   2321
   2322/*
   2323 * Adapt the mappings of the cluster chain starting at first cluster
   2324 * (i.e. if a file starts at first_cluster, the chain is followed according
   2325 * to the modified fat, and the corresponding entries in s->mapping are
   2326 * adjusted)
   2327 */
   2328static int commit_mappings(BDRVVVFATState* s,
   2329        uint32_t first_cluster, int dir_index)
   2330{
   2331    mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
   2332    direntry_t* direntry = array_get(&(s->directory), dir_index);
   2333    uint32_t cluster = first_cluster;
   2334
   2335    vvfat_close_current_file(s);
   2336
   2337    assert(mapping);
   2338    assert(mapping->begin == first_cluster);
   2339    mapping->first_mapping_index = -1;
   2340    mapping->dir_index = dir_index;
   2341    mapping->mode = (dir_index <= 0 || is_directory(direntry)) ?
   2342        MODE_DIRECTORY : MODE_NORMAL;
   2343
   2344    while (!fat_eof(s, cluster)) {
   2345        uint32_t c, c1;
   2346
   2347        for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
   2348                c = c1, c1 = modified_fat_get(s, c1));
   2349
   2350        c++;
   2351        if (c > mapping->end) {
   2352            int index = array_index(&(s->mapping), mapping);
   2353            int i, max_i = s->mapping.next - index;
   2354            for (i = 1; i < max_i && mapping[i].begin < c; i++);
   2355            while (--i > 0)
   2356                remove_mapping(s, index + 1);
   2357        }
   2358        assert(mapping == array_get(&(s->mapping), s->mapping.next - 1)
   2359                || mapping[1].begin >= c);
   2360        mapping->end = c;
   2361
   2362        if (!fat_eof(s, c1)) {
   2363            int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next);
   2364            mapping_t* next_mapping = i >= s->mapping.next ? NULL :
   2365                array_get(&(s->mapping), i);
   2366
   2367            if (next_mapping == NULL || next_mapping->begin > c1) {
   2368                int i1 = array_index(&(s->mapping), mapping);
   2369
   2370                next_mapping = insert_mapping(s, c1, c1+1);
   2371
   2372                if (c1 < c)
   2373                    i1++;
   2374                mapping = array_get(&(s->mapping), i1);
   2375            }
   2376
   2377            next_mapping->dir_index = mapping->dir_index;
   2378            next_mapping->first_mapping_index =
   2379                mapping->first_mapping_index < 0 ?
   2380                array_index(&(s->mapping), mapping) :
   2381                mapping->first_mapping_index;
   2382            next_mapping->path = mapping->path;
   2383            next_mapping->mode = mapping->mode;
   2384            next_mapping->read_only = mapping->read_only;
   2385            if (mapping->mode & MODE_DIRECTORY) {
   2386                next_mapping->info.dir.parent_mapping_index =
   2387                        mapping->info.dir.parent_mapping_index;
   2388                next_mapping->info.dir.first_dir_index =
   2389                        mapping->info.dir.first_dir_index +
   2390                        0x10 * s->sectors_per_cluster *
   2391                        (mapping->end - mapping->begin);
   2392            } else
   2393                next_mapping->info.file.offset = mapping->info.file.offset +
   2394                        mapping->end - mapping->begin;
   2395
   2396            mapping = next_mapping;
   2397        }
   2398
   2399        cluster = c1;
   2400    }
   2401
   2402    return 0;
   2403}
   2404
   2405static int commit_direntries(BDRVVVFATState* s,
   2406        int dir_index, int parent_mapping_index)
   2407{
   2408    direntry_t* direntry = array_get(&(s->directory), dir_index);
   2409    uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
   2410    mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
   2411    int factor = 0x10 * s->sectors_per_cluster;
   2412    int old_cluster_count, new_cluster_count;
   2413    int current_dir_index;
   2414    int first_dir_index;
   2415    int ret, i;
   2416    uint32_t c;
   2417
   2418    assert(direntry);
   2419    assert(mapping);
   2420    assert(mapping->begin == first_cluster);
   2421    assert(mapping->info.dir.first_dir_index < s->directory.next);
   2422    assert(mapping->mode & MODE_DIRECTORY);
   2423    assert(dir_index == 0 || is_directory(direntry));
   2424
   2425    DLOG(fprintf(stderr, "commit_direntries for %s, parent_mapping_index %d\n",
   2426                 mapping->path, parent_mapping_index));
   2427
   2428    current_dir_index = mapping->info.dir.first_dir_index;
   2429    first_dir_index = current_dir_index;
   2430    mapping->info.dir.parent_mapping_index = parent_mapping_index;
   2431
   2432    if (first_cluster == 0) {
   2433        old_cluster_count = new_cluster_count =
   2434            s->last_cluster_of_root_directory;
   2435    } else {
   2436        for (old_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
   2437                c = fat_get(s, c))
   2438            old_cluster_count++;
   2439
   2440        for (new_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
   2441                c = modified_fat_get(s, c))
   2442            new_cluster_count++;
   2443    }
   2444
   2445    if (new_cluster_count > old_cluster_count) {
   2446        if (insert_direntries(s,
   2447                current_dir_index + factor * old_cluster_count,
   2448                factor * (new_cluster_count - old_cluster_count)) == NULL)
   2449            return -1;
   2450    } else if (new_cluster_count < old_cluster_count)
   2451        remove_direntries(s,
   2452                current_dir_index + factor * new_cluster_count,
   2453                factor * (old_cluster_count - new_cluster_count));
   2454
   2455    for (c = first_cluster; !fat_eof(s, c); c = modified_fat_get(s, c)) {
   2456        direntry_t *first_direntry;
   2457        void* direntry = array_get(&(s->directory), current_dir_index);
   2458        int ret = vvfat_read(s->bs, cluster2sector(s, c), direntry,
   2459                s->sectors_per_cluster);
   2460        if (ret)
   2461            return ret;
   2462
   2463        /* The first directory entry on the filesystem is the volume name */
   2464        first_direntry = (direntry_t*) s->directory.pointer;
   2465        assert(!memcmp(first_direntry->name, s->volume_label, 11));
   2466
   2467        current_dir_index += factor;
   2468    }
   2469
   2470    ret = commit_mappings(s, first_cluster, dir_index);
   2471    if (ret)
   2472        return ret;
   2473
   2474    /* recurse */
   2475    for (i = 0; i < factor * new_cluster_count; i++) {
   2476        direntry = array_get(&(s->directory), first_dir_index + i);
   2477        if (is_directory(direntry) && !is_dot(direntry)) {
   2478            mapping = find_mapping_for_cluster(s, first_cluster);
   2479            if (mapping == NULL) {
   2480                return -1;
   2481            }
   2482            assert(mapping->mode & MODE_DIRECTORY);
   2483            ret = commit_direntries(s, first_dir_index + i,
   2484                array_index(&(s->mapping), mapping));
   2485            if (ret)
   2486                return ret;
   2487        }
   2488    }
   2489
   2490    return 0;
   2491}
   2492
   2493/* commit one file (adjust contents, adjust mapping),
   2494   return first_mapping_index */
   2495static int commit_one_file(BDRVVVFATState* s,
   2496        int dir_index, uint32_t offset)
   2497{
   2498    direntry_t* direntry = array_get(&(s->directory), dir_index);
   2499    uint32_t c = begin_of_direntry(direntry);
   2500    uint32_t first_cluster = c;
   2501    mapping_t* mapping = find_mapping_for_cluster(s, c);
   2502    uint32_t size = filesize_of_direntry(direntry);
   2503    char *cluster;
   2504    uint32_t i;
   2505    int fd = 0;
   2506
   2507    assert(offset < size);
   2508    assert((offset % s->cluster_size) == 0);
   2509
   2510    if (mapping == NULL) {
   2511        return -1;
   2512    }
   2513
   2514    for (i = s->cluster_size; i < offset; i += s->cluster_size)
   2515        c = modified_fat_get(s, c);
   2516
   2517    fd = qemu_open_old(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666);
   2518    if (fd < 0) {
   2519        fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path,
   2520                strerror(errno), errno);
   2521        return fd;
   2522    }
   2523    if (offset > 0) {
   2524        if (lseek(fd, offset, SEEK_SET) != offset) {
   2525            qemu_close(fd);
   2526            return -3;
   2527        }
   2528    }
   2529
   2530    cluster = g_malloc(s->cluster_size);
   2531
   2532    while (offset < size) {
   2533        uint32_t c1;
   2534        int rest_size = (size - offset > s->cluster_size ?
   2535                s->cluster_size : size - offset);
   2536        int ret;
   2537
   2538        c1 = modified_fat_get(s, c);
   2539
   2540        assert((size - offset == 0 && fat_eof(s, c)) ||
   2541                (size > offset && c >=2 && !fat_eof(s, c)));
   2542
   2543        ret = vvfat_read(s->bs, cluster2sector(s, c),
   2544            (uint8_t*)cluster, DIV_ROUND_UP(rest_size, 0x200));
   2545
   2546        if (ret < 0) {
   2547            qemu_close(fd);
   2548            g_free(cluster);
   2549            return ret;
   2550        }
   2551
   2552        if (write(fd, cluster, rest_size) < 0) {
   2553            qemu_close(fd);
   2554            g_free(cluster);
   2555            return -2;
   2556        }
   2557
   2558        offset += rest_size;
   2559        c = c1;
   2560    }
   2561
   2562    if (ftruncate(fd, size)) {
   2563        perror("ftruncate()");
   2564        qemu_close(fd);
   2565        g_free(cluster);
   2566        return -4;
   2567    }
   2568    qemu_close(fd);
   2569    g_free(cluster);
   2570
   2571    return commit_mappings(s, first_cluster, dir_index);
   2572}
   2573
   2574#ifdef DEBUG
   2575/* test, if all mappings point to valid direntries */
   2576static void check1(BDRVVVFATState* s)
   2577{
   2578    int i;
   2579    for (i = 0; i < s->mapping.next; i++) {
   2580        mapping_t* mapping = array_get(&(s->mapping), i);
   2581        if (mapping->mode & MODE_DELETED) {
   2582            fprintf(stderr, "deleted\n");
   2583            continue;
   2584        }
   2585        assert(mapping->dir_index < s->directory.next);
   2586        direntry_t* direntry = array_get(&(s->directory), mapping->dir_index);
   2587        assert(mapping->begin == begin_of_direntry(direntry) || mapping->first_mapping_index >= 0);
   2588        if (mapping->mode & MODE_DIRECTORY) {
   2589            assert(mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster * (mapping->end - mapping->begin) <= s->directory.next);
   2590            assert((mapping->info.dir.first_dir_index % (0x10 * s->sectors_per_cluster)) == 0);
   2591        }
   2592    }
   2593}
   2594
   2595/* test, if all direntries have mappings */
   2596static void check2(BDRVVVFATState* s)
   2597{
   2598    int i;
   2599    int first_mapping = -1;
   2600
   2601    for (i = 0; i < s->directory.next; i++) {
   2602        direntry_t* direntry = array_get(&(s->directory), i);
   2603
   2604        if (is_short_name(direntry) && begin_of_direntry(direntry)) {
   2605            mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
   2606            assert(mapping);
   2607            assert(mapping->dir_index == i || is_dot(direntry));
   2608            assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry));
   2609        }
   2610
   2611        if ((i % (0x10 * s->sectors_per_cluster)) == 0) {
   2612            /* cluster start */
   2613            int j, count = 0;
   2614
   2615            for (j = 0; j < s->mapping.next; j++) {
   2616                mapping_t* mapping = array_get(&(s->mapping), j);
   2617                if (mapping->mode & MODE_DELETED)
   2618                    continue;
   2619                if (mapping->mode & MODE_DIRECTORY) {
   2620                    if (mapping->info.dir.first_dir_index <= i && mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster > i) {
   2621                        assert(++count == 1);
   2622                        if (mapping->first_mapping_index == -1)
   2623                            first_mapping = array_index(&(s->mapping), mapping);
   2624                        else
   2625                            assert(first_mapping == mapping->first_mapping_index);
   2626                        if (mapping->info.dir.parent_mapping_index < 0)
   2627                            assert(j == 0);
   2628                        else {
   2629                            mapping_t* parent = array_get(&(s->mapping), mapping->info.dir.parent_mapping_index);
   2630                            assert(parent->mode & MODE_DIRECTORY);
   2631                            assert(parent->info.dir.first_dir_index < mapping->info.dir.first_dir_index);
   2632                        }
   2633                    }
   2634                }
   2635            }
   2636            if (count == 0)
   2637                first_mapping = -1;
   2638        }
   2639    }
   2640}
   2641#endif
   2642
   2643static int handle_renames_and_mkdirs(BDRVVVFATState* s)
   2644{
   2645    int i;
   2646
   2647#ifdef DEBUG
   2648    fprintf(stderr, "handle_renames\n");
   2649    for (i = 0; i < s->commits.next; i++) {
   2650        commit_t* commit = array_get(&(s->commits), i);
   2651        fprintf(stderr, "%d, %s (%u, %d)\n", i,
   2652                commit->path ? commit->path : "(null)",
   2653                commit->param.rename.cluster, commit->action);
   2654    }
   2655#endif
   2656
   2657    for (i = 0; i < s->commits.next;) {
   2658        commit_t* commit = array_get(&(s->commits), i);
   2659        if (commit->action == ACTION_RENAME) {
   2660            mapping_t* mapping = find_mapping_for_cluster(s,
   2661                    commit->param.rename.cluster);
   2662            char *old_path;
   2663
   2664            if (mapping == NULL) {
   2665                return -1;
   2666            }
   2667            old_path = mapping->path;
   2668            assert(commit->path);
   2669            mapping->path = commit->path;
   2670            if (rename(old_path, mapping->path))
   2671                return -2;
   2672
   2673            if (mapping->mode & MODE_DIRECTORY) {
   2674                int l1 = strlen(mapping->path);
   2675                int l2 = strlen(old_path);
   2676                int diff = l1 - l2;
   2677                direntry_t* direntry = array_get(&(s->directory),
   2678                        mapping->info.dir.first_dir_index);
   2679                uint32_t c = mapping->begin;
   2680                int i = 0;
   2681
   2682                /* recurse */
   2683                while (!fat_eof(s, c)) {
   2684                    do {
   2685                        direntry_t* d = direntry + i;
   2686
   2687                        if (is_file(d) || (is_directory(d) && !is_dot(d))) {
   2688                            int l;
   2689                            char *new_path;
   2690                            mapping_t* m = find_mapping_for_cluster(s,
   2691                                    begin_of_direntry(d));
   2692                            if (m == NULL) {
   2693                                return -1;
   2694                            }
   2695                            l = strlen(m->path);
   2696                            new_path = g_malloc(l + diff + 1);
   2697
   2698                            assert(!strncmp(m->path, mapping->path, l2));
   2699
   2700                            pstrcpy(new_path, l + diff + 1, mapping->path);
   2701                            pstrcpy(new_path + l1, l + diff + 1 - l1,
   2702                                    m->path + l2);
   2703
   2704                            schedule_rename(s, m->begin, new_path);
   2705                        }
   2706                        i++;
   2707                    } while((i % (0x10 * s->sectors_per_cluster)) != 0);
   2708                    c = fat_get(s, c);
   2709                }
   2710            }
   2711
   2712            g_free(old_path);
   2713            array_remove(&(s->commits), i);
   2714            continue;
   2715        } else if (commit->action == ACTION_MKDIR) {
   2716            mapping_t* mapping;
   2717            int j, parent_path_len;
   2718
   2719#ifdef __MINGW32__
   2720            if (mkdir(commit->path))
   2721                return -5;
   2722#else
   2723            if (mkdir(commit->path, 0755))
   2724                return -5;
   2725#endif
   2726
   2727            mapping = insert_mapping(s, commit->param.mkdir.cluster,
   2728                    commit->param.mkdir.cluster + 1);
   2729            if (mapping == NULL)
   2730                return -6;
   2731
   2732            mapping->mode = MODE_DIRECTORY;
   2733            mapping->read_only = 0;
   2734            mapping->path = commit->path;
   2735            j = s->directory.next;
   2736            assert(j);
   2737            insert_direntries(s, s->directory.next,
   2738                    0x10 * s->sectors_per_cluster);
   2739            mapping->info.dir.first_dir_index = j;
   2740
   2741            parent_path_len = strlen(commit->path)
   2742                - strlen(get_basename(commit->path)) - 1;
   2743            for (j = 0; j < s->mapping.next; j++) {
   2744                mapping_t* m = array_get(&(s->mapping), j);
   2745                if (m->first_mapping_index < 0 && m != mapping &&
   2746                        !strncmp(m->path, mapping->path, parent_path_len) &&
   2747                        strlen(m->path) == parent_path_len)
   2748                    break;
   2749            }
   2750            assert(j < s->mapping.next);
   2751            mapping->info.dir.parent_mapping_index = j;
   2752
   2753            array_remove(&(s->commits), i);
   2754            continue;
   2755        }
   2756
   2757        i++;
   2758    }
   2759    return 0;
   2760}
   2761
   2762/*
   2763 * TODO: make sure that the short name is not matching *another* file
   2764 */
   2765static int handle_commits(BDRVVVFATState* s)
   2766{
   2767    int i, fail = 0;
   2768
   2769    vvfat_close_current_file(s);
   2770
   2771    for (i = 0; !fail && i < s->commits.next; i++) {
   2772        commit_t* commit = array_get(&(s->commits), i);
   2773        switch(commit->action) {
   2774        case ACTION_RENAME: case ACTION_MKDIR:
   2775            abort();
   2776            fail = -2;
   2777            break;
   2778        case ACTION_WRITEOUT: {
   2779#ifndef NDEBUG
   2780            /* these variables are only used by assert() below */
   2781            direntry_t* entry = array_get(&(s->directory),
   2782                    commit->param.writeout.dir_index);
   2783            uint32_t begin = begin_of_direntry(entry);
   2784            mapping_t* mapping = find_mapping_for_cluster(s, begin);
   2785#endif
   2786
   2787            assert(mapping);
   2788            assert(mapping->begin == begin);
   2789            assert(commit->path == NULL);
   2790
   2791            if (commit_one_file(s, commit->param.writeout.dir_index,
   2792                        commit->param.writeout.modified_offset))
   2793                fail = -3;
   2794
   2795            break;
   2796        }
   2797        case ACTION_NEW_FILE: {
   2798            int begin = commit->param.new_file.first_cluster;
   2799            mapping_t* mapping = find_mapping_for_cluster(s, begin);
   2800            direntry_t* entry;
   2801            int i;
   2802
   2803            /* find direntry */
   2804            for (i = 0; i < s->directory.next; i++) {
   2805                entry = array_get(&(s->directory), i);
   2806                if (is_file(entry) && begin_of_direntry(entry) == begin)
   2807                    break;
   2808            }
   2809
   2810            if (i >= s->directory.next) {
   2811                fail = -6;
   2812                continue;
   2813            }
   2814
   2815            /* make sure there exists an initial mapping */
   2816            if (mapping && mapping->begin != begin) {
   2817                mapping->end = begin;
   2818                mapping = NULL;
   2819            }
   2820            if (mapping == NULL) {
   2821                mapping = insert_mapping(s, begin, begin+1);
   2822            }
   2823            /* most members will be fixed in commit_mappings() */
   2824            assert(commit->path);
   2825            mapping->path = commit->path;
   2826            mapping->read_only = 0;
   2827            mapping->mode = MODE_NORMAL;
   2828            mapping->info.file.offset = 0;
   2829
   2830            if (commit_one_file(s, i, 0))
   2831                fail = -7;
   2832
   2833            break;
   2834        }
   2835        default:
   2836            abort();
   2837        }
   2838    }
   2839    if (i > 0 && array_remove_slice(&(s->commits), 0, i))
   2840        return -1;
   2841    return fail;
   2842}
   2843
   2844static int handle_deletes(BDRVVVFATState* s)
   2845{
   2846    int i, deferred = 1, deleted = 1;
   2847
   2848    /* delete files corresponding to mappings marked as deleted */
   2849    /* handle DELETEs and unused mappings (modified_fat_get(s, mapping->begin) == 0) */
   2850    while (deferred && deleted) {
   2851        deferred = 0;
   2852        deleted = 0;
   2853
   2854        for (i = 1; i < s->mapping.next; i++) {
   2855            mapping_t* mapping = array_get(&(s->mapping), i);
   2856            if (mapping->mode & MODE_DELETED) {
   2857                direntry_t* entry = array_get(&(s->directory),
   2858                        mapping->dir_index);
   2859
   2860                if (is_free(entry)) {
   2861                    /* remove file/directory */
   2862                    if (mapping->mode & MODE_DIRECTORY) {
   2863                        int j, next_dir_index = s->directory.next,
   2864                        first_dir_index = mapping->info.dir.first_dir_index;
   2865
   2866                        if (rmdir(mapping->path) < 0) {
   2867                            if (errno == ENOTEMPTY) {
   2868                                deferred++;
   2869                                continue;
   2870                            } else
   2871                                return -5;
   2872                        }
   2873
   2874                        for (j = 1; j < s->mapping.next; j++) {
   2875                            mapping_t* m = array_get(&(s->mapping), j);
   2876                            if (m->mode & MODE_DIRECTORY &&
   2877                                    m->info.dir.first_dir_index >
   2878                                    first_dir_index &&
   2879                                    m->info.dir.first_dir_index <
   2880                                    next_dir_index)
   2881                                next_dir_index =
   2882                                    m->info.dir.first_dir_index;
   2883                        }
   2884                        remove_direntries(s, first_dir_index,
   2885                                next_dir_index - first_dir_index);
   2886
   2887                        deleted++;
   2888                    }
   2889                } else {
   2890                    if (unlink(mapping->path))
   2891                        return -4;
   2892                    deleted++;
   2893                }
   2894                DLOG(fprintf(stderr, "DELETE (%d)\n", i); print_mapping(mapping); print_direntry(entry));
   2895                remove_mapping(s, i);
   2896            }
   2897        }
   2898    }
   2899
   2900    return 0;
   2901}
   2902
   2903/*
   2904 * synchronize mapping with new state:
   2905 *
   2906 * - copy FAT (with bdrv_pread)
   2907 * - mark all filenames corresponding to mappings as deleted
   2908 * - recurse direntries from root (using bs->bdrv_pread)
   2909 * - delete files corresponding to mappings marked as deleted
   2910 */
   2911static int do_commit(BDRVVVFATState* s)
   2912{
   2913    int ret = 0;
   2914
   2915    /* the real meat are the commits. Nothing to do? Move along! */
   2916    if (s->commits.next == 0)
   2917        return 0;
   2918
   2919    vvfat_close_current_file(s);
   2920
   2921    ret = handle_renames_and_mkdirs(s);
   2922    if (ret) {
   2923        fprintf(stderr, "Error handling renames (%d)\n", ret);
   2924        abort();
   2925        return ret;
   2926    }
   2927
   2928    /* copy FAT (with bdrv_pread) */
   2929    memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
   2930
   2931    /* recurse direntries from root (using bs->bdrv_pread) */
   2932    ret = commit_direntries(s, 0, -1);
   2933    if (ret) {
   2934        fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
   2935        abort();
   2936        return ret;
   2937    }
   2938
   2939    ret = handle_commits(s);
   2940    if (ret) {
   2941        fprintf(stderr, "Error handling commits (%d)\n", ret);
   2942        abort();
   2943        return ret;
   2944    }
   2945
   2946    ret = handle_deletes(s);
   2947    if (ret) {
   2948        fprintf(stderr, "Error deleting\n");
   2949        abort();
   2950        return ret;
   2951    }
   2952
   2953    bdrv_make_empty(s->qcow, NULL);
   2954
   2955    memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
   2956
   2957DLOG(checkpoint());
   2958    return 0;
   2959}
   2960
   2961static int try_commit(BDRVVVFATState* s)
   2962{
   2963    vvfat_close_current_file(s);
   2964DLOG(checkpoint());
   2965    if(!is_consistent(s))
   2966        return -1;
   2967    return do_commit(s);
   2968}
   2969
   2970static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
   2971                    const uint8_t *buf, int nb_sectors)
   2972{
   2973    BDRVVVFATState *s = bs->opaque;
   2974    int i, ret;
   2975
   2976DLOG(checkpoint());
   2977
   2978    /* Check if we're operating in read-only mode */
   2979    if (s->qcow == NULL) {
   2980        return -EACCES;
   2981    }
   2982
   2983    vvfat_close_current_file(s);
   2984
   2985    /*
   2986     * Some sanity checks:
   2987     * - do not allow writing to the boot sector
   2988     */
   2989
   2990    if (sector_num < s->offset_to_fat)
   2991        return -1;
   2992
   2993    for (i = sector2cluster(s, sector_num);
   2994            i <= sector2cluster(s, sector_num + nb_sectors - 1);) {
   2995        mapping_t* mapping = find_mapping_for_cluster(s, i);
   2996        if (mapping) {
   2997            if (mapping->read_only) {
   2998                fprintf(stderr, "Tried to write to write-protected file %s\n",
   2999                        mapping->path);
   3000                return -1;
   3001            }
   3002
   3003            if (mapping->mode & MODE_DIRECTORY) {
   3004                int begin = cluster2sector(s, i);
   3005                int end = begin + s->sectors_per_cluster, k;
   3006                int dir_index;
   3007                const direntry_t* direntries;
   3008                long_file_name lfn;
   3009
   3010                lfn_init(&lfn);
   3011
   3012                if (begin < sector_num)
   3013                    begin = sector_num;
   3014                if (end > sector_num + nb_sectors)
   3015                    end = sector_num + nb_sectors;
   3016                dir_index  = mapping->dir_index +
   3017                    0x10 * (begin - mapping->begin * s->sectors_per_cluster);
   3018                direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
   3019
   3020                for (k = 0; k < (end - begin) * 0x10; k++) {
   3021                    /* no access to the direntry of a read-only file */
   3022                    if (is_short_name(direntries + k) &&
   3023                            (direntries[k].attributes & 1)) {
   3024                        if (memcmp(direntries + k,
   3025                                    array_get(&(s->directory), dir_index + k),
   3026                                    sizeof(direntry_t))) {
   3027                            warn_report("tried to write to write-protected "
   3028                                        "file");
   3029                            return -1;
   3030                        }
   3031                    }
   3032                }
   3033            }
   3034            i = mapping->end;
   3035        } else
   3036            i++;
   3037    }
   3038
   3039    /*
   3040     * Use qcow backend. Commit later.
   3041     */
   3042DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
   3043    ret = bdrv_pwrite(s->qcow, sector_num * BDRV_SECTOR_SIZE, buf,
   3044                      nb_sectors * BDRV_SECTOR_SIZE);
   3045    if (ret < 0) {
   3046        fprintf(stderr, "Error writing to qcow backend\n");
   3047        return ret;
   3048    }
   3049
   3050    for (i = sector2cluster(s, sector_num);
   3051            i <= sector2cluster(s, sector_num + nb_sectors - 1); i++)
   3052        if (i >= 0)
   3053            s->used_clusters[i] |= USED_ALLOCATED;
   3054
   3055DLOG(checkpoint());
   3056    /* TODO: add timeout */
   3057    try_commit(s);
   3058
   3059DLOG(checkpoint());
   3060    return 0;
   3061}
   3062
   3063static int coroutine_fn
   3064vvfat_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
   3065                 QEMUIOVector *qiov, BdrvRequestFlags flags)
   3066{
   3067    int ret;
   3068    BDRVVVFATState *s = bs->opaque;
   3069    uint64_t sector_num = offset >> BDRV_SECTOR_BITS;
   3070    int nb_sectors = bytes >> BDRV_SECTOR_BITS;
   3071    void *buf;
   3072
   3073    assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
   3074    assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
   3075
   3076    buf = g_try_malloc(bytes);
   3077    if (bytes && buf == NULL) {
   3078        return -ENOMEM;
   3079    }
   3080    qemu_iovec_to_buf(qiov, 0, buf, bytes);
   3081
   3082    qemu_co_mutex_lock(&s->lock);
   3083    ret = vvfat_write(bs, sector_num, buf, nb_sectors);
   3084    qemu_co_mutex_unlock(&s->lock);
   3085
   3086    g_free(buf);
   3087
   3088    return ret;
   3089}
   3090
   3091static int coroutine_fn vvfat_co_block_status(BlockDriverState *bs,
   3092                                              bool want_zero, int64_t offset,
   3093                                              int64_t bytes, int64_t *n,
   3094                                              int64_t *map,
   3095                                              BlockDriverState **file)
   3096{
   3097    *n = bytes;
   3098    return BDRV_BLOCK_DATA;
   3099}
   3100
   3101static void vvfat_qcow_options(BdrvChildRole role, bool parent_is_format,
   3102                               int *child_flags, QDict *child_options,
   3103                               int parent_flags, QDict *parent_options)
   3104{
   3105    qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "off");
   3106    qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
   3107    qdict_set_default_str(child_options, BDRV_OPT_CACHE_NO_FLUSH, "on");
   3108}
   3109
   3110static BdrvChildClass child_vvfat_qcow;
   3111
   3112static int enable_write_target(BlockDriverState *bs, Error **errp)
   3113{
   3114    BDRVVVFATState *s = bs->opaque;
   3115    BlockDriver *bdrv_qcow = NULL;
   3116    QemuOpts *opts = NULL;
   3117    int ret;
   3118    int size = sector2cluster(s, s->sector_count);
   3119    QDict *options;
   3120
   3121    s->used_clusters = calloc(size, 1);
   3122
   3123    array_init(&(s->commits), sizeof(commit_t));
   3124
   3125    s->qcow_filename = g_malloc(PATH_MAX);
   3126    ret = get_tmp_filename(s->qcow_filename, PATH_MAX);
   3127    if (ret < 0) {
   3128        error_setg_errno(errp, -ret, "can't create temporary file");
   3129        goto err;
   3130    }
   3131
   3132    bdrv_qcow = bdrv_find_format("qcow");
   3133    if (!bdrv_qcow) {
   3134        error_setg(errp, "Failed to locate qcow driver");
   3135        ret = -ENOENT;
   3136        goto err;
   3137    }
   3138
   3139    opts = qemu_opts_create(bdrv_qcow->create_opts, NULL, 0, &error_abort);
   3140    qemu_opt_set_number(opts, BLOCK_OPT_SIZE, s->sector_count * 512,
   3141                        &error_abort);
   3142    qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, "fat:", &error_abort);
   3143
   3144    ret = bdrv_create(bdrv_qcow, s->qcow_filename, opts, errp);
   3145    qemu_opts_del(opts);
   3146    if (ret < 0) {
   3147        goto err;
   3148    }
   3149
   3150    options = qdict_new();
   3151    qdict_put_str(options, "write-target.driver", "qcow");
   3152    s->qcow = bdrv_open_child(s->qcow_filename, options, "write-target", bs,
   3153                              &child_vvfat_qcow,
   3154                              BDRV_CHILD_DATA | BDRV_CHILD_METADATA,
   3155                              false, errp);
   3156    qobject_unref(options);
   3157    if (!s->qcow) {
   3158        ret = -EINVAL;
   3159        goto err;
   3160    }
   3161
   3162#ifndef _WIN32
   3163    unlink(s->qcow_filename);
   3164#endif
   3165
   3166    return 0;
   3167
   3168err:
   3169    g_free(s->qcow_filename);
   3170    s->qcow_filename = NULL;
   3171    return ret;
   3172}
   3173
   3174static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c,
   3175                             BdrvChildRole role,
   3176                             BlockReopenQueue *reopen_queue,
   3177                             uint64_t perm, uint64_t shared,
   3178                             uint64_t *nperm, uint64_t *nshared)
   3179{
   3180    assert(role & BDRV_CHILD_DATA);
   3181    /* This is a private node, nobody should try to attach to it */
   3182    *nperm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE;
   3183    *nshared = BLK_PERM_WRITE_UNCHANGED;
   3184}
   3185
   3186static void vvfat_close(BlockDriverState *bs)
   3187{
   3188    BDRVVVFATState *s = bs->opaque;
   3189
   3190    vvfat_close_current_file(s);
   3191    array_free(&(s->fat));
   3192    array_free(&(s->directory));
   3193    array_free(&(s->mapping));
   3194    g_free(s->cluster_buffer);
   3195
   3196    if (s->qcow) {
   3197        migrate_del_blocker(s->migration_blocker);
   3198        error_free(s->migration_blocker);
   3199    }
   3200}
   3201
   3202static const char *const vvfat_strong_runtime_opts[] = {
   3203    "dir",
   3204    "fat-type",
   3205    "floppy",
   3206    "label",
   3207    "rw",
   3208
   3209    NULL
   3210};
   3211
   3212static BlockDriver bdrv_vvfat = {
   3213    .format_name            = "vvfat",
   3214    .protocol_name          = "fat",
   3215    .instance_size          = sizeof(BDRVVVFATState),
   3216
   3217    .bdrv_parse_filename    = vvfat_parse_filename,
   3218    .bdrv_file_open         = vvfat_open,
   3219    .bdrv_refresh_limits    = vvfat_refresh_limits,
   3220    .bdrv_close             = vvfat_close,
   3221    .bdrv_child_perm        = vvfat_child_perm,
   3222
   3223    .bdrv_co_preadv         = vvfat_co_preadv,
   3224    .bdrv_co_pwritev        = vvfat_co_pwritev,
   3225    .bdrv_co_block_status   = vvfat_co_block_status,
   3226
   3227    .strong_runtime_opts    = vvfat_strong_runtime_opts,
   3228};
   3229
   3230static void bdrv_vvfat_init(void)
   3231{
   3232    child_vvfat_qcow = child_of_bds;
   3233    child_vvfat_qcow.inherit_options = vvfat_qcow_options;
   3234    bdrv_register(&bdrv_vvfat);
   3235}
   3236
   3237block_init(bdrv_vvfat_init);
   3238
   3239#ifdef DEBUG
   3240static void checkpoint(void)
   3241{
   3242    assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2);
   3243    check1(vvv);
   3244    check2(vvv);
   3245    assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY));
   3246}
   3247#endif