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