(linenum→info "unix/slp.c:2238")

qemu/0.9.1/block-vvfat.c

    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 <assert.h>
   28: #include "qemu-common.h"
   29: #include "block_int.h"
   30: 
   31: #ifndef S_IWGRP
   32: #define S_IWGRP 0
   33: #endif
   34: #ifndef S_IWOTH
   35: #define S_IWOTH 0
   36: #endif
   37: 
   38: /* TODO: add ":bootsector=blabla.img:" */
   39: /* LATER TODO: add automatic boot sector generation from
   40:     BOOTEASY.ASM and Ranish Partition Manager
   41:     Note that DOS assumes the system files to be the first files in the
   42:     file system (test if the boot sector still relies on that fact)! */
   43: /* MAYBE TODO: write block-visofs.c */
   44: /* TODO: call try_commit() only after a timeout */
   45: 
   46: /* #define DEBUG */
   47: 
   48: #ifdef DEBUG
   49: 
   50: #define DLOG(a) a
   51: 
   52: #undef stderr
   53: #define stderr STDERR
   54: FILE* stderr = NULL;
   55: 
   56: static void checkpoint();
   57: 
   58: #ifdef __MINGW32__
   59: void nonono(const char* file, int line, const char* msg) {
   60:     fprintf(stderr, "Nonono! %s:%d %s\n", file, line, msg);
   61:     exit(-5);
   62: }
   63: #undef assert
   64: #define assert(a) do {if (!(a)) nonono(__FILE__, __LINE__, #a);}while(0)
   65: #endif
   66: 
   67: #else
   68: 
   69: #define DLOG(a)
   70: 
   71: #endif
   72: 
   73: /* dynamic array functions */
   74: typedef struct array_t {
   75:     char* pointer;
   76:     unsigned int size,next,item_size;
   77: } array_t;
   78: 
   79: static inline void array_init(array_t* array,unsigned int item_size)
   80: {
   81:     array->pointer=0;
   82:     array->size=0;
   83:     array->next=0;
   84:     array->item_size=item_size;
   85: }
   86: 
   87: static inline void array_free(array_t* array)
   88: {
   89:     if(array->pointer)
   90:         free(array->pointer);
   91:     array->size=array->next=0;
   92: }
   93: 
   94: /* does not automatically grow */
   95: static inline void* array_get(array_t* array,unsigned int index) {
   96:     assert(index >= 0);
   97:     assert(index < array->next);
   98:     return array->pointer + index * array->item_size;
   99: }
  100: 
  101: static inline int array_ensure_allocated(array_t* array, int index)
  102: {
  103:     if((index + 1) * array->item_size > array->size) {
  104:         int new_size = (index + 32) * array->item_size;
  105:         array->pointer = realloc(array->pointer, new_size);
  106:         if (!array->pointer)
  107:             return -1;
  108:         array->size = new_size;
  109:         array->next = index + 1;
  110:     }
  111: 
  112:     return 0;
  113: }
  114: 
  115: static inline void* array_get_next(array_t* array) {
  116:     unsigned int next = array->next;
  117:     void* result;
  118: 
  119:     if (array_ensure_allocated(array, next) < 0)
  120:         return NULL;
  121: 
  122:     array->next = next + 1;
  123:     result = array_get(array, next);
  124: 
  125:     return result;
  126: }
  127: 
  128: static inline void* array_insert(array_t* array,unsigned int index,unsigned int count) {
  129:     if((array->next+count)*array->item_size>array->size) {
  130:         int increment=count*array->item_size;
  131:         array->pointer=realloc(array->pointer,array->size+increment);
  132:         if(!array->pointer)
  133:             return 0;
  134:         array->size+=increment;
  135:     }
  136:     memmove(array->pointer+(index+count)*array->item_size,
  137:                 array->pointer+index*array->item_size,
  138:                 (array->next-index)*array->item_size);
  139:     array->next+=count;
  140:     return array->pointer+index*array->item_size;
  141: }
  142: 
  143: /* this performs a "roll", so that the element which was at index_from becomes
  144:  * index_to, but the order of all other elements is preserved. */
  145: static inline int array_roll(array_t* array,int index_to,int index_from,int count)
  146: {
  147:     char* buf;
  148:     char* from;
  149:     char* to;
  150:     int is;
  151: 
  152:     if(!array ||
  153:             index_to<0 || index_to>=array->next ||
  154:             index_from<0 || index_from>=array->next)
  155:         return -1;
  156: 
  157:     if(index_to==index_from)
  158:         return 0;
  159: 
  160:     is=array->item_size;
  161:     from=array->pointer+index_from*is;
  162:     to=array->pointer+index_to*is;
  163:     buf=malloc(is*count);
  164:     memcpy(buf,from,is*count);
  165: 
  166:     if(index_to<index_from)
  167:         memmove(to+is*count,to,from-to);
  168:     else
  169:         memmove(from,from+is*count,to-from);
  170: 
  171:     memcpy(to,buf,is*count);
  172: 
  173:     free(buf);
  174: 
  175:     return 0;
  176: }
  177: 
  178: static inline int array_remove_slice(array_t* array,int index, int count)
  179: {
  180:     assert(index >=0);
  181:     assert(count > 0);
  182:     assert(index + count <= array->next);
  183:     if(array_roll(array,array->next-1,index,count))
  184:         return -1;
  185:     array->next -= count;
  186:     return 0;
  187: }
  188: 
  189: static int array_remove(array_t* array,int index)
  190: {
  191:     return array_remove_slice(array, index, 1);
  192: }
  193: 
  194: /* return the index for a given member */
  195: static int array_index(array_t* array, void* pointer)
  196: {
  197:     size_t offset = (char*)pointer - array->pointer;
  198:     assert(offset >= 0);
  199:     assert((offset % array->item_size) == 0);
  200:     assert(offset/array->item_size < array->next);
  201:     return offset/array->item_size;
  202: }
  203: 
  204: /* These structures are used to fake a disk and the VFAT filesystem.
  205:  * For this reason we need to use __attribute__((packed)). */
  206: 
  207: typedef struct bootsector_t {
  208:     uint8_t jump[3];
  209:     uint8_t name[8];
  210:     uint16_t sector_size;
  211:     uint8_t sectors_per_cluster;
  212:     uint16_t reserved_sectors;
  213:     uint8_t number_of_fats;
  214:     uint16_t root_entries;
  215:     uint16_t total_sectors16;
  216:     uint8_t media_type;
  217:     uint16_t sectors_per_fat;
  218:     uint16_t sectors_per_track;
  219:     uint16_t number_of_heads;
  220:     uint32_t hidden_sectors;
  221:     uint32_t total_sectors;
  222:     union {
  223:         struct {
  224:             uint8_t drive_number;
  225:             uint8_t current_head;
  226:             uint8_t signature;
  227:             uint32_t id;
  228:             uint8_t volume_label[11];
  229:         } __attribute__((packed)) fat16;
  230:         struct {
  231:             uint32_t sectors_per_fat;
  232:             uint16_t flags;
  233:             uint8_t major,minor;
  234:             uint32_t first_cluster_of_root_directory;
  235:             uint16_t info_sector;
  236:             uint16_t backup_boot_sector;
  237:             uint16_t ignored;
  238:         } __attribute__((packed)) fat32;
  239:     } u;
  240:     uint8_t fat_type[8];
  241:     uint8_t ignored[0x1c0];
  242:     uint8_t magic[2];
  243: } __attribute__((packed)) bootsector_t;
  244: 
  245: typedef struct {
  246:     uint8_t head;
  247:     uint8_t sector;
  248:     uint8_t cylinder;
  249: } mbr_chs_t;
  250: 
  251: typedef struct partition_t {
  252:     uint8_t attributes; /* 0x80 = bootable */
  253:     mbr_chs_t start_CHS;
  254:     uint8_t   fs_type; /* 0x1 = FAT12, 0x6 = FAT16, 0xe = FAT16_LBA, 0xb = FAT32, 0xc = FAT32_LBA */
  255:     mbr_chs_t end_CHS;
  256:     uint32_t start_sector_long;
  257:     uint32_t length_sector_long;
  258: } __attribute__((packed)) partition_t;
  259: 
  260: typedef struct mbr_t {
  261:     uint8_t ignored[0x1b8];
  262:     uint32_t nt_id;
  263:     uint8_t ignored2[2];
  264:     partition_t partition[4];
  265:     uint8_t magic[2];
  266: } __attribute__((packed)) mbr_t;
  267: 
  268: typedef struct direntry_t {
  269:     uint8_t name[8];
  270:     uint8_t extension[3];
  271:     uint8_t attributes;
  272:     uint8_t reserved[2];
  273:     uint16_t ctime;
  274:     uint16_t cdate;
  275:     uint16_t adate;
  276:     uint16_t begin_hi;
  277:     uint16_t mtime;
  278:     uint16_t mdate;
  279:     uint16_t begin;
  280:     uint32_t size;
  281: } __attribute__((packed)) direntry_t;
  282: 
  283: /* this structure are used to transparently access the files */
  284: 
  285: typedef struct mapping_t {
  286:     /* begin is the first cluster, end is the last+1 */
  287:     uint32_t begin,end;
  288:     /* as s->directory is growable, no pointer may be used here */
  289:     unsigned int dir_index;
  290:     /* the clusters of a file may be in any order; this points to the first */
  291:     int first_mapping_index;
  292:     union {
  293:         /* offset is
  294:          * - the offset in the file (in clusters) for a file, or
  295:          * - the next cluster of the directory for a directory, and
  296:          * - the address of the buffer for a faked entry
  297:          */
  298:         struct {
  299:             uint32_t offset;
  300:         } file;
  301:         struct {
  302:             int parent_mapping_index;
  303:             int first_dir_index;
  304:         } dir;
  305:     } info;
  306:     /* path contains the full path, i.e. it always starts with s->path */
  307:     char* path;
  308: 
  309:     enum { MODE_UNDEFINED = 0, MODE_NORMAL = 1, MODE_MODIFIED = 2,
  310:         MODE_DIRECTORY = 4, MODE_FAKED = 8,
  311:         MODE_DELETED = 16, MODE_RENAMED = 32 } mode;
  312:     int read_only;
  313: } mapping_t;
  314: 
  315: #ifdef DEBUG
  316: static void print_direntry(const struct direntry_t*);
  317: static void print_mapping(const struct mapping_t* mapping);
  318: #endif
  319: 
  320: /* here begins the real VVFAT driver */
  321: 
  322: typedef struct BDRVVVFATState {
  323:     BlockDriverState* bs; /* pointer to parent */
  324:     unsigned int first_sectors_number; /* 1 for a single partition, 0x40 for a disk with partition table */
  325:     unsigned char first_sectors[0x40*0x200];
  326: 
  327:     int fat_type; /* 16 or 32 */
  328:     array_t fat,directory,mapping;
  329: 
  330:     unsigned int cluster_size;
  331:     unsigned int sectors_per_cluster;
  332:     unsigned int sectors_per_fat;
  333:     unsigned int sectors_of_root_directory;
  334:     uint32_t last_cluster_of_root_directory;
  335:     unsigned int faked_sectors; /* how many sectors are faked before file data */
  336:     uint32_t sector_count; /* total number of sectors of the partition */
  337:     uint32_t cluster_count; /* total number of clusters of this partition */
  338:     uint32_t max_fat_value;
  339: 
  340:     int current_fd;
  341:     mapping_t* current_mapping;
  342:     unsigned char* cluster; /* points to current cluster */
  343:     unsigned char* cluster_buffer; /* points to a buffer to hold temp data */
  344:     unsigned int current_cluster;
  345: 
  346:     /* write support */
  347:     BlockDriverState* write_target;
  348:     char* qcow_filename;
  349:     BlockDriverState* qcow;
  350:     void* fat2;
  351:     char* used_clusters;
  352:     array_t commits;
  353:     const char* path;
  354:     int downcase_short_names;
  355: } BDRVVVFATState;
  356: 
  357: /* take the sector position spos and convert it to Cylinder/Head/Sector position
  358:  * if the position is outside the specified geometry, fill maximum value for CHS
  359:  * and return 1 to signal overflow.
  360:  */
  361: static int sector2CHS(BlockDriverState* bs, mbr_chs_t * chs, int spos){
  362:     int head,sector;
  363:     sector   = spos % (bs->secs);  spos/= bs->secs;
  364:     head     = spos % (bs->heads); spos/= bs->heads;
  365:     if(spos >= bs->cyls){
  366:         /* Overflow,
  367:         it happens if 32bit sector positions are used, while CHS is only 24bit.
  368:         Windows/Dos is said to take 1023/255/63 as nonrepresentable CHS */
  369:         chs->head     = 0xFF;
  370:         chs->sector   = 0xFF;
  371:         chs->cylinder = 0xFF;
  372:         return 1;
  373:     }
  374:     chs->head     = (uint8_t)head;
  375:     chs->sector   = (uint8_t)( (sector+1) | ((spos>>8)<<6) );
  376:     chs->cylinder = (uint8_t)spos;
  377:     return 0;
  378: }
  379: 
  380: static void init_mbr(BDRVVVFATState* s)
  381: {
  382:     /* TODO: if the files mbr.img and bootsect.img exist, use them */
  383:     mbr_t* real_mbr=(mbr_t*)s->first_sectors;
  384:     partition_t* partition=&(real_mbr->partition[0]);
  385:     int lba;
  386: 
  387:     memset(s->first_sectors,0,512);
  388: 
  389:     /* Win NT Disk Signature */
  390:     real_mbr->nt_id= cpu_to_le32(0xbe1afdfa);
  391: 
  392:     partition->attributes=0x80; /* bootable */
  393: 
  394:     /* LBA is used when partition is outside the CHS geometry */
  395:     lba = sector2CHS(s->bs, &partition->start_CHS, s->first_sectors_number-1);
  396:     lba|= sector2CHS(s->bs, &partition->end_CHS,   s->sector_count);
  397: 
  398:     /*LBA partitions are identified only by start/length_sector_long not by CHS*/
  399:     partition->start_sector_long =cpu_to_le32(s->first_sectors_number-1);
  400:     partition->length_sector_long=cpu_to_le32(s->sector_count - s->first_sectors_number+1);
  401: 
  402:     /* FAT12/FAT16/FAT32 */
  403:     /* DOS uses different types when partition is LBA,
  404:        probably to prevent older versions from using CHS on them */
  405:     partition->fs_type= s->fat_type==12 ? 0x1:
  406:                         s->fat_type==16 ? (lba?0xe:0x06):
  407:                          /*fat_tyoe==32*/ (lba?0xc:0x0b);
  408: 
  409:     real_mbr->magic[0]=0x55; real_mbr->magic[1]=0xaa;
  410: }
  411: 
  412: /* direntry functions */
  413: 
  414: /* dest is assumed to hold 258 bytes, and pads with 0xffff up to next multiple of 26 */
  415: static inline int short2long_name(char* dest,const char* src)
  416: {
  417:     int i;
  418:     int len;
  419:     for(i=0;i<129 && src[i];i++) {
  420:         dest[2*i]=src[i];
  421:         dest[2*i+1]=0;
  422:     }
  423:     len=2*i;
  424:     dest[2*i]=dest[2*i+1]=0;
  425:     for(i=2*i+2;(i%26);i++)
  426:         dest[i]=0xff;
  427:     return len;
  428: }
  429: 
  430: static inline direntry_t* create_long_filename(BDRVVVFATState* s,const char* filename)
  431: {
  432:     char buffer[258];
  433:     int length=short2long_name(buffer,filename),
  434:         number_of_entries=(length+25)/26,i;
  435:     direntry_t* entry;
  436: 
  437:     for(i=0;i<number_of_entries;i++) {
  438:         entry=array_get_next(&(s->directory));
  439:         entry->attributes=0xf;
  440:         entry->reserved[0]=0;
  441:         entry->begin=0;
  442:         entry->name[0]=(number_of_entries-i)|(i==0?0x40:0);
  443:     }
  444:     for(i=0;i<26*number_of_entries;i++) {
  445:         int offset=(i%26);
  446:         if(offset<10) offset=1+offset;
  447:         else if(offset<22) offset=14+offset-10;
  448:         else offset=28+offset-22;
  449:         entry=array_get(&(s->directory),s->directory.next-1-(i/26));
  450:         entry->name[offset]=buffer[i];
  451:     }
  452:     return array_get(&(s->directory),s->directory.next-number_of_entries);
  453: }
  454: 
  455: static char is_free(const direntry_t* direntry)
  456: {
  457:     /* return direntry->name[0]==0 ; */
  458:     return direntry->attributes == 0 || direntry->name[0]==0xe5;
  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:         chksum=(((chksum&0xfe)>>1)|((chksum&0x01)?0x80:0))
  517:             +(unsigned char)entry->name[i];
  518: 
  519:     return chksum;
  520: }
  521: 
  522: /* if return_time==0, this returns the fat_date, else the fat_time */
  523: static uint16_t fat_datetime(time_t time,int return_time) {
  524:     struct tm* t;
  525: #ifdef _WIN32
  526:     t=localtime(&time); /* this is not thread safe */
  527: #else
  528:     struct tm t1;
  529:     t=&t1;
  530:     localtime_r(&time,t);
  531: #endif
  532:     if(return_time)
  533:         return cpu_to_le16((t->tm_sec/2)|(t->tm_min<<5)|(t->tm_hour<<11));
  534:     return cpu_to_le16((t->tm_mday)|((t->tm_mon+1)<<5)|((t->tm_year-80)<<9));
  535: }
  536: 
  537: static inline void fat_set(BDRVVVFATState* s,unsigned int cluster,uint32_t value)
  538: {
  539:     if(s->fat_type==32) {
  540:         uint32_t* entry=array_get(&(s->fat),cluster);
  541:         *entry=cpu_to_le32(value);
  542:     } else if(s->fat_type==16) {
  543:         uint16_t* entry=array_get(&(s->fat),cluster);
  544:         *entry=cpu_to_le16(value&0xffff);
  545:     } else {
  546:         int offset = (cluster*3/2);
  547:         unsigned char* p = array_get(&(s->fat), offset);
  548:         switch (cluster&1) {
  549:         case 0:
  550:                 p[0] = value&0xff;
  551:                 p[1] = (p[1]&0xf0) | ((value>>8)&0xf);
  552:                 break;
  553: