Annotation of qemu/block/vvfat.c, revision 1.1.1.7

1.1       root        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"
1.1.1.7 ! root       30: #include "migration.h"
1.1       root       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
                     55: FILE* stderr = NULL;
                     56: 
                     57: static void checkpoint(void);
                     58: 
                     59: #ifdef __MINGW32__
                     60: void 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 */
                     75: typedef struct array_t {
                     76:     char* pointer;
                     77:     unsigned int size,next,item_size;
                     78: } array_t;
                     79: 
                     80: static 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: 
                     88: static inline void array_free(array_t* array)
                     89: {
1.1.1.7 ! root       90:     g_free(array->pointer);
1.1       root       91:     array->size=array->next=0;
                     92: }
                     93: 
                     94: /* does not automatically grow */
                     95: static inline void* array_get(array_t* array,unsigned int index) {
                     96:     assert(index < array->next);
                     97:     return array->pointer + index * array->item_size;
                     98: }
                     99: 
                    100: static inline int array_ensure_allocated(array_t* array, int index)
                    101: {
                    102:     if((index + 1) * array->item_size > array->size) {
                    103:        int new_size = (index + 32) * array->item_size;
1.1.1.7 ! root      104:        array->pointer = g_realloc(array->pointer, new_size);
1.1       root      105:        if (!array->pointer)
                    106:            return -1;
                    107:        array->size = new_size;
                    108:        array->next = index + 1;
                    109:     }
                    110: 
                    111:     return 0;
                    112: }
                    113: 
                    114: static inline void* array_get_next(array_t* array) {
                    115:     unsigned int next = array->next;
                    116:     void* result;
                    117: 
                    118:     if (array_ensure_allocated(array, next) < 0)
                    119:        return NULL;
                    120: 
                    121:     array->next = next + 1;
                    122:     result = array_get(array, next);
                    123: 
                    124:     return result;
                    125: }
                    126: 
                    127: static inline void* array_insert(array_t* array,unsigned int index,unsigned int count) {
                    128:     if((array->next+count)*array->item_size>array->size) {
                    129:        int increment=count*array->item_size;
1.1.1.7 ! root      130:        array->pointer=g_realloc(array->pointer,array->size+increment);
1.1       root      131:        if(!array->pointer)
                    132:             return NULL;
                    133:        array->size+=increment;
                    134:     }
                    135:     memmove(array->pointer+(index+count)*array->item_size,
                    136:                array->pointer+index*array->item_size,
                    137:                (array->next-index)*array->item_size);
                    138:     array->next+=count;
                    139:     return array->pointer+index*array->item_size;
                    140: }
                    141: 
                    142: /* this performs a "roll", so that the element which was at index_from becomes
                    143:  * index_to, but the order of all other elements is preserved. */
                    144: static inline int array_roll(array_t* array,int index_to,int index_from,int count)
                    145: {
                    146:     char* buf;
                    147:     char* from;
                    148:     char* to;
                    149:     int is;
                    150: 
                    151:     if(!array ||
                    152:            index_to<0 || index_to>=array->next ||
                    153:            index_from<0 || index_from>=array->next)
                    154:        return -1;
                    155: 
                    156:     if(index_to==index_from)
                    157:        return 0;
                    158: 
                    159:     is=array->item_size;
                    160:     from=array->pointer+index_from*is;
                    161:     to=array->pointer+index_to*is;
1.1.1.7 ! root      162:     buf=g_malloc(is*count);
1.1       root      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: 
1.1.1.7 ! root      172:     g_free(buf);
1.1       root      173: 
                    174:     return 0;
                    175: }
                    176: 
                    177: static inline int array_remove_slice(array_t* array,int index, int count)
                    178: {
                    179:     assert(index >=0);
                    180:     assert(count > 0);
                    181:     assert(index + count <= array->next);
                    182:     if(array_roll(array,array->next-1,index,count))
                    183:        return -1;
                    184:     array->next -= count;
                    185:     return 0;
                    186: }
                    187: 
                    188: static int array_remove(array_t* array,int index)
                    189: {
                    190:     return array_remove_slice(array, index, 1);
                    191: }
                    192: 
                    193: /* return the index for a given member */
                    194: static int array_index(array_t* array, void* pointer)
                    195: {
                    196:     size_t offset = (char*)pointer - array->pointer;
                    197:     assert((offset % array->item_size) == 0);
                    198:     assert(offset/array->item_size < array->next);
                    199:     return offset/array->item_size;
                    200: }
                    201: 
                    202: /* These structures are used to fake a disk and the VFAT filesystem.
1.1.1.7 ! root      203:  * For this reason we need to use QEMU_PACKED. */
1.1       root      204: 
                    205: typedef struct bootsector_t {
                    206:     uint8_t jump[3];
                    207:     uint8_t name[8];
                    208:     uint16_t sector_size;
                    209:     uint8_t sectors_per_cluster;
                    210:     uint16_t reserved_sectors;
                    211:     uint8_t number_of_fats;
                    212:     uint16_t root_entries;
                    213:     uint16_t total_sectors16;
                    214:     uint8_t media_type;
                    215:     uint16_t sectors_per_fat;
                    216:     uint16_t sectors_per_track;
                    217:     uint16_t number_of_heads;
                    218:     uint32_t hidden_sectors;
                    219:     uint32_t total_sectors;
                    220:     union {
                    221:         struct {
                    222:            uint8_t drive_number;
                    223:            uint8_t current_head;
                    224:            uint8_t signature;
                    225:            uint32_t id;
                    226:            uint8_t volume_label[11];
1.1.1.7 ! root      227:        } QEMU_PACKED fat16;
1.1       root      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;
1.1.1.7 ! root      236:        } QEMU_PACKED fat32;
1.1       root      237:     } u;
                    238:     uint8_t fat_type[8];
                    239:     uint8_t ignored[0x1c0];
                    240:     uint8_t magic[2];
1.1.1.7 ! root      241: } QEMU_PACKED bootsector_t;
1.1       root      242: 
                    243: typedef struct {
                    244:     uint8_t head;
                    245:     uint8_t sector;
                    246:     uint8_t cylinder;
                    247: } mbr_chs_t;
                    248: 
                    249: typedef struct partition_t {
                    250:     uint8_t attributes; /* 0x80 = bootable */
                    251:     mbr_chs_t start_CHS;
                    252:     uint8_t   fs_type; /* 0x1 = FAT12, 0x6 = FAT16, 0xe = FAT16_LBA, 0xb = FAT32, 0xc = FAT32_LBA */
                    253:     mbr_chs_t end_CHS;
                    254:     uint32_t start_sector_long;
                    255:     uint32_t length_sector_long;
1.1.1.7 ! root      256: } QEMU_PACKED partition_t;
1.1       root      257: 
                    258: typedef struct mbr_t {
                    259:     uint8_t ignored[0x1b8];
                    260:     uint32_t nt_id;
                    261:     uint8_t ignored2[2];
                    262:     partition_t partition[4];
                    263:     uint8_t magic[2];
1.1.1.7 ! root      264: } QEMU_PACKED mbr_t;
1.1       root      265: 
                    266: typedef struct direntry_t {
                    267:     uint8_t name[8];
                    268:     uint8_t extension[3];
                    269:     uint8_t attributes;
                    270:     uint8_t reserved[2];
                    271:     uint16_t ctime;
                    272:     uint16_t cdate;
                    273:     uint16_t adate;
                    274:     uint16_t begin_hi;
                    275:     uint16_t mtime;
                    276:     uint16_t mdate;
                    277:     uint16_t begin;
                    278:     uint32_t size;
1.1.1.7 ! root      279: } QEMU_PACKED direntry_t;
1.1       root      280: 
                    281: /* this structure are used to transparently access the files */
                    282: 
                    283: typedef struct mapping_t {
                    284:     /* begin is the first cluster, end is the last+1 */
                    285:     uint32_t begin,end;
                    286:     /* as s->directory is growable, no pointer may be used here */
                    287:     unsigned int dir_index;
                    288:     /* the clusters of a file may be in any order; this points to the first */
                    289:     int first_mapping_index;
                    290:     union {
                    291:        /* offset is
                    292:         * - the offset in the file (in clusters) for a file, or
                    293:         * - the next cluster of the directory for a directory, and
                    294:         * - the address of the buffer for a faked entry
                    295:         */
                    296:        struct {
                    297:            uint32_t offset;
                    298:        } file;
                    299:        struct {
                    300:            int parent_mapping_index;
                    301:            int first_dir_index;
                    302:        } dir;
                    303:     } info;
                    304:     /* path contains the full path, i.e. it always starts with s->path */
                    305:     char* path;
                    306: 
                    307:     enum { MODE_UNDEFINED = 0, MODE_NORMAL = 1, MODE_MODIFIED = 2,
                    308:        MODE_DIRECTORY = 4, MODE_FAKED = 8,
                    309:        MODE_DELETED = 16, MODE_RENAMED = 32 } mode;
                    310:     int read_only;
                    311: } mapping_t;
                    312: 
                    313: #ifdef DEBUG
                    314: static void print_direntry(const struct direntry_t*);
                    315: static void print_mapping(const struct mapping_t* mapping);
                    316: #endif
                    317: 
                    318: /* here begins the real VVFAT driver */
                    319: 
                    320: typedef struct BDRVVVFATState {
1.1.1.7 ! root      321:     CoMutex lock;
1.1       root      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;
1.1.1.7 ! root      354: 
        !           355:     Error *migration_blocker;
1.1       root      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:  */
                    362: static 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: 
                    381: static 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;
1.1.1.2   root      385:     partition_t* partition = &(real_mbr->partition[0]);
1.1       root      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 */
                    416: static 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: 
                    431: static 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: 
                    456: static char is_free(const direntry_t* direntry)
                    457: {
                    458:     return direntry->name[0]==0xe5 || direntry->name[0]==0x00;
                    459: }
                    460: 
                    461: static char is_volume_label(const direntry_t* direntry)
                    462: {
                    463:     return direntry->attributes == 0x28;
                    464: }
                    465: 
                    466: static char is_long_name(const direntry_t* direntry)
                    467: {
                    468:     return direntry->attributes == 0xf;
                    469: }
                    470: 
                    471: static char is_short_name(const direntry_t* direntry)
                    472: {
                    473:     return !is_volume_label(direntry) && !is_long_name(direntry)
                    474:        && !is_free(direntry);
                    475: }
                    476: 
                    477: static char is_directory(const direntry_t* direntry)
                    478: {
                    479:     return direntry->attributes & 0x10 && direntry->name[0] != 0xe5;
                    480: }
                    481: 
                    482: static inline char is_dot(const direntry_t* direntry)
                    483: {
                    484:     return is_short_name(direntry) && direntry->name[0] == '.';
                    485: }
                    486: 
                    487: static char is_file(const direntry_t* direntry)
                    488: {
                    489:     return is_short_name(direntry) && !is_directory(direntry);
                    490: }
                    491: 
                    492: static inline uint32_t begin_of_direntry(const direntry_t* direntry)
                    493: {
                    494:     return le16_to_cpu(direntry->begin)|(le16_to_cpu(direntry->begin_hi)<<16);
                    495: }
                    496: 
                    497: static inline uint32_t filesize_of_direntry(const direntry_t* direntry)
                    498: {
                    499:     return le32_to_cpu(direntry->size);
                    500: }
                    501: 
                    502: static void set_begin_of_direntry(direntry_t* direntry, uint32_t begin)
                    503: {
                    504:     direntry->begin = cpu_to_le16(begin & 0xffff);
                    505:     direntry->begin_hi = cpu_to_le16((begin >> 16) & 0xffff);
                    506: }
                    507: 
                    508: /* fat functions */
                    509: 
                    510: static inline uint8_t fat_chksum(const direntry_t* entry)
                    511: {
                    512:     uint8_t chksum=0;
                    513:     int i;
                    514: 
                    515:     for(i=0;i<11;i++) {
                    516:         unsigned char c;
                    517: 
1.1.1.5   root      518:         c = (i < 8) ? entry->name[i] : entry->extension[i-8];
1.1       root      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 */
                    526: static 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;
1.1.1.2   root      532:     t = &t1;
1.1       root      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: 
                    540: static 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: 
                    564: static 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: 
                    578: static 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: 
                    585: static 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! */
                    609: static 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:  */
                    697: static 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: 
1.1.1.7 ! root      734:        buffer=(char*)g_malloc(length);
1.1       root      735:        snprintf(buffer,length,"%s/%s",dirname,entry->d_name);
                    736: 
                    737:        if(stat(buffer,&st)<0) {
1.1.1.7 ! root      738:             g_free(buffer);
1.1       root      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);
1.1.1.7 ! root      761:             g_free(buffer);
1.1.1.6   root      762:             closedir(dir);
1.1       root      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);
1.1.1.7 ! root      805:        s->directory.next = ROOT_ENTRIES;
1.1       root      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: 
                    822: static inline uint32_t sector2cluster(BDRVVVFATState* s,off_t sector_num)
                    823: {
                    824:     return (sector_num-s->faked_sectors)/s->sectors_per_cluster;
                    825: }
                    826: 
                    827: static inline off_t cluster2sector(BDRVVVFATState* s, uint32_t cluster_num)
                    828: {
                    829:     return s->faked_sectors + s->sectors_per_cluster * cluster_num;
                    830: }
                    831: 
                    832: static 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;
1.1.1.7 ! root      843:     s->cluster_buffer=g_malloc(s->cluster_size);
1.1       root      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 */
1.1.1.4   root      862:        memcpy(entry->name,"QEMU VVF",8);
                    863:        memcpy(entry->extension,"AT ",3);
1.1       root      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;
1.1.1.7 ! root      877:     mapping->path = g_strdup(dirname);
1.1       root      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) {
1.1.1.7 ! root      922:            fprintf(stderr,"Directory does not fit in FAT%d (capacity %.2f MB)\n",
        !           923:                    s->fat_type, s->sector_count / 2000.0);
1.1       root      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);
1.1.1.7 ! root      957:     bootsector->media_type=(s->first_sectors_number>1?0xf8:0xf0); /* media descriptor (f8=hd, f0=3.5 fd)*/
1.1       root      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 */
1.1.1.7 ! root      966:     bootsector->u.fat16.drive_number=s->first_sectors_number==1?0:0x80; /* fda=0, hda=0x80 */
1.1       root      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
                    979: static BDRVVVFATState *vvv = NULL;
                    980: #endif
                    981: 
                    982: static int enable_write_target(BDRVVVFATState *s);
                    983: static int is_consistent(BDRVVVFATState *s);
                    984: 
                    985: static 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: 
                    994: DLOG(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: 
1.1.1.7 ! root     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: 
1.1       root     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);
1.1.1.7 ! root     1072:     else {
        !          1073:         /* MS-DOS does not like to know about CHS (?). */
1.1       root     1074:        bs->heads = bs->cyls = bs->secs = 0;
1.1.1.7 ! root     1075:     }
1.1       root     1076: 
                   1077:     //    assert(is_consistent(s));
1.1.1.7 ! root     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: 
1.1       root     1088:     return 0;
                   1089: }
                   1090: 
                   1091: static 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:  */
                   1106: static inline int find_mapping_for_cluster_aux(BDRVVVFATState* s,int cluster_num,int index1,int index2)
                   1107: {
                   1108:     while(1) {
1.1.1.5   root     1109:         int index3;
1.1       root     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: 
                   1133: static 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: 
                   1146: static 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: 
                   1163: static 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;
                   1180: read_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
                   1212: static void print_direntry(const direntry_t* direntry)
                   1213: {
                   1214:     int j = 0;
                   1215:     char buffer[1024];
                   1216: 
1.1.1.5   root     1217:     fprintf(stderr, "direntry %p: ", direntry);
1.1       root     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: 
                   1244: static void print_mapping(const mapping_t* mapping)
                   1245: {
1.1.1.5   root     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: 
1.1       root     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: 
                   1258: static 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++) {
1.1.1.7 ! root     1265:        if (sector_num >= bs->total_sectors)
1.1       root     1266:           return -1;
                   1267:        if (s->qcow) {
                   1268:            int n;
1.1.1.7 ! root     1269:             if (bdrv_is_allocated(s->qcow, sector_num, nb_sectors-i, &n)) {
1.1       root     1270: DLOG(fprintf(stderr, "sectors %d+%d allocated\n", (int)sector_num, n));
1.1.1.7 ! root     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:             }
1.1       root     1278: DLOG(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;
1.1.1.7 ! root     1291:            if(cluster_num > s->cluster_count || read_cluster(s, cluster_num) != 0) {
1.1       root     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: 
1.1.1.7 ! root     1302: static 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: 
1.1       root     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: 
                   1335: typedef 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: 
                   1349: static void clear_commits(BDRVVVFATState* s)
                   1350: {
                   1351:     int i;
                   1352: DLOG(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);
1.1.1.7 ! root     1358:             g_free(commit->path);
1.1       root     1359:        } else
                   1360:            assert(commit->path == NULL);
                   1361:     }
                   1362:     s->commits.next = 0;
                   1363: }
                   1364: 
                   1365: static 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: 
                   1374: static 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: 
                   1384: static 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: 
                   1393: static 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: 
                   1401: typedef 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: 
                   1412: static 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 */
                   1419: static 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 */
                   1462: static 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: 
                   1500: static 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: 
                   1522: static 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++)
1.1.1.7 ! root     1531:        was_modified = bdrv_is_allocated(s->qcow,
1.1       root     1532:                cluster2sector(s, cluster_num) + i, 1, &dummy);
                   1533: 
                   1534:     return was_modified;
                   1535: }
                   1536: 
                   1537: static 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:  */
                   1553: typedef 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:  */
                   1567: static 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))
1.1.1.7 ! root     1621:                schedule_rename(s, cluster_num, g_strdup(path));
1.1       root     1622:        } else if (is_file(direntry))
                   1623:            /* new file */
1.1.1.7 ! root     1624:            schedule_new_file(s, g_strdup(path), cluster_num);
1.1       root     1625:        else {
1.1.1.5   root     1626:             abort();
1.1       root     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 */
1.1.1.5   root     1647:                         abort();
1.1       root     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) {
1.1.1.5   root     1659:                         abort();
1.1       root     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);
1.1.1.7 ! root     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:                 }
1.1       root     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:  */
                   1714: static int check_directory_consistency(BDRVVVFATState *s,
                   1715:        int cluster_num, const char* path)
                   1716: {
                   1717:     int ret = 0;
1.1.1.7 ! root     1718:     unsigned char* cluster = g_malloc(s->cluster_size);
1.1       root     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);
1.1.1.7 ! root     1724:     char path2[PATH_MAX + 1];
1.1       root     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))
1.1.1.7 ! root     1741:            schedule_rename(s, cluster_num, g_strdup(path));
1.1       root     1742:     } else
                   1743:        /* new directory */
1.1.1.7 ! root     1744:        schedule_mkdir(s, cluster_num, g_strdup(path));
1.1       root     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: 
                   1759: DLOG(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:
1.1.1.7 ! root     1765:             g_free(cluster);
1.1       root     1766:            return 0;
                   1767:        }
                   1768: 
                   1769:        for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
                   1770:            int cluster_count = 0;
                   1771: 
1.1.1.7 ! root     1772: DLOG(fprintf(stderr, "check direntry %d:\n", i); print_direntry(direntries + i));
1.1       root     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
1.1.1.5   root     1825:                 abort(); /* cluster_count = 0; */
1.1       root     1826: 
                   1827:            ret += cluster_count;
                   1828:        }
                   1829: 
                   1830:        cluster_num = modified_fat_get(s, cluster_num);
                   1831:     } while(!fat_eof(s, cluster_num));
                   1832: 
1.1.1.7 ! root     1833:     g_free(cluster);
1.1       root     1834:     return ret;
                   1835: }
                   1836: 
                   1837: /* returns 1 on success */
                   1838: static int is_consistent(BDRVVVFATState* s)
                   1839: {
                   1840:     int i, check;
                   1841:     int used_clusters_count = 0;
                   1842: 
                   1843: DLOG(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;
1.1.1.7 ! root     1859:        s->fat2 = g_malloc(size);
1.1       root     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: 
                   1912: static 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 */
                   1931: static 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: 
                   1960: DLOG(mapping_t* next_mapping;
                   1961: assert(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: 
                   1972: static 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 */
1.1.1.7 ! root     1978:     if (mapping->first_mapping_index < 0) {
        !          1979:         g_free(mapping->path);
        !          1980:     }
1.1       root     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: 
                   1995: static 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: 
                   2008: static 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: 
                   2022: static 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:  */
                   2037: static 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: 
                   2114: static 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: 
                   2128: DLOG(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 */
                   2194: static 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);
1.1.1.7 ! root     2202:     char* cluster = g_malloc(s->cluster_size);
1.1       root     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);
1.1.1.7 ! root     2216:         g_free(cluster);
1.1       root     2217:        return fd;
                   2218:     }
1.1.1.7 ! root     2219:     if (offset > 0) {
        !          2220:         if (lseek(fd, offset, SEEK_SET) != offset) {
        !          2221:             g_free(cluster);
        !          2222:             return -3;
        !          2223:         }
        !          2224:     }
1.1       root     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: 
1.1.1.7 ! root     2240:         if (ret < 0) {
        !          2241:             g_free(cluster);
        !          2242:             return ret;
        !          2243:         }
1.1       root     2244: 
1.1.1.7 ! root     2245:         if (write(fd, cluster, rest_size) < 0) {
        !          2246:             g_free(cluster);
        !          2247:             return -2;
        !          2248:         }
1.1       root     2249: 
                   2250:        offset += rest_size;
                   2251:        c = c1;
                   2252:     }
                   2253: 
1.1.1.4   root     2254:     if (ftruncate(fd, size)) {
                   2255:         perror("ftruncate()");
                   2256:         close(fd);
1.1.1.7 ! root     2257:         g_free(cluster);
1.1.1.4   root     2258:         return -4;
                   2259:     }
1.1       root     2260:     close(fd);
1.1.1.7 ! root     2261:     g_free(cluster);
1.1       root     2262: 
                   2263:     return commit_mappings(s, first_cluster, dir_index);
                   2264: }
                   2265: 
                   2266: #ifdef DEBUG
                   2267: /* test, if all mappings point to valid direntries */
                   2268: static 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 */
                   2288: static 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: 
                   2335: static 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);
1.1.1.7 ! root     2377:                            char* new_path = g_malloc(l + diff + 1);
1.1       root     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: 
1.1.1.7 ! root     2393:             g_free(old_path);
1.1       root     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:  */
                   2446: static 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:
1.1.1.5   root     2456:             abort();
1.1       root     2457:            fail = -2;
                   2458:            break;
                   2459:        case ACTION_WRITEOUT: {
1.1.1.5   root     2460: #ifndef NDEBUG
                   2461:             /* these variables are only used by assert() below */
1.1       root     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);
1.1.1.5   root     2466: #endif
1.1       root     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:
1.1.1.5   root     2517:             abort();
1.1       root     2518:        }
                   2519:     }
                   2520:     if (i > 0 && array_remove_slice(&(s->commits), 0, i))
                   2521:        return -1;
                   2522:     return fail;
                   2523: }
                   2524: 
                   2525: static 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:  */
                   2592: static 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);
1.1.1.5   root     2605:         abort();
1.1       root     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);
1.1.1.5   root     2616:         abort();
1.1       root     2617:        return ret;
                   2618:     }
                   2619: 
                   2620:     ret = handle_commits(s);
                   2621:     if (ret) {
                   2622:        fprintf(stderr, "Error handling commits (%d)\n", ret);
1.1.1.5   root     2623:         abort();
1.1       root     2624:        return ret;
                   2625:     }
                   2626: 
                   2627:     ret = handle_deletes(s);
                   2628:     if (ret) {
                   2629:        fprintf(stderr, "Error deleting\n");
1.1.1.5   root     2630:         abort();
1.1       root     2631:        return ret;
                   2632:     }
                   2633: 
1.1.1.7 ! root     2634:     if (s->qcow->drv->bdrv_make_empty) {
        !          2635:         s->qcow->drv->bdrv_make_empty(s->qcow);
        !          2636:     }
1.1       root     2637: 
                   2638:     memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
                   2639: 
                   2640: DLOG(checkpoint());
                   2641:     return 0;
                   2642: }
                   2643: 
                   2644: static int try_commit(BDRVVVFATState* s)
                   2645: {
                   2646:     vvfat_close_current_file(s);
                   2647: DLOG(checkpoint());
                   2648:     if(!is_consistent(s))
                   2649:        return -1;
                   2650:     return do_commit(s);
                   2651: }
                   2652: 
                   2653: static 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: 
                   2659: DLOG(checkpoint());
                   2660: 
1.1.1.5   root     2661:     /* Check if we're operating in read-only mode */
                   2662:     if (s->qcow == NULL) {
                   2663:         return -EACCES;
                   2664:     }
                   2665: 
1.1       root     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:      */
                   2730: DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
1.1.1.7 ! root     2731:     ret = bdrv_write(s->qcow, sector_num, buf, nb_sectors);
1.1       root     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: 
                   2742: DLOG(checkpoint());
                   2743:     /* TODO: add timeout */
                   2744:     try_commit(s);
                   2745: 
                   2746: DLOG(checkpoint());
                   2747:     return 0;
                   2748: }
                   2749: 
1.1.1.7 ! root     2750: static 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: 
1.1       root     2761: static 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: 
                   2773: static int write_target_commit(BlockDriverState *bs, int64_t sector_num,
                   2774:        const uint8_t* buffer, int nb_sectors) {
1.1.1.5   root     2775:     BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
1.1       root     2776:     return try_commit(s);
                   2777: }
                   2778: 
                   2779: static void write_target_close(BlockDriverState *bs) {
1.1.1.5   root     2780:     BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
1.1       root     2781:     bdrv_delete(s->qcow);
1.1.1.7 ! root     2782:     g_free(s->qcow_filename);
1.1       root     2783: }
                   2784: 
                   2785: static BlockDriver vvfat_write_target = {
                   2786:     .format_name        = "vvfat_write_target",
                   2787:     .bdrv_write         = write_target_commit,
                   2788:     .bdrv_close         = write_target_close,
                   2789: };
                   2790: 
                   2791: static int enable_write_target(BDRVVVFATState *s)
                   2792: {
                   2793:     BlockDriver *bdrv_qcow;
                   2794:     QEMUOptionParameter *options;
1.1.1.5   root     2795:     int ret;
1.1       root     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: 
1.1.1.7 ! root     2801:     s->qcow_filename = g_malloc(1024);
1.1       root     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;
1.1.1.5   root     2811: 
1.1       root     2812:     s->qcow = bdrv_new("");
1.1.1.5   root     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:     }
1.1       root     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;
1.1.1.7 ! root     2829:     s->bs->backing_hd->opaque = g_malloc(sizeof(void*));
1.1.1.5   root     2830:     *(void**)s->bs->backing_hd->opaque = s;
1.1       root     2831: 
                   2832:     return 0;
                   2833: }
                   2834: 
                   2835: static 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));
1.1.1.7 ! root     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:     }
1.1       root     2849: }
                   2850: 
                   2851: static BlockDriver bdrv_vvfat = {
                   2852:     .format_name       = "vvfat",
                   2853:     .instance_size     = sizeof(BDRVVVFATState),
1.1.1.5   root     2854:     .bdrv_file_open    = vvfat_open,
1.1.1.7 ! root     2855:     .bdrv_read          = vvfat_co_read,
        !          2856:     .bdrv_write         = vvfat_co_write,
1.1       root     2857:     .bdrv_close                = vvfat_close,
                   2858:     .bdrv_is_allocated = vvfat_is_allocated,
                   2859:     .protocol_name     = "fat",
                   2860: };
                   2861: 
                   2862: static void bdrv_vvfat_init(void)
                   2863: {
                   2864:     bdrv_register(&bdrv_vvfat);
                   2865: }
                   2866: 
                   2867: block_init(bdrv_vvfat_init);
                   2868: 
                   2869: #ifdef DEBUG
                   2870: static 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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.