qemu/block/vvfat.c
<<
>>
Prefs
   1/* vim:set shiftwidth=4 ts=8: */
   2/*
   3 * QEMU Block driver for virtual VFAT (shadows a local directory)
   4 *
   5 * Copyright (c) 2004,2005 Johannes E. Schindelin
   6 *
   7 * Permission is hereby granted, free of charge, to any person obtaining a copy
   8 * of this software and associated documentation files (the "Software"), to deal
   9 * in the Software without restriction, including without limitation the rights
  10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11 * copies of the Software, and to permit persons to whom the Software is
  12 * furnished to do so, subject to the following conditions:
  13 *
  14 * The above copyright notice and this permission notice shall be included in
  15 * all copies or substantial portions of the Software.
  16 *
  17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23 * THE SOFTWARE.
  24 */
  25#include <sys/stat.h>
  26#include <dirent.h>
  27#include "qemu-common.h"
  28#include "block_int.h"
  29#include "module.h"
  30#include "migration.h"
  31
  32#ifndef S_IWGRP
  33#define S_IWGRP 0
  34#endif
  35#ifndef S_IWOTH
  36#define S_IWOTH 0
  37#endif
  38
  39/* TODO: add ":bootsector=blabla.img:" */
  40/* LATER TODO: add automatic boot sector generation from
  41    BOOTEASY.ASM and Ranish Partition Manager
  42    Note that DOS assumes the system files to be the first files in the
  43    file system (test if the boot sector still relies on that fact)! */
  44/* MAYBE TODO: write block-visofs.c */
  45/* TODO: call try_commit() only after a timeout */
  46
  47/* #define DEBUG */
  48
  49#ifdef DEBUG
  50
  51#define DLOG(a) a
  52
  53#undef stderr
  54#define stderr STDERR
  55FILE* stderr = NULL;
  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];
 268    uint8_t extension[3];
 269    uint8_t attributes;
 270    uint8_t reserved[2];
 271    uint16_t ctime;
 272    uint16_t cdate;
 273    uint16_t adate;
 274    uint16_t begin_hi;
 275    uint16_t mtime;
 276    uint16_t mdate;
 277    uint16_t begin;
 278    uint32_t size;
 279} QEMU_PACKED direntry_t;
 280
 281/* this structure are used to transparently access the files */
 282
 283typedef struct mapping_t {
 284    /* begin is the first cluster, end is the last+1 */
 285    uint32_t begin,end;
 286    /* as s->directory is growable, no pointer may be used here */
 287    unsigned int dir_index;
 288    /* the clusters of a file may be in any order; this points to the first */
 289    int first_mapping_index;
 290    union {
 291        /* offset is
 292         * - the offset in the file (in clusters) for a file, or
 293         * - the next cluster of the directory for a directory, and
 294         * - the address of the buffer for a faked entry
 295         */
 296        struct {
 297            uint32_t offset;
 298        } file;
 299        struct {
 300            int parent_mapping_index;
 301            int first_dir_index;
 302        } dir;
 303    } info;
 304    /* path contains the full path, i.e. it always starts with s->path */
 305    char* path;
 306
 307    enum { MODE_UNDEFINED = 0, MODE_NORMAL = 1, MODE_MODIFIED = 2,
 308        MODE_DIRECTORY = 4, MODE_FAKED = 8,
 309        MODE_DELETED = 16, MODE_RENAMED = 32 } mode;
 310    int read_only;
 311} mapping_t;
 312
 313#ifdef DEBUG
 314static void print_direntry(const struct direntry_t*);
 315static void print_mapping(const struct mapping_t* mapping);
 316#endif
 317
 318/* here begins the real VVFAT driver */
 319
 320typedef struct BDRVVVFATState {
 321    CoMutex lock;
 322    BlockDriverState* bs; /* pointer to parent */
 323    unsigned int first_sectors_number; /* 1 for a single partition, 0x40 for a disk with partition table */
 324    unsigned char first_sectors[0x40*0x200];
 325
 326    int fat_type; /* 16 or 32 */
 327    array_t fat,directory,mapping;
 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(BlockDriverState* bs, mbr_chs_t * chs, int spos){
 363    int head,sector;
 364    sector   = spos % (bs->secs);  spos/= bs->secs;
 365    head     = spos % (bs->heads); spos/= bs->heads;
 366    if(spos >= bs->cyls){
 367        /* Overflow,
 368        it happens if 32bit sector positions are used, while CHS is only 24bit.
 369        Windows/Dos is said to take 1023/255/63 as nonrepresentable CHS */
 370        chs->head     = 0xFF;
 371        chs->sector   = 0xFF;
 372        chs->cylinder = 0xFF;
 373        return 1;
 374    }
 375    chs->head     = (uint8_t)head;
 376    chs->sector   = (uint8_t)( (sector+1) | ((spos>>8)<<6) );
 377    chs->cylinder = (uint8_t)spos;
 378    return 0;
 379}
 380
 381static void init_mbr(BDRVVVFATState* s)
 382{
 383    /* TODO: if the files mbr.img and bootsect.img exist, use them */
 384    mbr_t* real_mbr=(mbr_t*)s->first_sectors;
 385    partition_t* partition = &(real_mbr->partition[0]);
 386    int lba;
 387
 388    memset(s->first_sectors,0,512);
 389
 390    /* Win NT Disk Signature */
 391    real_mbr->nt_id= cpu_to_le32(0xbe1afdfa);
 392
 393    partition->attributes=0x80; /* bootable */
 394
 395    /* LBA is used when partition is outside the CHS geometry */
 396    lba = sector2CHS(s->bs, &partition->start_CHS, s->first_sectors_number-1);
 397    lba|= sector2CHS(s->bs, &partition->end_CHS,   s->sector_count);
 398
 399    /*LBA partitions are identified only by start/length_sector_long not by CHS*/
 400    partition->start_sector_long =cpu_to_le32(s->first_sectors_number-1);
 401    partition->length_sector_long=cpu_to_le32(s->sector_count - s->first_sectors_number+1);
 402
 403    /* FAT12/FAT16/FAT32 */
 404    /* DOS uses different types when partition is LBA,
 405       probably to prevent older versions from using CHS on them */
 406    partition->fs_type= s->fat_type==12 ? 0x1:
 407                        s->fat_type==16 ? (lba?0xe:0x06):
 408                         /*fat_tyoe==32*/ (lba?0xc:0x0b);
 409
 410    real_mbr->magic[0]=0x55; real_mbr->magic[1]=0xaa;
 411}
 412
 413/* direntry functions */
 414
 415/* dest is assumed to hold 258 bytes, and pads with 0xffff up to next multiple of 26 */
 416static inline int short2long_name(char* dest,const char* src)
 417{
 418    int i;
 419    int len;
 420    for(i=0;i<129 && src[i];i++) {
 421        dest[2*i]=src[i];
 422        dest[2*i+1]=0;
 423    }
 424    len=2*i;
 425    dest[2*i]=dest[2*i+1]=0;
 426    for(i=2*i+2;(i%26);i++)
 427        dest[i]=0xff;
 428    return len;
 429}
 430
 431static inline direntry_t* create_long_filename(BDRVVVFATState* s,const char* filename)
 432{
 433    char buffer[258];
 434    int length=short2long_name(buffer,filename),
 435        number_of_entries=(length+25)/26,i;
 436    direntry_t* entry;
 437
 438    for(i=0;i<number_of_entries;i++) {
 439        entry=array_get_next(&(s->directory));
 440        entry->attributes=0xf;
 441        entry->reserved[0]=0;
 442        entry->begin=0;
 443        entry->name[0]=(number_of_entries-i)|(i==0?0x40:0);
 444    }
 445    for(i=0;i<26*number_of_entries;i++) {
 446        int offset=(i%26);
 447        if(offset<10) offset=1+offset;
 448        else if(offset<22) offset=14+offset-10;
 449        else offset=28+offset-22;
 450        entry=array_get(&(s->directory),s->directory.next-1-(i/26));
 451        entry->name[offset]=buffer[i];
 452    }
 453    return array_get(&(s->directory),s->directory.next-number_of_entries);
 454}
 455
 456static char is_free(const direntry_t* direntry)
 457{
 458    return direntry->name[0]==0xe5 || direntry->name[0]==0x00;
 459}
 460
 461static char is_volume_label(const direntry_t* direntry)
 462{
 463    return direntry->attributes == 0x28;
 464}
 465
 466static char is_long_name(const direntry_t* direntry)
 467{
 468    return direntry->attributes == 0xf;
 469}
 470
 471static char is_short_name(const direntry_t* direntry)
 472{
 473    return !is_volume_label(direntry) && !is_long_name(direntry)
 474        && !is_free(direntry);
 475}
 476
 477static char is_directory(const direntry_t* direntry)
 478{
 479    return direntry->attributes & 0x10 && direntry->name[0] != 0xe5;
 480}
 481
 482static inline char is_dot(const direntry_t* direntry)
 483{
 484    return is_short_name(direntry) && direntry->name[0] == '.';
 485}
 486
 487static char is_file(const direntry_t* direntry)
 488{
 489    return is_short_name(direntry) && !is_directory(direntry);
 490}
 491
 492static inline uint32_t begin_of_direntry(const direntry_t* direntry)
 493{
 494    return le16_to_cpu(direntry->begin)|(le16_to_cpu(direntry->begin_hi)<<16);
 495}
 496
 497static inline uint32_t filesize_of_direntry(const direntry_t* direntry)
 498{
 499    return le32_to_cpu(direntry->size);
 500}
 501
 502static void set_begin_of_direntry(direntry_t* direntry, uint32_t begin)
 503{
 504    direntry->begin = cpu_to_le16(begin & 0xffff);
 505    direntry->begin_hi = cpu_to_le16((begin >> 16) & 0xffff);
 506}
 507
 508/* fat functions */
 509
 510static inline uint8_t fat_chksum(const direntry_t* entry)
 511{
 512    uint8_t chksum=0;
 513    int i;
 514
 515    for(i=0;i<11;i++) {
 516        unsigned char c;
 517
 518        c = (i < 8) ? entry->name[i] : entry->extension[i-8];
 519        chksum=(((chksum&0xfe)>>1)|((chksum&0x01)?0x80:0)) + c;
 520    }
 521
 522    return chksum;
 523}
 524
 525/* if return_time==0, this returns the fat_date, else the fat_time */
 526static uint16_t fat_datetime(time_t time,int return_time) {
 527    struct tm* t;
 528#ifdef _WIN32
 529    t=localtime(&time); /* this is not thread safe */
 530#else
 531    struct tm t1;
 532    t = &t1;
 533    localtime_r(&time,t);
 534#endif
 535    if(return_time)
 536        return cpu_to_le16((t->tm_sec/2)|(t->tm_min<<5)|(t->tm_hour<<11));
 537    return cpu_to_le16((t->tm_mday)|((t->tm_mon+1)<<5)|((t->tm_year-80)<<9));
 538}
 539
 540static inline void fat_set(BDRVVVFATState* s,unsigned int cluster,uint32_t value)
 541{
 542    if(s->fat_type==32) {
 543        uint32_t* entry=array_get(&(s->fat),cluster);
 544        *entry=cpu_to_le32(value);
 545    } else if(s->fat_type==16) {
 546        uint16_t* entry=array_get(&(s->fat),cluster);
 547        *entry=cpu_to_le16(value&0xffff);
 548    } else {
 549        int offset = (cluster*3/2);
 550        unsigned char* p = array_get(&(s->fat), offset);
 551        switch (cluster&1) {
 552        case 0:
 553                p[0] = value&0xff;
 554                p[1] = (p[1]&0xf0) | ((value>>8)&0xf);
 555                break;
 556        case 1:
 557                p[0] = (p[0]&0xf) | ((value&0xf)<<4);
 558                p[1] = (value>>4);
 559                break;
 560        }
 561    }
 562}
 563
 564static inline uint32_t fat_get(BDRVVVFATState* s,unsigned int cluster)
 565{
 566    if(s->fat_type==32) {
 567        uint32_t* entry=array_get(&(s->fat),cluster);
 568        return le32_to_cpu(*entry);
 569    } else if(s->fat_type==16) {
 570        uint16_t* entry=array_get(&(s->fat),cluster);
 571        return le16_to_cpu(*entry);
 572    } else {
 573        const uint8_t* x=(uint8_t*)(s->fat.pointer)+cluster*3/2;
 574        return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
 575    }
 576}
 577
 578static inline int fat_eof(BDRVVVFATState* s,uint32_t fat_entry)
 579{
 580    if(fat_entry>s->max_fat_value-8)
 581        return -1;
 582    return 0;
 583}
 584
 585static inline void init_fat(BDRVVVFATState* s)
 586{
 587    if (s->fat_type == 12) {
 588        array_init(&(s->fat),1);
 589        array_ensure_allocated(&(s->fat),
 590                s->sectors_per_fat * 0x200 * 3 / 2 - 1);
 591    } else {
 592        array_init(&(s->fat),(s->fat_type==32?4:2));
 593        array_ensure_allocated(&(s->fat),
 594                s->sectors_per_fat * 0x200 / s->fat.item_size - 1);
 595    }
 596    memset(s->fat.pointer,0,s->fat.size);
 597
 598    switch(s->fat_type) {
 599        case 12: s->max_fat_value=0xfff; break;
 600        case 16: s->max_fat_value=0xffff; break;
 601        case 32: s->max_fat_value=0x0fffffff; break;
 602        default: s->max_fat_value=0; /* error... */
 603    }
 604
 605}
 606
 607/* TODO: in create_short_filename, 0xe5->0x05 is not yet handled! */
 608/* TODO: in parse_short_filename, 0x05->0xe5 is not yet handled! */
 609static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,
 610        unsigned int directory_start, const char* filename, int is_dot)
 611{
 612    int i,j,long_index=s->directory.next;
 613    direntry_t* entry = NULL;
 614    direntry_t* entry_long = NULL;
 615
 616    if(is_dot) {
 617        entry=array_get_next(&(s->directory));
 618        memset(entry->name,0x20,11);
 619        memcpy(entry->name,filename,strlen(filename));
 620        return entry;
 621    }
 622
 623    entry_long=create_long_filename(s,filename);
 624
 625    i = strlen(filename);
 626    for(j = i - 1; j>0  && filename[j]!='.';j--);
 627    if (j > 0)
 628        i = (j > 8 ? 8 : j);
 629    else if (i > 8)
 630        i = 8;
 631
 632    entry=array_get_next(&(s->directory));
 633    memset(entry->name,0x20,11);
 634    memcpy(entry->name, filename, i);
 635
 636    if(j > 0)
 637        for (i = 0; i < 3 && filename[j+1+i]; i++)
 638            entry->extension[i] = filename[j+1+i];
 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=(char*)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=(mapping_t*)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        }
 790    }
 791    closedir(dir);
 792
 793    /* fill with zeroes up to the end of the cluster */
 794    while(s->directory.next%(0x10*s->sectors_per_cluster)) {
 795        direntry_t* direntry=array_get_next(&(s->directory));
 796        memset(direntry,0,sizeof(direntry_t));
 797    }
 798
 799/* TODO: if there are more entries, bootsector has to be adjusted! */
 800#define ROOT_ENTRIES (0x02 * 0x10 * s->sectors_per_cluster)
 801    if (mapping_index == 0 && s->directory.next < ROOT_ENTRIES) {
 802        /* root directory */
 803        int cur = s->directory.next;
 804        array_ensure_allocated(&(s->directory), ROOT_ENTRIES - 1);
 805        s->directory.next = ROOT_ENTRIES;
 806        memset(array_get(&(s->directory), cur), 0,
 807                (ROOT_ENTRIES - cur) * sizeof(direntry_t));
 808    }
 809
 810     /* reget the mapping, since s->mapping was possibly realloc()ed */
 811    mapping = (mapping_t*)array_get(&(s->mapping), mapping_index);
 812    first_cluster += (s->directory.next - mapping->info.dir.first_dir_index)
 813        * 0x20 / s->cluster_size;
 814    mapping->end = first_cluster;
 815
 816    direntry = (direntry_t*)array_get(&(s->directory), mapping->dir_index);
 817    set_begin_of_direntry(direntry, mapping->begin);
 818
 819    return 0;
 820}
 821
 822static inline uint32_t sector2cluster(BDRVVVFATState* s,off_t sector_num)
 823{
 824    return (sector_num-s->faked_sectors)/s->sectors_per_cluster;
 825}
 826
 827static inline off_t cluster2sector(BDRVVVFATState* s, uint32_t cluster_num)
 828{
 829    return s->faked_sectors + s->sectors_per_cluster * cluster_num;
 830}
 831
 832static int init_directories(BDRVVVFATState* s,
 833        const char* dirname)
 834{
 835    bootsector_t* bootsector;
 836    mapping_t* mapping;
 837    unsigned int i;
 838    unsigned int cluster;
 839
 840    memset(&(s->first_sectors[0]),0,0x40*0x200);
 841
 842    s->cluster_size=s->sectors_per_cluster*0x200;
 843    s->cluster_buffer=g_malloc(s->cluster_size);
 844
 845    /*
 846     * The formula: sc = spf+1+spf*spc*(512*8/fat_type),
 847     * where sc is sector_count,
 848     * spf is sectors_per_fat,
 849     * spc is sectors_per_clusters, and
 850     * fat_type = 12, 16 or 32.
 851     */
 852    i = 1+s->sectors_per_cluster*0x200*8/s->fat_type;
 853    s->sectors_per_fat=(s->sector_count+i)/i; /* round up */
 854
 855    array_init(&(s->mapping),sizeof(mapping_t));
 856    array_init(&(s->directory),sizeof(direntry_t));
 857
 858    /* add volume label */
 859    {
 860        direntry_t* entry=array_get_next(&(s->directory));
 861        entry->attributes=0x28; /* archive | volume label */
 862        memcpy(entry->name,"QEMU VVF",8);
 863        memcpy(entry->extension,"AT ",3);
 864    }
 865
 866    /* Now build FAT, and write back information into directory */
 867    init_fat(s);
 868
 869    s->faked_sectors=s->first_sectors_number+s->sectors_per_fat*2;
 870    s->cluster_count=sector2cluster(s, s->sector_count);
 871
 872    mapping = array_get_next(&(s->mapping));
 873    mapping->begin = 0;
 874    mapping->dir_index = 0;
 875    mapping->info.dir.parent_mapping_index = -1;
 876    mapping->first_mapping_index = -1;
 877    mapping->path = g_strdup(dirname);
 878    i = strlen(mapping->path);
 879    if (i > 0 && mapping->path[i - 1] == '/')
 880        mapping->path[i - 1] = '\0';
 881    mapping->mode = MODE_DIRECTORY;
 882    mapping->read_only = 0;
 883    s->path = mapping->path;
 884
 885    for (i = 0, cluster = 0; i < s->mapping.next; i++) {
 886        /* MS-DOS expects the FAT to be 0 for the root directory
 887         * (except for the media byte). */
 888        /* LATER TODO: still true for FAT32? */
 889        int fix_fat = (i != 0);
 890        mapping = array_get(&(s->mapping), i);
 891
 892        if (mapping->mode & MODE_DIRECTORY) {
 893            mapping->begin = cluster;
 894            if(read_directory(s, i)) {
 895                fprintf(stderr, "Could not read directory %s\n",
 896                        mapping->path);
 897                return -1;
 898            }
 899            mapping = array_get(&(s->mapping), i);
 900        } else {
 901            assert(mapping->mode == MODE_UNDEFINED);
 902            mapping->mode=MODE_NORMAL;
 903            mapping->begin = cluster;
 904            if (mapping->end > 0) {
 905                direntry_t* direntry = array_get(&(s->directory),
 906                        mapping->dir_index);
 907
 908                mapping->end = cluster + 1 + (mapping->end-1)/s->cluster_size;
 909                set_begin_of_direntry(direntry, mapping->begin);
 910            } else {
 911                mapping->end = cluster + 1;
 912                fix_fat = 0;
 913            }
 914        }
 915
 916        assert(mapping->begin < mapping->end);
 917
 918        /* next free cluster */
 919        cluster = mapping->end;
 920
 921        if(cluster > s->cluster_count) {
 922            fprintf(stderr,"Directory does not fit in FAT%d (capacity %.2f MB)\n",
 923                    s->fat_type, s->sector_count / 2000.0);
 924            return -EINVAL;
 925        }
 926
 927        /* fix fat for entry */
 928        if (fix_fat) {
 929            int j;
 930            for(j = mapping->begin; j < mapping->end - 1; j++)
 931                fat_set(s, j, j+1);
 932            fat_set(s, mapping->end - 1, s->max_fat_value);
 933        }
 934    }
 935
 936    mapping = array_get(&(s->mapping), 0);
 937    s->sectors_of_root_directory = mapping->end * s->sectors_per_cluster;
 938    s->last_cluster_of_root_directory = mapping->end;
 939
 940    /* the FAT signature */
 941    fat_set(s,0,s->max_fat_value);
 942    fat_set(s,1,s->max_fat_value);
 943
 944    s->current_mapping = NULL;
 945
 946    bootsector=(bootsector_t*)(s->first_sectors+(s->first_sectors_number-1)*0x200);
 947    bootsector->jump[0]=0xeb;
 948    bootsector->jump[1]=0x3e;
 949    bootsector->jump[2]=0x90;
 950    memcpy(bootsector->name,"QEMU    ",8);
 951    bootsector->sector_size=cpu_to_le16(0x200);
 952    bootsector->sectors_per_cluster=s->sectors_per_cluster;
 953    bootsector->reserved_sectors=cpu_to_le16(1);
 954    bootsector->number_of_fats=0x2; /* number of FATs */
 955    bootsector->root_entries=cpu_to_le16(s->sectors_of_root_directory*0x10);
 956    bootsector->total_sectors16=s->sector_count>0xffff?0:cpu_to_le16(s->sector_count);
 957    bootsector->media_type=(s->first_sectors_number>1?0xf8:0xf0); /* media descriptor (f8=hd, f0=3.5 fd)*/
 958    s->fat.pointer[0] = bootsector->media_type;
 959    bootsector->sectors_per_fat=cpu_to_le16(s->sectors_per_fat);
 960    bootsector->sectors_per_track=cpu_to_le16(s->bs->secs);
 961    bootsector->number_of_heads=cpu_to_le16(s->bs->heads);
 962    bootsector->hidden_sectors=cpu_to_le32(s->first_sectors_number==1?0:0x3f);
 963    bootsector->total_sectors=cpu_to_le32(s->sector_count>0xffff?s->sector_count:0);
 964
 965    /* LATER TODO: if FAT32, this is wrong */
 966    bootsector->u.fat16.drive_number=s->first_sectors_number==1?0:0x80; /* fda=0, hda=0x80 */
 967    bootsector->u.fat16.current_head=0;
 968    bootsector->u.fat16.signature=0x29;
 969    bootsector->u.fat16.id=cpu_to_le32(0xfabe1afd);
 970
 971    memcpy(bootsector->u.fat16.volume_label,"QEMU VVFAT ",11);
 972    memcpy(bootsector->fat_type,(s->fat_type==12?"FAT12   ":s->fat_type==16?"FAT16   ":"FAT32   "),8);
 973    bootsector->magic[0]=0x55; bootsector->magic[1]=0xaa;
 974
 975    return 0;
 976}
 977
 978#ifdef DEBUG
 979static BDRVVVFATState *vvv = NULL;
 980#endif
 981
 982static int enable_write_target(BDRVVVFATState *s);
 983static int is_consistent(BDRVVVFATState *s);
 984
 985static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
 986{
 987    BDRVVVFATState *s = bs->opaque;
 988    int i;
 989
 990#ifdef DEBUG
 991    vvv = s;
 992#endif
 993
 994DLOG(if (stderr == NULL) {
 995    stderr = fopen("vvfat.log", "a");
 996    setbuf(stderr, NULL);
 997})
 998
 999    s->bs = bs;
1000
1001    /* LATER TODO: if FAT32, adjust */
1002    s->sectors_per_cluster=0x10;
1003
1004    s->current_cluster=0xffffffff;
1005
1006    s->first_sectors_number=0x40;
1007    /* read only is the default for safety */
1008    bs->read_only = 1;
1009    s->qcow = s->write_target = NULL;
1010    s->qcow_filename = NULL;
1011    s->fat2 = NULL;
1012    s->downcase_short_names = 1;
1013
1014    if (!strstart(dirname, "fat:", NULL))
1015        return -1;
1016
1017    if (strstr(dirname, ":32:")) {
1018        fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. You are welcome to do so!\n");
1019        s->fat_type = 32;
1020    } else if (strstr(dirname, ":16:")) {
1021        s->fat_type = 16;
1022    } else if (strstr(dirname, ":12:")) {
1023        s->fat_type = 12;
1024    }
1025
1026    if (strstr(dirname, ":floppy:")) {
1027        /* 1.44MB or 2.88MB floppy.  2.88MB can be FAT12 (default) or FAT16. */
1028        if (!s->fat_type) {
1029            s->fat_type = 12;
1030            bs->secs = 36;
1031            s->sectors_per_cluster=2;
1032        } else {
1033            bs->secs=(s->fat_type == 12 ? 18 : 36);
1034            s->sectors_per_cluster=1;
1035        }
1036        s->first_sectors_number = 1;
1037        bs->cyls=80; bs->heads=2;
1038    } else {
1039        /* 32MB or 504MB disk*/
1040        if (!s->fat_type) {
1041            s->fat_type = 16;
1042        }
1043        bs->cyls=(s->fat_type == 12 ? 64 : 1024);
1044        bs->heads=16; bs->secs=63;
1045    }
1046
1047    s->sector_count=bs->cyls*bs->heads*bs->secs-(s->first_sectors_number-1);
1048
1049    if (strstr(dirname, ":rw:")) {
1050        if (enable_write_target(s))
1051            return -1;
1052        bs->read_only = 0;
1053    }
1054
1055    i = strrchr(dirname, ':') - dirname;
1056    assert(i >= 3);
1057    if (dirname[i-2] == ':' && qemu_isalpha(dirname[i-1]))
1058        /* workaround for DOS drive names */
1059        dirname += i-1;
1060    else
1061        dirname += i+1;
1062
1063    bs->total_sectors=bs->cyls*bs->heads*bs->secs;
1064
1065    if(init_directories(s, dirname))
1066        return -1;
1067
1068    s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
1069
1070    if(s->first_sectors_number==0x40)
1071        init_mbr(s);
1072    else {
1073        /* MS-DOS does not like to know about CHS (?). */
1074        bs->heads = bs->cyls = bs->secs = 0;
1075    }
1076
1077    //    assert(is_consistent(s));
1078    qemu_co_mutex_init(&s->lock);
1079
1080    /* Disable migration when vvfat is used rw */
1081    if (s->qcow) {
1082        error_set(&s->migration_blocker,
1083                  QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
1084                  "vvfat (rw)", bs->device_name, "live migration");
1085        migrate_add_blocker(s->migration_blocker);
1086    }
1087
1088    return 0;
1089}
1090
1091static inline void vvfat_close_current_file(BDRVVVFATState *s)
1092{
1093    if(s->current_mapping) {
1094        s->current_mapping = NULL;
1095        if (s->current_fd) {
1096                close(s->current_fd);
1097                s->current_fd = 0;
1098        }
1099    }
1100    s->current_cluster = -1;
1101}
1102
1103/* mappings between index1 and index2-1 are supposed to be ordered
1104 * return value is the index of the last mapping for which end>cluster_num
1105 */
1106static inline int find_mapping_for_cluster_aux(BDRVVVFATState* s,int cluster_num,int index1,int index2)
1107{
1108    while(1) {
1109        int index3;
1110        mapping_t* mapping;
1111        index3=(index1+index2)/2;
1112        mapping=array_get(&(s->mapping),index3);
1113        assert(mapping->begin < mapping->end);
1114        if(mapping->begin>=cluster_num) {
1115            assert(index2!=index3 || index2==0);
1116            if(index2==index3)
1117                return index1;
1118            index2=index3;
1119        } else {
1120            if(index1==index3)
1121                return mapping->end<=cluster_num ? index2 : index1;
1122            index1=index3;
1123        }
1124        assert(index1<=index2);
1125        DLOG(mapping=array_get(&(s->mapping),index1);
1126        assert(mapping->begin<=cluster_num);
1127        assert(index2 >= s->mapping.next ||
1128                ((mapping = array_get(&(s->mapping),index2)) &&
1129                mapping->end>cluster_num)));
1130    }
1131}
1132
1133static inline mapping_t* find_mapping_for_cluster(BDRVVVFATState* s,int cluster_num)
1134{
1135    int index=find_mapping_for_cluster_aux(s,cluster_num,0,s->mapping.next);
1136    mapping_t* mapping;
1137    if(index>=s->mapping.next)
1138        return NULL;
1139    mapping=array_get(&(s->mapping),index);
1140    if(mapping->begin>cluster_num)
1141        return NULL;
1142    assert(mapping->begin<=cluster_num && mapping->end>cluster_num);
1143    return mapping;
1144}
1145
1146static int open_file(BDRVVVFATState* s,mapping_t* mapping)
1147{
1148    if(!mapping)
1149        return -1;
1150    if(!s->current_mapping ||
1151            strcmp(s->current_mapping->path,mapping->path)) {
1152        /* open file */
1153        int fd = open(mapping->path, O_RDONLY | O_BINARY | O_LARGEFILE);
1154        if(fd<0)
1155            return -1;
1156        vvfat_close_current_file(s);
1157        s->current_fd = fd;
1158        s->current_mapping = mapping;
1159    }
1160    return 0;
1161}
1162
1163static inline int read_cluster(BDRVVVFATState *s,int cluster_num)
1164{
1165    if(s->current_cluster != cluster_num) {
1166        int result=0;
1167        off_t offset;
1168        assert(!s->current_mapping || s->current_fd || (s->current_mapping->mode & MODE_DIRECTORY));
1169        if(!s->current_mapping
1170                || s->current_mapping->begin>cluster_num
1171                || s->current_mapping->end<=cluster_num) {
1172            /* binary search of mappings for file */
1173            mapping_t* mapping=find_mapping_for_cluster(s,cluster_num);
1174
1175            assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
1176
1177            if (mapping && mapping->mode & MODE_DIRECTORY) {
1178                vvfat_close_current_file(s);
1179                s->current_mapping = mapping;
1180read_cluster_directory:
1181                offset = s->cluster_size*(cluster_num-s->current_mapping->begin);
1182                s->cluster = (unsigned char*)s->directory.pointer+offset
1183                        + 0x20*s->current_mapping->info.dir.first_dir_index;
1184                assert(((s->cluster-(unsigned char*)s->directory.pointer)%s->cluster_size)==0);
1185                assert((char*)s->cluster+s->cluster_size <= s->directory.pointer+s->directory.next*s->directory.item_size);
1186                s->current_cluster = cluster_num;
1187                return 0;
1188            }
1189
1190            if(open_file(s,mapping))
1191                return -2;
1192        } else if (s->current_mapping->mode & MODE_DIRECTORY)
1193            goto read_cluster_directory;
1194
1195        assert(s->current_fd);
1196
1197        offset=s->cluster_size*(cluster_num-s->current_mapping->begin)+s->current_mapping->info.file.offset;
1198        if(lseek(s->current_fd, offset, SEEK_SET)!=offset)
1199            return -3;
1200        s->cluster=s->cluster_buffer;
1201        result=read(s->current_fd,s->cluster,s->cluster_size);
1202        if(result<0) {
1203            s->current_cluster = -1;
1204            return -1;
1205        }
1206        s->current_cluster = cluster_num;
1207    }
1208    return 0;
1209}
1210
1211#ifdef DEBUG
1212static void print_direntry(const direntry_t* direntry)
1213{
1214    int j = 0;
1215    char buffer[1024];
1216
1217    fprintf(stderr, "direntry %p: ", direntry);
1218    if(!direntry)
1219        return;
1220    if(is_long_name(direntry)) {
1221        unsigned char* c=(unsigned char*)direntry;
1222        int i;
1223        for(i=1;i<11 && c[i] && c[i]!=0xff;i+=2)
1224#define ADD_CHAR(c) {buffer[j] = (c); if (buffer[j] < ' ') buffer[j] = 0xb0; j++;}
1225            ADD_CHAR(c[i]);
1226        for(i=14;i<26 && c[i] && c[i]!=0xff;i+=2)
1227            ADD_CHAR(c[i]);
1228        for(i=28;i<32 && c[i] && c[i]!=0xff;i+=2)
1229            ADD_CHAR(c[i]);
1230        buffer[j] = 0;
1231        fprintf(stderr, "%s\n", buffer);
1232    } else {
1233        int i;
1234        for(i=0;i<11;i++)
1235            ADD_CHAR(direntry->name[i]);
1236        buffer[j] = 0;
1237        fprintf(stderr,"%s attributes=0x%02x begin=%d size=%d\n",
1238                buffer,
1239                direntry->attributes,
1240                begin_of_direntry(direntry),le32_to_cpu(direntry->size));
1241    }
1242}
1243
1244static void print_mapping(const mapping_t* mapping)
1245{
1246    fprintf(stderr, "mapping (%p): begin, end = %d, %d, dir_index = %d, "
1247        "first_mapping_index = %d, name = %s, mode = 0x%x, " ,
1248        mapping, mapping->begin, mapping->end, mapping->dir_index,
1249        mapping->first_mapping_index, mapping->path, mapping->mode);
1250
1251    if (mapping->mode & MODE_DIRECTORY)
1252        fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
1253    else
1254        fprintf(stderr, "offset = %d\n", mapping->info.file.offset);
1255}
1256#endif
1257
1258static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
1259                    uint8_t *buf, int nb_sectors)
1260{
1261    BDRVVVFATState *s = bs->opaque;
1262    int i;
1263
1264    for(i=0;i<nb_sectors;i++,sector_num++) {
1265        if (sector_num >= bs->total_sectors)
1266           return -1;
1267        if (s->qcow) {
1268            int n;
1269            if (bdrv_is_allocated(s->qcow, sector_num, nb_sectors-i, &n)) {
1270DLOG(fprintf(stderr, "sectors %d+%d allocated\n", (int)sector_num, n));
1271                if (bdrv_read(s->qcow, sector_num, buf + i*0x200, n)) {
1272                    return -1;
1273                }
1274                i += n - 1;
1275                sector_num += n - 1;
1276                continue;
1277            }
1278DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num));
1279        }
1280        if(sector_num<s->faked_sectors) {
1281            if(sector_num<s->first_sectors_number)
1282                memcpy(buf+i*0x200,&(s->first_sectors[sector_num*0x200]),0x200);
1283            else if(sector_num-s->first_sectors_number<s->sectors_per_fat)
1284                memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number)*0x200]),0x200);
1285            else if(sector_num-s->first_sectors_number-s->sectors_per_fat<s->sectors_per_fat)
1286                memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number-s->sectors_per_fat)*0x200]),0x200);
1287        } else {
1288            uint32_t sector=sector_num-s->faked_sectors,
1289            sector_offset_in_cluster=(sector%s->sectors_per_cluster),
1290            cluster_num=sector/s->sectors_per_cluster;
1291            if(cluster_num > s->cluster_count || read_cluster(s, cluster_num) != 0) {
1292                /* LATER TODO: strict: return -1; */
1293                memset(buf+i*0x200,0,0x200);
1294                continue;
1295            }
1296            memcpy(buf+i*0x200,s->cluster+sector_offset_in_cluster*0x200,0x200);
1297        }
1298    }
1299    return 0;
1300}
1301
1302static coroutine_fn int vvfat_co_read(BlockDriverState *bs, int64_t sector_num,
1303                                      uint8_t *buf, int nb_sectors)
1304{
1305    int ret;
1306    BDRVVVFATState *s = bs->opaque;
1307    qemu_co_mutex_lock(&s->lock);
1308    ret = vvfat_read(bs, sector_num, buf, nb_sectors);
1309    qemu_co_mutex_unlock(&s->lock);
1310    return ret;
1311}
1312
1313/* LATER TODO: statify all functions */
1314
1315/*
1316 * Idea of the write support (use snapshot):
1317 *
1318 * 1. check if all data is consistent, recording renames, modifications,
1319 *    new files and directories (in s->commits).
1320 *
1321 * 2. if the data is not consistent, stop committing
1322 *
1323 * 3. handle renames, and create new files and directories (do not yet
1324 *    write their contents)
1325 *
1326 * 4. walk the directories, fixing the mapping and direntries, and marking
1327 *    the handled mappings as not deleted
1328 *
1329 * 5. commit the contents of the files
1330 *
1331 * 6. handle deleted files and directories
1332 *
1333 */
1334
1335typedef struct commit_t {
1336    char* path;
1337    union {
1338        struct { uint32_t cluster; } rename;
1339        struct { int dir_index; uint32_t modified_offset; } writeout;
1340        struct { uint32_t first_cluster; } new_file;
1341        struct { uint32_t cluster; } mkdir;
1342    } param;
1343    /* DELETEs and RMDIRs are handled differently: see handle_deletes() */
1344    enum {
1345        ACTION_RENAME, ACTION_WRITEOUT, ACTION_NEW_FILE, ACTION_MKDIR
1346    } action;
1347} commit_t;
1348
1349static void clear_commits(BDRVVVFATState* s)
1350{
1351    int i;
1352DLOG(fprintf(stderr, "clear_commits (%d commits)\n", s->commits.next));
1353    for (i = 0; i < s->commits.next; i++) {
1354        commit_t* commit = array_get(&(s->commits), i);
1355        assert(commit->path || commit->action == ACTION_WRITEOUT);
1356        if (commit->action != ACTION_WRITEOUT) {
1357            assert(commit->path);
1358            g_free(commit->path);
1359        } else
1360            assert(commit->path == NULL);
1361    }
1362    s->commits.next = 0;
1363}
1364
1365static void schedule_rename(BDRVVVFATState* s,
1366        uint32_t cluster, char* new_path)
1367{
1368    commit_t* commit = array_get_next(&(s->commits));
1369    commit->path = new_path;
1370    commit->param.rename.cluster = cluster;
1371    commit->action = ACTION_RENAME;
1372}
1373
1374static void schedule_writeout(BDRVVVFATState* s,
1375        int dir_index, uint32_t modified_offset)
1376{
1377    commit_t* commit = array_get_next(&(s->commits));
1378    commit->path = NULL;
1379    commit->param.writeout.dir_index = dir_index;
1380    commit->param.writeout.modified_offset = modified_offset;
1381    commit->action = ACTION_WRITEOUT;
1382}
1383
1384static void schedule_new_file(BDRVVVFATState* s,
1385        char* path, uint32_t first_cluster)
1386{
1387    commit_t* commit = array_get_next(&(s->commits));
1388    commit->path = path;
1389    commit->param.new_file.first_cluster = first_cluster;
1390    commit->action = ACTION_NEW_FILE;
1391}
1392
1393static void schedule_mkdir(BDRVVVFATState* s, uint32_t cluster, char* path)
1394{
1395    commit_t* commit = array_get_next(&(s->commits));
1396    commit->path = path;
1397    commit->param.mkdir.cluster = cluster;
1398    commit->action = ACTION_MKDIR;
1399}
1400
1401typedef struct {
1402    /*
1403     * Since the sequence number is at most 0x3f, and the filename
1404     * length is at most 13 times the sequence number, the maximal
1405     * filename length is 0x3f * 13 bytes.
1406     */
1407    unsigned char name[0x3f * 13 + 1];
1408    int checksum, len;
1409    int sequence_number;
1410} long_file_name;
1411
1412static void lfn_init(long_file_name* lfn)
1413{
1414   lfn->sequence_number = lfn->len = 0;
1415   lfn->checksum = 0x100;
1416}
1417
1418/* return 0 if parsed successfully, > 0 if no long name, < 0 if error */
1419static int parse_long_name(long_file_name* lfn,
1420        const direntry_t* direntry)
1421{
1422    int i, j, offset;
1423    const unsigned char* pointer = (const unsigned char*)direntry;
1424
1425    if (!is_long_name(direntry))
1426        return 1;
1427
1428    if (pointer[0] & 0x40) {
1429        lfn->sequence_number = pointer[0] & 0x3f;
1430        lfn->checksum = pointer[13];
1431        lfn->name[0] = 0;
1432        lfn->name[lfn->sequence_number * 13] = 0;
1433    } else if ((pointer[0] & 0x3f) != --lfn->sequence_number)
1434        return -1;
1435    else if (pointer[13] != lfn->checksum)
1436        return -2;
1437    else if (pointer[12] || pointer[26] || pointer[27])
1438        return -3;
1439
1440    offset = 13 * (lfn->sequence_number - 1);
1441    for (i = 0, j = 1; i < 13; i++, j+=2) {
1442        if (j == 11)
1443            j = 14;
1444        else if (j == 26)
1445            j = 28;
1446
1447        if (pointer[j+1] == 0)
1448            lfn->name[offset + i] = pointer[j];
1449        else if (pointer[j+1] != 0xff || (pointer[0] & 0x40) == 0)
1450            return -4;
1451        else
1452            lfn->name[offset + i] = 0;
1453    }
1454
1455    if (pointer[0] & 0x40)
1456        lfn->len = offset + strlen((char*)lfn->name + offset);
1457
1458    return 0;
1459}
1460
1461/* returns 0 if successful, >0 if no short_name, and <0 on error */
1462static int parse_short_name(BDRVVVFATState* s,
1463        long_file_name* lfn, direntry_t* direntry)
1464{
1465    int i, j;
1466
1467    if (!is_short_name(direntry))
1468        return 1;
1469
1470    for (j = 7; j >= 0 && direntry->name[j] == ' '; j--);
1471    for (i = 0; i <= j; i++) {
1472        if (direntry->name[i] <= ' ' || direntry->name[i] > 0x7f)
1473            return -1;
1474        else if (s->downcase_short_names)
1475            lfn->name[i] = qemu_tolower(direntry->name[i]);
1476        else
1477            lfn->name[i] = direntry->name[i];
1478    }
1479
1480    for (j = 2; j >= 0 && direntry->extension[j] == ' '; j--);
1481    if (j >= 0) {
1482        lfn->name[i++] = '.';
1483        lfn->name[i + j + 1] = '\0';
1484        for (;j >= 0; j--) {
1485            if (direntry->extension[j] <= ' ' || direntry->extension[j] > 0x7f)
1486                return -2;
1487            else if (s->downcase_short_names)
1488                lfn->name[i + j] = qemu_tolower(direntry->extension[j]);
1489            else
1490                lfn->name[i + j] = direntry->extension[j];
1491        }
1492    } else
1493        lfn->name[i + j + 1] = '\0';
1494
1495    lfn->len = strlen((char*)lfn->name);
1496
1497    return 0;
1498}
1499
1500static inline uint32_t modified_fat_get(BDRVVVFATState* s,
1501        unsigned int cluster)
1502{
1503    if (cluster < s->last_cluster_of_root_directory) {
1504        if (cluster + 1 == s->last_cluster_of_root_directory)
1505            return s->max_fat_value;
1506        else
1507            return cluster + 1;
1508    }
1509
1510    if (s->fat_type==32) {
1511        uint32_t* entry=((uint32_t*)s->fat2)+cluster;
1512        return le32_to_cpu(*entry);
1513    } else if (s->fat_type==16) {
1514        uint16_t* entry=((uint16_t*)s->fat2)+cluster;
1515        return le16_to_cpu(*entry);
1516    } else {
1517        const uint8_t* x=s->fat2+cluster*3/2;
1518        return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
1519    }
1520}
1521
1522static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num)
1523{
1524    int was_modified = 0;
1525    int i, dummy;
1526
1527    if (s->qcow == NULL)
1528        return 0;
1529
1530    for (i = 0; !was_modified && i < s->sectors_per_cluster; i++)
1531        was_modified = bdrv_is_allocated(s->qcow,
1532                cluster2sector(s, cluster_num) + i, 1, &dummy);
1533
1534    return was_modified;
1535}
1536
1537static const char* get_basename(const char* path)
1538{
1539    char* basename = strrchr(path, '/');
1540    if (basename == NULL)
1541        return path;
1542    else
1543        return basename + 1; /* strip '/' */
1544}
1545
1546/*
1547 * The array s->used_clusters holds the states of the clusters. If it is
1548 * part of a file, it has bit 2 set, in case of a directory, bit 1. If it
1549 * was modified, bit 3 is set.
1550 * If any cluster is allocated, but not part of a file or directory, this
1551 * driver refuses to commit.
1552 */
1553typedef enum {
1554     USED_DIRECTORY = 1, USED_FILE = 2, USED_ANY = 3, USED_ALLOCATED = 4
1555} used_t;
1556
1557/*
1558 * get_cluster_count_for_direntry() not only determines how many clusters
1559 * are occupied by direntry, but also if it was renamed or modified.
1560 *
1561 * A file is thought to be renamed *only* if there already was a file with
1562 * exactly the same first cluster, but a different name.
1563 *
1564 * Further, the files/directories handled by this function are
1565 * assumed to be *not* deleted (and *only* those).
1566 */
1567static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
1568        direntry_t* direntry, const char* path)
1569{
1570    /*
1571     * This is a little bit tricky:
1572     * IF the guest OS just inserts a cluster into the file chain,
1573     * and leaves the rest alone, (i.e. the original file had clusters
1574     * 15 -> 16, but now has 15 -> 32 -> 16), then the following happens:
1575     *
1576     * - do_commit will write the cluster into the file at the given
1577     *   offset, but
1578     *
1579     * - the cluster which is overwritten should be moved to a later
1580     *   position in the file.
1581     *
1582     * I am not aware that any OS does something as braindead, but this
1583     * situation could happen anyway when not committing for a long time.
1584     * Just to be sure that this does not bite us, detect it, and copy the
1585     * contents of the clusters to-be-overwritten into the qcow.
1586     */
1587    int copy_it = 0;
1588    int was_modified = 0;
1589    int32_t ret = 0;
1590
1591    uint32_t cluster_num = begin_of_direntry(direntry);
1592    uint32_t offset = 0;
1593    int first_mapping_index = -1;
1594    mapping_t* mapping = NULL;
1595    const char* basename2 = NULL;
1596
1597    vvfat_close_current_file(s);
1598
1599    /* the root directory */
1600    if (cluster_num == 0)
1601        return 0;
1602
1603    /* write support */
1604    if (s->qcow) {
1605        basename2 = get_basename(path);
1606
1607        mapping = find_mapping_for_cluster(s, cluster_num);
1608
1609        if (mapping) {
1610            const char* basename;
1611
1612            assert(mapping->mode & MODE_DELETED);
1613            mapping->mode &= ~MODE_DELETED;
1614
1615            basename = get_basename(mapping->path);
1616
1617            assert(mapping->mode & MODE_NORMAL);
1618
1619            /* rename */
1620            if (strcmp(basename, basename2))
1621                schedule_rename(s, cluster_num, g_strdup(path));
1622        } else if (is_file(direntry))
1623            /* new file */
1624            schedule_new_file(s, g_strdup(path), cluster_num);
1625        else {
1626            abort();
1627            return 0;
1628        }
1629    }
1630
1631    while(1) {
1632        if (s->qcow) {
1633            if (!copy_it && cluster_was_modified(s, cluster_num)) {
1634                if (mapping == NULL ||
1635                        mapping->begin > cluster_num ||
1636                        mapping->end <= cluster_num)
1637                mapping = find_mapping_for_cluster(s, cluster_num);
1638
1639
1640                if (mapping &&
1641                        (mapping->mode & MODE_DIRECTORY) == 0) {
1642
1643                    /* was modified in qcow */
1644                    if (offset != mapping->info.file.offset + s->cluster_size
1645                            * (cluster_num - mapping->begin)) {
1646                        /* offset of this cluster in file chain has changed */
1647                        abort();
1648                        copy_it = 1;
1649                    } else if (offset == 0) {
1650                        const char* basename = get_basename(mapping->path);
1651
1652                        if (strcmp(basename, basename2))
1653                            copy_it = 1;
1654                        first_mapping_index = array_index(&(s->mapping), mapping);
1655                    }
1656
1657                    if (mapping->first_mapping_index != first_mapping_index
1658                            && mapping->info.file.offset > 0) {
1659                        abort();
1660                        copy_it = 1;
1661                    }
1662
1663                    /* need to write out? */
1664                    if (!was_modified && is_file(direntry)) {
1665                        was_modified = 1;
1666                        schedule_writeout(s, mapping->dir_index, offset);
1667                    }
1668                }
1669            }
1670
1671            if (copy_it) {
1672                int i, dummy;
1673                /*
1674                 * This is horribly inefficient, but that is okay, since
1675                 * it is rarely executed, if at all.
1676                 */
1677                int64_t offset = cluster2sector(s, cluster_num);
1678
1679                vvfat_close_current_file(s);
1680                for (i = 0; i < s->sectors_per_cluster; i++) {
1681                    if (!bdrv_is_allocated(s->qcow, offset + i, 1, &dummy)) {
1682                        if (vvfat_read(s->bs, offset, s->cluster_buffer, 1)) {
1683                            return -1;
1684                        }
1685                        if (bdrv_write(s->qcow, offset, s->cluster_buffer, 1)) {
1686                            return -2;
1687                        }
1688                    }
1689                }
1690            }
1691        }
1692
1693        ret++;
1694        if (s->used_clusters[cluster_num] & USED_ANY)
1695            return 0;
1696        s->used_clusters[cluster_num] = USED_FILE;
1697
1698        cluster_num = modified_fat_get(s, cluster_num);
1699
1700        if (fat_eof(s, cluster_num))
1701            return ret;
1702        else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
1703            return -1;
1704
1705        offset += s->cluster_size;
1706    }
1707}
1708
1709/*
1710 * This function looks at the modified data (qcow).
1711 * It returns 0 upon inconsistency or error, and the number of clusters
1712 * used by the directory, its subdirectories and their files.
1713 */
1714static int check_directory_consistency(BDRVVVFATState *s,
1715        int cluster_num, const char* path)
1716{
1717    int ret = 0;
1718    unsigned char* cluster = g_malloc(s->cluster_size);
1719    direntry_t* direntries = (direntry_t*)cluster;
1720    mapping_t* mapping = find_mapping_for_cluster(s, cluster_num);
1721
1722    long_file_name lfn;
1723    int path_len = strlen(path);
1724    char path2[PATH_MAX + 1];
1725
1726    assert(path_len < PATH_MAX); /* len was tested before! */
1727    pstrcpy(path2, sizeof(path2), path);
1728    path2[path_len] = '/';
1729    path2[path_len + 1] = '\0';
1730
1731    if (mapping) {
1732        const char* basename = get_basename(mapping->path);
1733        const char* basename2 = get_basename(path);
1734
1735        assert(mapping->mode & MODE_DIRECTORY);
1736
1737        assert(mapping->mode & MODE_DELETED);
1738        mapping->mode &= ~MODE_DELETED;
1739
1740        if (strcmp(basename, basename2))
1741            schedule_rename(s, cluster_num, g_strdup(path));
1742    } else
1743        /* new directory */
1744        schedule_mkdir(s, cluster_num, g_strdup(path));
1745
1746    lfn_init(&lfn);
1747    do {
1748        int i;
1749        int subret = 0;
1750
1751        ret++;
1752
1753        if (s->used_clusters[cluster_num] & USED_ANY) {
1754            fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
1755            return 0;
1756        }
1757        s->used_clusters[cluster_num] = USED_DIRECTORY;
1758
1759DLOG(fprintf(stderr, "read cluster %d (sector %d)\n", (int)cluster_num, (int)cluster2sector(s, cluster_num)));
1760        subret = vvfat_read(s->bs, cluster2sector(s, cluster_num), cluster,
1761                s->sectors_per_cluster);
1762        if (subret) {
1763            fprintf(stderr, "Error fetching direntries\n");
1764        fail:
1765            g_free(cluster);
1766            return 0;
1767        }
1768
1769        for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
1770            int cluster_count = 0;
1771
1772DLOG(fprintf(stderr, "check direntry %d:\n", i); print_direntry(direntries + i));
1773            if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
1774                    is_free(direntries + i))
1775                continue;
1776
1777            subret = parse_long_name(&lfn, direntries + i);
1778            if (subret < 0) {
1779                fprintf(stderr, "Error in long name\n");
1780                goto fail;
1781            }
1782            if (subret == 0 || is_free(direntries + i))
1783                continue;
1784
1785            if (fat_chksum(direntries+i) != lfn.checksum) {
1786                subret = parse_short_name(s, &lfn, direntries + i);
1787                if (subret < 0) {
1788                    fprintf(stderr, "Error in short name (%d)\n", subret);
1789                    goto fail;
1790                }
1791                if (subret > 0 || !strcmp((char*)lfn.name, ".")
1792                        || !strcmp((char*)lfn.name, ".."))
1793                    continue;
1794            }
1795            lfn.checksum = 0x100; /* cannot use long name twice */
1796
1797            if (path_len + 1 + lfn.len >= PATH_MAX) {
1798                fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
1799                goto fail;
1800            }
1801            pstrcpy(path2 + path_len + 1, sizeof(path2) - path_len - 1,
1802                    (char*)lfn.name);
1803
1804            if (is_directory(direntries + i)) {
1805                if (begin_of_direntry(direntries + i) == 0) {
1806                    DLOG(fprintf(stderr, "invalid begin for directory: %s\n", path2); print_direntry(direntries + i));
1807                    goto fail;
1808                }
1809                cluster_count = check_directory_consistency(s,
1810                        begin_of_direntry(direntries + i), path2);
1811                if (cluster_count == 0) {
1812                    DLOG(fprintf(stderr, "problem in directory %s:\n", path2); print_direntry(direntries + i));
1813                    goto fail;
1814                }
1815            } else if (is_file(direntries + i)) {
1816                /* check file size with FAT */
1817                cluster_count = get_cluster_count_for_direntry(s, direntries + i, path2);
1818                if (cluster_count !=
1819                        (le32_to_cpu(direntries[i].size) + s->cluster_size
1820                         - 1) / s->cluster_size) {
1821                    DLOG(fprintf(stderr, "Cluster count mismatch\n"));
1822                    goto fail;
1823                }
1824            } else
1825                abort(); /* cluster_count = 0; */
1826
1827            ret += cluster_count;
1828        }
1829
1830        cluster_num = modified_fat_get(s, cluster_num);
1831    } while(!fat_eof(s, cluster_num));
1832
1833    g_free(cluster);
1834    return ret;
1835}
1836
1837/* returns 1 on success */
1838static int is_consistent(BDRVVVFATState* s)
1839{
1840    int i, check;
1841    int used_clusters_count = 0;
1842
1843DLOG(checkpoint());
1844    /*
1845     * - get modified FAT
1846     * - compare the two FATs (TODO)
1847     * - get buffer for marking used clusters
1848     * - recurse direntries from root (using bs->bdrv_read to make
1849     *    sure to get the new data)
1850     *   - check that the FAT agrees with the size
1851     *   - count the number of clusters occupied by this directory and
1852     *     its files
1853     * - check that the cumulative used cluster count agrees with the
1854     *   FAT
1855     * - if all is fine, return number of used clusters
1856     */
1857    if (s->fat2 == NULL) {
1858        int size = 0x200 * s->sectors_per_fat;
1859        s->fat2 = g_malloc(size);
1860        memcpy(s->fat2, s->fat.pointer, size);
1861    }
1862    check = vvfat_read(s->bs,
1863            s->first_sectors_number, s->fat2, s->sectors_per_fat);
1864    if (check) {
1865        fprintf(stderr, "Could not copy fat\n");
1866        return 0;
1867    }
1868    assert (s->used_clusters);
1869    for (i = 0; i < sector2cluster(s, s->sector_count); i++)
1870        s->used_clusters[i] &= ~USED_ANY;
1871
1872    clear_commits(s);
1873
1874    /* mark every mapped file/directory as deleted.
1875     * (check_directory_consistency() will unmark those still present). */
1876    if (s->qcow)
1877        for (i = 0; i < s->mapping.next; i++) {
1878            mapping_t* mapping = array_get(&(s->mapping), i);
1879            if (mapping->first_mapping_index < 0)
1880                mapping->mode |= MODE_DELETED;
1881        }
1882
1883    used_clusters_count = check_directory_consistency(s, 0, s->path);
1884    if (used_clusters_count <= 0) {
1885        DLOG(fprintf(stderr, "problem in directory\n"));
1886        return 0;
1887    }
1888
1889    check = s->last_cluster_of_root_directory;
1890    for (i = check; i < sector2cluster(s, s->sector_count); i++) {
1891        if (modified_fat_get(s, i)) {
1892            if(!s->used_clusters[i]) {
1893                DLOG(fprintf(stderr, "FAT was modified (%d), but cluster is not used?\n", i));
1894                return 0;
1895            }
1896            check++;
1897        }
1898
1899        if (s->used_clusters[i] == USED_ALLOCATED) {
1900            /* allocated, but not used... */
1901            DLOG(fprintf(stderr, "unused, modified cluster: %d\n", i));
1902            return 0;
1903        }
1904    }
1905
1906    if (check != used_clusters_count)
1907        return 0;
1908
1909    return used_clusters_count;
1910}
1911
1912static inline void adjust_mapping_indices(BDRVVVFATState* s,
1913        int offset, int adjust)
1914{
1915    int i;
1916
1917    for (i = 0; i < s->mapping.next; i++) {
1918        mapping_t* mapping = array_get(&(s->mapping), i);
1919
1920#define ADJUST_MAPPING_INDEX(name) \
1921        if (mapping->name >= offset) \
1922            mapping->name += adjust
1923
1924        ADJUST_MAPPING_INDEX(first_mapping_index);
1925        if (mapping->mode & MODE_DIRECTORY)
1926            ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
1927    }
1928}
1929
1930/* insert or update mapping */
1931static mapping_t* insert_mapping(BDRVVVFATState* s,
1932        uint32_t begin, uint32_t end)
1933{
1934    /*
1935     * - find mapping where mapping->begin >= begin,
1936     * - if mapping->begin > begin: insert
1937     *   - adjust all references to mappings!
1938     * - else: adjust
1939     * - replace name
1940     */
1941    int index = find_mapping_for_cluster_aux(s, begin, 0, s->mapping.next);
1942    mapping_t* mapping = NULL;
1943    mapping_t* first_mapping = array_get(&(s->mapping), 0);
1944
1945    if (index < s->mapping.next && (mapping = array_get(&(s->mapping), index))
1946            && mapping->begin < begin) {
1947        mapping->end = begin;
1948        index++;
1949        mapping = array_get(&(s->mapping), index);
1950    }
1951    if (index >= s->mapping.next || mapping->begin > begin) {
1952        mapping = array_insert(&(s->mapping), index, 1);
1953        mapping->path = NULL;
1954        adjust_mapping_indices(s, index, +1);
1955    }
1956
1957    mapping->begin = begin;
1958    mapping->end = end;
1959
1960DLOG(mapping_t* next_mapping;
1961assert(index + 1 >= s->mapping.next ||
1962((next_mapping = array_get(&(s->mapping), index + 1)) &&
1963 next_mapping->begin >= end)));
1964
1965    if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1966        s->current_mapping = array_get(&(s->mapping),
1967                s->current_mapping - first_mapping);
1968
1969    return mapping;
1970}
1971
1972static int remove_mapping(BDRVVVFATState* s, int mapping_index)
1973{
1974    mapping_t* mapping = array_get(&(s->mapping), mapping_index);
1975    mapping_t* first_mapping = array_get(&(s->mapping), 0);
1976
1977    /* free mapping */
1978    if (mapping->first_mapping_index < 0) {
1979        g_free(mapping->path);
1980    }
1981
1982    /* remove from s->mapping */
1983    array_remove(&(s->mapping), mapping_index);
1984
1985    /* adjust all references to mappings */
1986    adjust_mapping_indices(s, mapping_index, -1);
1987
1988    if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1989        s->current_mapping = array_get(&(s->mapping),
1990                s->current_mapping - first_mapping);
1991
1992    return 0;
1993}
1994
1995static void adjust_dirindices(BDRVVVFATState* s, int offset, int adjust)
1996{
1997    int i;
1998    for (i = 0; i < s->mapping.next; i++) {
1999        mapping_t* mapping = array_get(&(s->mapping), i);
2000        if (mapping->dir_index >= offset)
2001            mapping->dir_index += adjust;
2002        if ((mapping->mode & MODE_DIRECTORY) &&
2003                mapping->info.dir.first_dir_index >= offset)
2004            mapping->info.dir.first_dir_index += adjust;
2005    }
2006}
2007
2008static direntry_t* insert_direntries(BDRVVVFATState* s,
2009        int dir_index, int count)
2010{
2011    /*
2012     * make room in s->directory,
2013     * adjust_dirindices
2014     */
2015    direntry_t* result = array_insert(&(s->directory), dir_index, count);
2016    if (result == NULL)
2017        return NULL;
2018    adjust_dirindices(s, dir_index, count);
2019    return result;
2020}
2021
2022static int remove_direntries(BDRVVVFATState* s, int dir_index, int count)
2023{
2024    int ret = array_remove_slice(&(s->directory), dir_index, count);
2025    if (ret)
2026        return ret;
2027    adjust_dirindices(s, dir_index, -count);
2028    return 0;
2029}
2030
2031/*
2032 * Adapt the mappings of the cluster chain starting at first cluster
2033 * (i.e. if a file starts at first_cluster, the chain is followed according
2034 * to the modified fat, and the corresponding entries in s->mapping are
2035 * adjusted)
2036 */
2037static int commit_mappings(BDRVVVFATState* s,
2038        uint32_t first_cluster, int dir_index)
2039{
2040    mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2041    direntry_t* direntry = array_get(&(s->directory), dir_index);
2042    uint32_t cluster = first_cluster;
2043
2044    vvfat_close_current_file(s);
2045
2046    assert(mapping);
2047    assert(mapping->begin == first_cluster);
2048    mapping->first_mapping_index = -1;
2049    mapping->dir_index = dir_index;
2050    mapping->mode = (dir_index <= 0 || is_directory(direntry)) ?
2051        MODE_DIRECTORY : MODE_NORMAL;
2052
2053    while (!fat_eof(s, cluster)) {
2054        uint32_t c, c1;
2055
2056        for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
2057                c = c1, c1 = modified_fat_get(s, c1));
2058
2059        c++;
2060        if (c > mapping->end) {
2061            int index = array_index(&(s->mapping), mapping);
2062            int i, max_i = s->mapping.next - index;
2063            for (i = 1; i < max_i && mapping[i].begin < c; i++);
2064            while (--i > 0)
2065                remove_mapping(s, index + 1);
2066        }
2067        assert(mapping == array_get(&(s->mapping), s->mapping.next - 1)
2068                || mapping[1].begin >= c);
2069        mapping->end = c;
2070
2071        if (!fat_eof(s, c1)) {
2072            int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next);
2073            mapping_t* next_mapping = i >= s->mapping.next ? NULL :
2074                array_get(&(s->mapping), i);
2075
2076            if (next_mapping == NULL || next_mapping->begin > c1) {
2077                int i1 = array_index(&(s->mapping), mapping);
2078
2079                next_mapping = insert_mapping(s, c1, c1+1);
2080
2081                if (c1 < c)
2082                    i1++;
2083                mapping = array_get(&(s->mapping), i1);
2084            }
2085
2086            next_mapping->dir_index = mapping->dir_index;
2087            next_mapping->first_mapping_index =
2088                mapping->first_mapping_index < 0 ?
2089                array_index(&(s->mapping), mapping) :
2090                mapping->first_mapping_index;
2091            next_mapping->path = mapping->path;
2092            next_mapping->mode = mapping->mode;
2093            next_mapping->read_only = mapping->read_only;
2094            if (mapping->mode & MODE_DIRECTORY) {
2095                next_mapping->info.dir.parent_mapping_index =
2096                        mapping->info.dir.parent_mapping_index;
2097                next_mapping->info.dir.first_dir_index =
2098                        mapping->info.dir.first_dir_index +
2099                        0x10 * s->sectors_per_cluster *
2100                        (mapping->end - mapping->begin);
2101            } else
2102                next_mapping->info.file.offset = mapping->info.file.offset +
2103                        mapping->end - mapping->begin;
2104
2105            mapping = next_mapping;
2106        }
2107
2108        cluster = c1;
2109    }
2110
2111    return 0;
2112}
2113
2114static int commit_direntries(BDRVVVFATState* s,
2115        int dir_index, int parent_mapping_index)
2116{
2117    direntry_t* direntry = array_get(&(s->directory), dir_index);
2118    uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
2119    mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
2120
2121    int factor = 0x10 * s->sectors_per_cluster;
2122    int old_cluster_count, new_cluster_count;
2123    int current_dir_index = mapping->info.dir.first_dir_index;
2124    int first_dir_index = current_dir_index;
2125    int ret, i;
2126    uint32_t c;
2127
2128DLOG(fprintf(stderr, "commit_direntries for %s, parent_mapping_index %d\n", mapping->path, parent_mapping_index));
2129
2130    assert(direntry);
2131    assert(mapping);
2132    assert(mapping->begin == first_cluster);
2133    assert(mapping->info.dir.first_dir_index < s->directory.next);
2134    assert(mapping->mode & MODE_DIRECTORY);
2135    assert(dir_index == 0 || is_directory(direntry));
2136
2137    mapping->info.dir.parent_mapping_index = parent_mapping_index;
2138
2139    if (first_cluster == 0) {
2140        old_cluster_count = new_cluster_count =
2141            s->last_cluster_of_root_directory;
2142    } else {
2143        for (old_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2144                c = fat_get(s, c))
2145            old_cluster_count++;
2146
2147        for (new_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2148                c = modified_fat_get(s, c))
2149            new_cluster_count++;
2150    }
2151
2152    if (new_cluster_count > old_cluster_count) {
2153        if (insert_direntries(s,
2154                current_dir_index + factor * old_cluster_count,
2155                factor * (new_cluster_count - old_cluster_count)) == NULL)
2156            return -1;
2157    } else if (new_cluster_count < old_cluster_count)
2158        remove_direntries(s,
2159                current_dir_index + factor * new_cluster_count,
2160                factor * (old_cluster_count - new_cluster_count));
2161
2162    for (c = first_cluster; !fat_eof(s, c); c = modified_fat_get(s, c)) {
2163        void* direntry = array_get(&(s->directory), current_dir_index);
2164        int ret = vvfat_read(s->bs, cluster2sector(s, c), direntry,
2165                s->sectors_per_cluster);
2166        if (ret)
2167            return ret;
2168        assert(!strncmp(s->directory.pointer, "QEMU", 4));
2169        current_dir_index += factor;
2170    }
2171
2172    ret = commit_mappings(s, first_cluster, dir_index);
2173    if (ret)
2174        return ret;
2175
2176    /* recurse */
2177    for (i = 0; i < factor * new_cluster_count; i++) {
2178        direntry = array_get(&(s->directory), first_dir_index + i);
2179        if (is_directory(direntry) && !is_dot(direntry)) {
2180            mapping = find_mapping_for_cluster(s, first_cluster);
2181            assert(mapping->mode & MODE_DIRECTORY);
2182            ret = commit_direntries(s, first_dir_index + i,
2183                array_index(&(s->mapping), mapping));
2184            if (ret)
2185                return ret;
2186        }
2187    }
2188
2189    return 0;
2190}
2191
2192/* commit one file (adjust contents, adjust mapping),
2193   return first_mapping_index */
2194static int commit_one_file(BDRVVVFATState* s,
2195        int dir_index, uint32_t offset)
2196{
2197    direntry_t* direntry = array_get(&(s->directory), dir_index);
2198    uint32_t c = begin_of_direntry(direntry);
2199    uint32_t first_cluster = c;
2200    mapping_t* mapping = find_mapping_for_cluster(s, c);
2201    uint32_t size = filesize_of_direntry(direntry);
2202    char* cluster = g_malloc(s->cluster_size);
2203    uint32_t i;
2204    int fd = 0;
2205
2206    assert(offset < size);
2207    assert((offset % s->cluster_size) == 0);
2208
2209    for (i = s->cluster_size; i < offset; i += s->cluster_size)
2210        c = modified_fat_get(s, c);
2211
2212    fd = open(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666);
2213    if (fd < 0) {
2214        fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path,
2215                strerror(errno), errno);
2216        g_free(cluster);
2217        return fd;
2218    }
2219    if (offset > 0) {
2220        if (lseek(fd, offset, SEEK_SET) != offset) {
2221            g_free(cluster);
2222            return -3;
2223        }
2224    }
2225
2226    while (offset < size) {
2227        uint32_t c1;
2228        int rest_size = (size - offset > s->cluster_size ?
2229                s->cluster_size : size - offset);
2230        int ret;
2231
2232        c1 = modified_fat_get(s, c);
2233
2234        assert((size - offset == 0 && fat_eof(s, c)) ||
2235                (size > offset && c >=2 && !fat_eof(s, c)));
2236
2237        ret = vvfat_read(s->bs, cluster2sector(s, c),
2238            (uint8_t*)cluster, (rest_size + 0x1ff) / 0x200);
2239
2240        if (ret < 0) {
2241            g_free(cluster);
2242            return ret;
2243        }
2244
2245        if (write(fd, cluster, rest_size) < 0) {
2246            g_free(cluster);
2247            return -2;
2248        }
2249
2250        offset += rest_size;
2251        c = c1;
2252    }
2253
2254    if (ftruncate(fd, size)) {
2255        perror("ftruncate()");
2256        close(fd);
2257        g_free(cluster);
2258        return -4;
2259    }
2260    close(fd);
2261    g_free(cluster);
2262
2263    return commit_mappings(s, first_cluster, dir_index);
2264}
2265
2266#ifdef DEBUG
2267/* test, if all mappings point to valid direntries */
2268static void check1(BDRVVVFATState* s)
2269{
2270    int i;
2271    for (i = 0; i < s->mapping.next; i++) {
2272        mapping_t* mapping = array_get(&(s->mapping), i);
2273        if (mapping->mode & MODE_DELETED) {
2274            fprintf(stderr, "deleted\n");
2275            continue;
2276        }
2277        assert(mapping->dir_index < s->directory.next);
2278        direntry_t* direntry = array_get(&(s->directory), mapping->dir_index);
2279        assert(mapping->begin == begin_of_direntry(direntry) || mapping->first_mapping_index >= 0);
2280        if (mapping->mode & MODE_DIRECTORY) {
2281            assert(mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster * (mapping->end - mapping->begin) <= s->directory.next);
2282            assert((mapping->info.dir.first_dir_index % (0x10 * s->sectors_per_cluster)) == 0);
2283        }
2284    }
2285}
2286
2287/* test, if all direntries have mappings */
2288static void check2(BDRVVVFATState* s)
2289{
2290    int i;
2291    int first_mapping = -1;
2292
2293    for (i = 0; i < s->directory.next; i++) {
2294        direntry_t* direntry = array_get(&(s->directory), i);
2295
2296        if (is_short_name(direntry) && begin_of_direntry(direntry)) {
2297            mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
2298            assert(mapping);
2299            assert(mapping->dir_index == i || is_dot(direntry));
2300            assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry));
2301        }
2302
2303        if ((i % (0x10 * s->sectors_per_cluster)) == 0) {
2304            /* cluster start */
2305            int j, count = 0;
2306
2307            for (j = 0; j < s->mapping.next; j++) {
2308                mapping_t* mapping = array_get(&(s->mapping), j);
2309                if (mapping->mode & MODE_DELETED)
2310                    continue;
2311                if (mapping->mode & MODE_DIRECTORY) {
2312                    if (mapping->info.dir.first_dir_index <= i && mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster > i) {
2313                        assert(++count == 1);
2314                        if (mapping->first_mapping_index == -1)
2315                            first_mapping = array_index(&(s->mapping), mapping);
2316                        else
2317                            assert(first_mapping == mapping->first_mapping_index);
2318                        if (mapping->info.dir.parent_mapping_index < 0)
2319                            assert(j == 0);
2320                        else {
2321                            mapping_t* parent = array_get(&(s->mapping), mapping->info.dir.parent_mapping_index);
2322                            assert(parent->mode & MODE_DIRECTORY);
2323                            assert(parent->info.dir.first_dir_index < mapping->info.dir.first_dir_index);
2324                        }
2325                    }
2326                }
2327            }
2328            if (count == 0)
2329                first_mapping = -1;
2330        }
2331    }
2332}
2333#endif
2334
2335static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2336{
2337    int i;
2338
2339#ifdef DEBUG
2340    fprintf(stderr, "handle_renames\n");
2341    for (i = 0; i < s->commits.next; i++) {
2342        commit_t* commit = array_get(&(s->commits), i);
2343        fprintf(stderr, "%d, %s (%d, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action);
2344    }
2345#endif
2346
2347    for (i = 0; i < s->commits.next;) {
2348        commit_t* commit = array_get(&(s->commits), i);
2349        if (commit->action == ACTION_RENAME) {
2350            mapping_t* mapping = find_mapping_for_cluster(s,
2351                    commit->param.rename.cluster);
2352            char* old_path = mapping->path;
2353
2354            assert(commit->path);
2355            mapping->path = commit->path;
2356            if (rename(old_path, mapping->path))
2357                return -2;
2358
2359            if (mapping->mode & MODE_DIRECTORY) {
2360                int l1 = strlen(mapping->path);
2361                int l2 = strlen(old_path);
2362                int diff = l1 - l2;
2363                direntry_t* direntry = array_get(&(s->directory),
2364                        mapping->info.dir.first_dir_index);
2365                uint32_t c = mapping->begin;
2366                int i = 0;
2367
2368                /* recurse */
2369                while (!fat_eof(s, c)) {
2370                    do {
2371                        direntry_t* d = direntry + i;
2372
2373                        if (is_file(d) || (is_directory(d) && !is_dot(d))) {
2374                            mapping_t* m = find_mapping_for_cluster(s,
2375                                    begin_of_direntry(d));
2376                            int l = strlen(m->path);
2377                            char* new_path = g_malloc(l + diff + 1);
2378
2379                            assert(!strncmp(m->path, mapping->path, l2));
2380
2381                            pstrcpy(new_path, l + diff + 1, mapping->path);
2382                            pstrcpy(new_path + l1, l + diff + 1 - l1,
2383                                    m->path + l2);
2384
2385                            schedule_rename(s, m->begin, new_path);
2386                        }
2387                        i++;
2388                    } while((i % (0x10 * s->sectors_per_cluster)) != 0);
2389                    c = fat_get(s, c);
2390                }
2391            }
2392
2393            g_free(old_path);
2394            array_remove(&(s->commits), i);
2395            continue;
2396        } else if (commit->action == ACTION_MKDIR) {
2397            mapping_t* mapping;
2398            int j, parent_path_len;
2399
2400#ifdef __MINGW32__
2401            if (mkdir(commit->path))
2402                return -5;
2403#else
2404            if (mkdir(commit->path, 0755))
2405                return -5;
2406#endif
2407
2408            mapping = insert_mapping(s, commit->param.mkdir.cluster,
2409                    commit->param.mkdir.cluster + 1);
2410            if (mapping == NULL)
2411                return -6;
2412
2413            mapping->mode = MODE_DIRECTORY;
2414            mapping->read_only = 0;
2415            mapping->path = commit->path;
2416            j = s->directory.next;
2417            assert(j);
2418            insert_direntries(s, s->directory.next,
2419                    0x10 * s->sectors_per_cluster);
2420            mapping->info.dir.first_dir_index = j;
2421
2422            parent_path_len = strlen(commit->path)
2423                - strlen(get_basename(commit->path)) - 1;
2424            for (j = 0; j < s->mapping.next; j++) {
2425                mapping_t* m = array_get(&(s->mapping), j);
2426                if (m->first_mapping_index < 0 && m != mapping &&
2427                        !strncmp(m->path, mapping->path, parent_path_len) &&
2428                        strlen(m->path) == parent_path_len)
2429                    break;
2430            }
2431            assert(j < s->mapping.next);
2432            mapping->info.dir.parent_mapping_index = j;
2433
2434            array_remove(&(s->commits), i);
2435            continue;
2436        }
2437
2438        i++;
2439    }
2440    return 0;
2441}
2442
2443/*
2444 * TODO: make sure that the short name is not matching *another* file
2445 */
2446static int handle_commits(BDRVVVFATState* s)
2447{
2448    int i, fail = 0;
2449
2450    vvfat_close_current_file(s);
2451
2452    for (i = 0; !fail && i < s->commits.next; i++) {
2453        commit_t* commit = array_get(&(s->commits), i);
2454        switch(commit->action) {
2455        case ACTION_RENAME: case ACTION_MKDIR:
2456            abort();
2457            fail = -2;
2458            break;
2459        case ACTION_WRITEOUT: {
2460#ifndef NDEBUG
2461            /* these variables are only used by assert() below */
2462            direntry_t* entry = array_get(&(s->directory),
2463                    commit->param.writeout.dir_index);
2464            uint32_t begin = begin_of_direntry(entry);
2465            mapping_t* mapping = find_mapping_for_cluster(s, begin);
2466#endif
2467
2468            assert(mapping);
2469            assert(mapping->begin == begin);
2470            assert(commit->path == NULL);
2471
2472            if (commit_one_file(s, commit->param.writeout.dir_index,
2473                        commit->param.writeout.modified_offset))
2474                fail = -3;
2475
2476            break;
2477        }
2478        case ACTION_NEW_FILE: {
2479            int begin = commit->param.new_file.first_cluster;
2480            mapping_t* mapping = find_mapping_for_cluster(s, begin);
2481            direntry_t* entry;
2482            int i;
2483
2484            /* find direntry */
2485            for (i = 0; i < s->directory.next; i++) {
2486                entry = array_get(&(s->directory), i);
2487                if (is_file(entry) && begin_of_direntry(entry) == begin)
2488                    break;
2489            }
2490
2491            if (i >= s->directory.next) {
2492                fail = -6;
2493                continue;
2494            }
2495
2496            /* make sure there exists an initial mapping */
2497            if (mapping && mapping->begin != begin) {
2498                mapping->end = begin;
2499                mapping = NULL;
2500            }
2501            if (mapping == NULL) {
2502                mapping = insert_mapping(s, begin, begin+1);
2503            }
2504            /* most members will be fixed in commit_mappings() */
2505            assert(commit->path);
2506            mapping->path = commit->path;
2507            mapping->read_only = 0;
2508            mapping->mode = MODE_NORMAL;
2509            mapping->info.file.offset = 0;
2510
2511            if (commit_one_file(s, i, 0))
2512                fail = -7;
2513
2514            break;
2515        }
2516        default:
2517            abort();
2518        }
2519    }
2520    if (i > 0 && array_remove_slice(&(s->commits), 0, i))
2521        return -1;
2522    return fail;
2523}
2524
2525static int handle_deletes(BDRVVVFATState* s)
2526{
2527    int i, deferred = 1, deleted = 1;
2528
2529    /* delete files corresponding to mappings marked as deleted */
2530    /* handle DELETEs and unused mappings (modified_fat_get(s, mapping->begin) == 0) */
2531    while (deferred && deleted) {
2532        deferred = 0;
2533        deleted = 0;
2534
2535        for (i = 1; i < s->mapping.next; i++) {
2536            mapping_t* mapping = array_get(&(s->mapping), i);
2537            if (mapping->mode & MODE_DELETED) {
2538                direntry_t* entry = array_get(&(s->directory),
2539                        mapping->dir_index);
2540
2541                if (is_free(entry)) {
2542                    /* remove file/directory */
2543                    if (mapping->mode & MODE_DIRECTORY) {
2544                        int j, next_dir_index = s->directory.next,
2545                        first_dir_index = mapping->info.dir.first_dir_index;
2546
2547                        if (rmdir(mapping->path) < 0) {
2548                            if (errno == ENOTEMPTY) {
2549                                deferred++;
2550                                continue;
2551                            } else
2552                                return -5;
2553                        }
2554
2555                        for (j = 1; j < s->mapping.next; j++) {
2556                            mapping_t* m = array_get(&(s->mapping), j);
2557                            if (m->mode & MODE_DIRECTORY &&
2558                                    m->info.dir.first_dir_index >
2559                                    first_dir_index &&
2560                                    m->info.dir.first_dir_index <
2561                                    next_dir_index)
2562                                next_dir_index =
2563                                    m->info.dir.first_dir_index;
2564                        }
2565                        remove_direntries(s, first_dir_index,
2566                                next_dir_index - first_dir_index);
2567
2568                        deleted++;
2569                    }
2570                } else {
2571                    if (unlink(mapping->path))
2572                        return -4;
2573                    deleted++;
2574                }
2575                DLOG(fprintf(stderr, "DELETE (%d)\n", i); print_mapping(mapping); print_direntry(entry));
2576                remove_mapping(s, i);
2577            }
2578        }
2579    }
2580
2581    return 0;
2582}
2583
2584/*
2585 * synchronize mapping with new state:
2586 *
2587 * - copy FAT (with bdrv_read)
2588 * - mark all filenames corresponding to mappings as deleted
2589 * - recurse direntries from root (using bs->bdrv_read)
2590 * - delete files corresponding to mappings marked as deleted
2591 */
2592static int do_commit(BDRVVVFATState* s)
2593{
2594    int ret = 0;
2595
2596    /* the real meat are the commits. Nothing to do? Move along! */
2597    if (s->commits.next == 0)
2598        return 0;
2599
2600    vvfat_close_current_file(s);
2601
2602    ret = handle_renames_and_mkdirs(s);
2603    if (ret) {
2604        fprintf(stderr, "Error handling renames (%d)\n", ret);
2605        abort();
2606        return ret;
2607    }
2608
2609    /* copy FAT (with bdrv_read) */
2610    memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
2611
2612    /* recurse direntries from root (using bs->bdrv_read) */
2613    ret = commit_direntries(s, 0, -1);
2614    if (ret) {
2615        fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
2616        abort();
2617        return ret;
2618    }
2619
2620    ret = handle_commits(s);
2621    if (ret) {
2622        fprintf(stderr, "Error handling commits (%d)\n", ret);
2623        abort();
2624        return ret;
2625    }
2626
2627    ret = handle_deletes(s);
2628    if (ret) {
2629        fprintf(stderr, "Error deleting\n");
2630        abort();
2631        return ret;
2632    }
2633
2634    if (s->qcow->drv->bdrv_make_empty) {
2635        s->qcow->drv->bdrv_make_empty(s->qcow);
2636    }
2637
2638    memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
2639
2640DLOG(checkpoint());
2641    return 0;
2642}
2643
2644static int try_commit(BDRVVVFATState* s)
2645{
2646    vvfat_close_current_file(s);
2647DLOG(checkpoint());
2648    if(!is_consistent(s))
2649        return -1;
2650    return do_commit(s);
2651}
2652
2653static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
2654                    const uint8_t *buf, int nb_sectors)
2655{
2656    BDRVVVFATState *s = bs->opaque;
2657    int i, ret;
2658
2659DLOG(checkpoint());
2660
2661    /* Check if we're operating in read-only mode */
2662    if (s->qcow == NULL) {
2663        return -EACCES;
2664    }
2665
2666    vvfat_close_current_file(s);
2667
2668    /*
2669     * Some sanity checks:
2670     * - do not allow writing to the boot sector
2671     * - do not allow to write non-ASCII filenames
2672     */
2673
2674    if (sector_num < s->first_sectors_number)
2675        return -1;
2676
2677    for (i = sector2cluster(s, sector_num);
2678            i <= sector2cluster(s, sector_num + nb_sectors - 1);) {
2679        mapping_t* mapping = find_mapping_for_cluster(s, i);
2680        if (mapping) {
2681            if (mapping->read_only) {
2682                fprintf(stderr, "Tried to write to write-protected file %s\n",
2683                        mapping->path);
2684                return -1;
2685            }
2686
2687            if (mapping->mode & MODE_DIRECTORY) {
2688                int begin = cluster2sector(s, i);
2689                int end = begin + s->sectors_per_cluster, k;
2690                int dir_index;
2691                const direntry_t* direntries;
2692                long_file_name lfn;
2693
2694                lfn_init(&lfn);
2695
2696                if (begin < sector_num)
2697                    begin = sector_num;
2698                if (end > sector_num + nb_sectors)
2699                    end = sector_num + nb_sectors;
2700                dir_index  = mapping->dir_index +
2701                    0x10 * (begin - mapping->begin * s->sectors_per_cluster);
2702                direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
2703
2704                for (k = 0; k < (end - begin) * 0x10; k++) {
2705                    /* do not allow non-ASCII filenames */
2706                    if (parse_long_name(&lfn, direntries + k) < 0) {
2707                        fprintf(stderr, "Warning: non-ASCII filename\n");
2708                        return -1;
2709                    }
2710                    /* no access to the direntry of a read-only file */
2711                    else if (is_short_name(direntries+k) &&
2712                            (direntries[k].attributes & 1)) {
2713                        if (memcmp(direntries + k,
2714                                    array_get(&(s->directory), dir_index + k),
2715                                    sizeof(direntry_t))) {
2716                            fprintf(stderr, "Warning: tried to write to write-protected file\n");
2717                            return -1;
2718                        }
2719                    }
2720                }
2721            }
2722            i = mapping->end;
2723        } else
2724            i++;
2725    }
2726
2727    /*
2728     * Use qcow backend. Commit later.
2729     */
2730DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
2731    ret = bdrv_write(s->qcow, sector_num, buf, nb_sectors);
2732    if (ret < 0) {
2733        fprintf(stderr, "Error writing to qcow backend\n");
2734        return ret;
2735    }
2736
2737    for (i = sector2cluster(s, sector_num);
2738            i <= sector2cluster(s, sector_num + nb_sectors - 1); i++)
2739        if (i >= 0)
2740            s->used_clusters[i] |= USED_ALLOCATED;
2741
2742DLOG(checkpoint());
2743    /* TODO: add timeout */
2744    try_commit(s);
2745
2746DLOG(checkpoint());
2747    return 0;
2748}
2749
2750static coroutine_fn int vvfat_co_write(BlockDriverState *bs, int64_t sector_num,
2751                                       const uint8_t *buf, int nb_sectors)
2752{
2753    int ret;
2754    BDRVVVFATState *s = bs->opaque;
2755    qemu_co_mutex_lock(&s->lock);
2756    ret = vvfat_write(bs, sector_num, buf, nb_sectors);
2757    qemu_co_mutex_unlock(&s->lock);
2758    return ret;
2759}
2760
2761static int vvfat_is_allocated(BlockDriverState *bs,
2762        int64_t sector_num, int nb_sectors, int* n)
2763{
2764    BDRVVVFATState* s = bs->opaque;
2765    *n = s->sector_count - sector_num;
2766    if (*n > nb_sectors)
2767        *n = nb_sectors;
2768    else if (*n < 0)
2769        return 0;
2770    return 1;
2771}
2772
2773static int write_target_commit(BlockDriverState *bs, int64_t sector_num,
2774        const uint8_t* buffer, int nb_sectors) {
2775    BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
2776    return try_commit(s);
2777}
2778
2779static void write_target_close(BlockDriverState *bs) {
2780    BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
2781    bdrv_delete(s->qcow);
2782    g_free(s->qcow_filename);
2783}
2784
2785static BlockDriver vvfat_write_target = {
2786    .format_name        = "vvfat_write_target",
2787    .bdrv_write         = write_target_commit,
2788    .bdrv_close         = write_target_close,
2789};
2790
2791static int enable_write_target(BDRVVVFATState *s)
2792{
2793    BlockDriver *bdrv_qcow;
2794    QEMUOptionParameter *options;
2795    int ret;
2796    int size = sector2cluster(s, s->sector_count);
2797    s->used_clusters = calloc(size, 1);
2798
2799    array_init(&(s->commits), sizeof(commit_t));
2800
2801    s->qcow_filename = g_malloc(1024);
2802    get_tmp_filename(s->qcow_filename, 1024);
2803
2804    bdrv_qcow = bdrv_find_format("qcow");
2805    options = parse_option_parameters("", bdrv_qcow->create_options, NULL);
2806    set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512);
2807    set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:");
2808
2809    if (bdrv_create(bdrv_qcow, s->qcow_filename, options) < 0)
2810        return -1;
2811
2812    s->qcow = bdrv_new("");
2813    if (s->qcow == NULL) {
2814        return -1;
2815    }
2816
2817    ret = bdrv_open(s->qcow, s->qcow_filename,
2818            BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, bdrv_qcow);
2819    if (ret < 0) {
2820        return ret;
2821    }
2822
2823#ifndef _WIN32
2824    unlink(s->qcow_filename);
2825#endif
2826
2827    s->bs->backing_hd = calloc(sizeof(BlockDriverState), 1);
2828    s->bs->backing_hd->drv = &vvfat_write_target;
2829    s->bs->backing_hd->opaque = g_malloc(sizeof(void*));
2830    *(void**)s->bs->backing_hd->opaque = s;
2831
2832    return 0;
2833}
2834
2835static void vvfat_close(BlockDriverState *bs)
2836{
2837    BDRVVVFATState *s = bs->opaque;
2838
2839    vvfat_close_current_file(s);
2840    array_free(&(s->fat));
2841    array_free(&(s->directory));
2842    array_free(&(s->mapping));
2843    g_free(s->cluster_buffer);
2844
2845    if (s->qcow) {
2846        migrate_del_blocker(s->migration_blocker);
2847        error_free(s->migration_blocker);
2848    }
2849}
2850
2851static BlockDriver bdrv_vvfat = {
2852    .format_name        = "vvfat",
2853    .instance_size      = sizeof(BDRVVVFATState),
2854    .bdrv_file_open     = vvfat_open,
2855    .bdrv_read          = vvfat_co_read,
2856    .bdrv_write         = vvfat_co_write,
2857    .bdrv_close         = vvfat_close,
2858    .bdrv_is_allocated  = vvfat_is_allocated,
2859    .protocol_name      = "fat",
2860};
2861
2862static void bdrv_vvfat_init(void)
2863{
2864    bdrv_register(&bdrv_vvfat);
2865}
2866
2867block_init(bdrv_vvfat_init);
2868
2869#ifdef DEBUG
2870static void checkpoint(void) {
2871    assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2);
2872    check1(vvv);
2873    check2(vvv);
2874    assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY));
2875#if 0
2876    if (((direntry_t*)vvv->directory.pointer)[1].attributes != 0xf)
2877        fprintf(stderr, "Nonono!\n");
2878    mapping_t* mapping;
2879    direntry_t* direntry;
2880    assert(vvv->mapping.size >= vvv->mapping.item_size * vvv->mapping.next);
2881    assert(vvv->directory.size >= vvv->directory.item_size * vvv->directory.next);
2882    if (vvv->mapping.next<47)
2883        return;
2884    assert((mapping = array_get(&(vvv->mapping), 47)));
2885    assert(mapping->dir_index < vvv->directory.next);
2886    direntry = array_get(&(vvv->directory), mapping->dir_index);
2887    assert(!memcmp(direntry->name, "USB     H  ", 11) || direntry->name[0]==0);
2888#endif
2889}
2890#endif
2891