} QEMU_PACKED mbr_t;
typedef struct direntry_t {
- uint8_t name[8];
- uint8_t extension[3];
+ uint8_t name[8 + 3];
uint8_t attributes;
uint8_t reserved[2];
uint16_t ctime;
uint8_t chksum=0;
int i;
- for(i=0;i<11;i++) {
- unsigned char c;
-
- c = (i < 8) ? entry->name[i] : entry->extension[i-8];
- chksum=(((chksum&0xfe)>>1)|((chksum&0x01)?0x80:0)) + c;
+ for (i = 0; i < ARRAY_SIZE(entry->name); i++) {
+ chksum = (((chksum & 0xfe) >> 1) |
+ ((chksum & 0x01) ? 0x80 : 0)) + entry->name[i];
}
return chksum;
if(is_dot) {
entry=array_get_next(&(s->directory));
- memset(entry->name,0x20,11);
+ memset(entry->name, 0x20, sizeof(entry->name));
memcpy(entry->name,filename,strlen(filename));
return entry;
}
i = 8;
entry=array_get_next(&(s->directory));
- memset(entry->name,0x20,11);
+ memset(entry->name, 0x20, sizeof(entry->name));
memcpy(entry->name, filename, i);
- if(j > 0)
- for (i = 0; i < 3 && filename[j+1+i]; i++)
- entry->extension[i] = filename[j+1+i];
+ if (j > 0) {
+ for (i = 0; i < 3 && filename[j + 1 + i]; i++) {
+ entry->name[8 + i] = filename[j + 1 + i];
+ }
+ }
/* upcase & remove unwanted characters */
for(i=10;i>=0;i--) {
s->current_mapping->path=buffer;
s->current_mapping->read_only =
(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0;
- }
+ } else {
+ g_free(buffer);
+ }
}
closedir(dir);
}
static int init_directories(BDRVVVFATState* s,
- const char *dirname, int heads, int secs)
+ const char *dirname, int heads, int secs,
+ Error **errp)
{
bootsector_t* bootsector;
mapping_t* mapping;
{
direntry_t* entry=array_get_next(&(s->directory));
entry->attributes=0x28; /* archive | volume label */
- memcpy(entry->name,"QEMU VVF",8);
- memcpy(entry->extension,"AT ",3);
+ memcpy(entry->name, "QEMU VVFAT ", sizeof(entry->name));
}
/* Now build FAT, and write back information into directory */
if (mapping->mode & MODE_DIRECTORY) {
mapping->begin = cluster;
if(read_directory(s, i)) {
- fprintf(stderr, "Could not read directory %s\n",
- mapping->path);
+ error_setg(errp, "Could not read directory %s",
+ mapping->path);
return -1;
}
mapping = array_get(&(s->mapping), i);
cluster = mapping->end;
if(cluster > s->cluster_count) {
- fprintf(stderr,"Directory does not fit in FAT%d (capacity %.2f MB)\n",
- s->fat_type, s->sector_count / 2000.0);
- return -EINVAL;
+ error_setg(errp,
+ "Directory does not fit in FAT%d (capacity %.2f MB)",
+ s->fat_type, s->sector_count / 2000.0);
+ return -1;
}
/* fix fat for entry */
static BDRVVVFATState *vvv = NULL;
#endif
-static int enable_write_target(BDRVVVFATState *s);
+static int enable_write_target(BDRVVVFATState *s, Error **errp);
static int is_consistent(BDRVVVFATState *s);
static void vvfat_rebind(BlockDriverState *bs)
qdict_put(options, "rw", qbool_from_int(rw));
}
-static int vvfat_open(BlockDriverState *bs, QDict *options, int flags)
+static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
+ Error **errp)
{
BDRVVVFATState *s = bs->opaque;
int cyls, heads, secs;
setbuf(stderr, NULL);
})
- opts = qemu_opts_create_nofail(&runtime_opts);
+ opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err);
- if (error_is_set(&local_err)) {
- qerror_report_err(local_err);
- error_free(local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
ret = -EINVAL;
goto fail;
}
dirname = qemu_opt_get(opts, "dir");
if (!dirname) {
- qerror_report(ERROR_CLASS_GENERIC_ERROR, "vvfat block driver requires "
- "a 'dir' option");
+ error_setg(errp, "vvfat block driver requires a 'dir' option");
ret = -EINVAL;
goto fail;
}
if (!s->fat_type) {
s->fat_type = 16;
}
+ s->first_sectors_number = 0x40;
cyls = s->fat_type == 12 ? 64 : 1024;
heads = 16;
secs = 63;
case 12:
break;
default:
- qerror_report(ERROR_CLASS_GENERIC_ERROR, "Valid FAT types are only "
- "12, 16 and 32");
+ error_setg(errp, "Valid FAT types are only 12, 16 and 32");
ret = -EINVAL;
goto fail;
}
s->current_cluster=0xffffffff;
- s->first_sectors_number=0x40;
/* read only is the default for safety */
bs->read_only = 1;
s->qcow = s->write_target = NULL;
s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1);
if (qemu_opt_get_bool(opts, "rw", false)) {
- if (enable_write_target(s)) {
- ret = -EIO;
+ ret = enable_write_target(s, errp);
+ if (ret < 0) {
goto fail;
}
bs->read_only = 0;
bs->total_sectors = cyls * heads * secs;
- if (init_directories(s, dirname, heads, secs)) {
+ if (init_directories(s, dirname, heads, secs, errp)) {
ret = -EIO;
goto fail;
}
lfn->name[i] = direntry->name[i];
}
- for (j = 2; j >= 0 && direntry->extension[j] == ' '; j--);
+ for (j = 2; j >= 0 && direntry->name[8 + j] == ' '; j--) {
+ }
if (j >= 0) {
lfn->name[i++] = '.';
lfn->name[i + j + 1] = '\0';
for (;j >= 0; j--) {
- if (direntry->extension[j] <= ' ' || direntry->extension[j] > 0x7f)
- return -2;
- else if (s->downcase_short_names)
- lfn->name[i + j] = qemu_tolower(direntry->extension[j]);
- else
- lfn->name[i + j] = direntry->extension[j];
+ uint8_t c = direntry->name[8 + j];
+ if (c <= ' ' || c > 0x7f) {
+ return -2;
+ } else if (s->downcase_short_names) {
+ lfn->name[i + j] = qemu_tolower(c);
+ } else {
+ lfn->name[i + j] = c;
+ }
}
} else
lfn->name[i + j + 1] = '\0';
if (s->used_clusters[cluster_num] & USED_ANY) {
fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
- return 0;
+ goto fail;
}
s->used_clusters[cluster_num] = USED_DIRECTORY;
return ret;
}
-static int coroutine_fn vvfat_co_is_allocated(BlockDriverState *bs,
+static int64_t coroutine_fn vvfat_co_get_block_status(BlockDriverState *bs,
int64_t sector_num, int nb_sectors, int* n)
{
BDRVVVFATState* s = bs->opaque;
*n = s->sector_count - sector_num;
- if (*n > nb_sectors)
- *n = nb_sectors;
- else if (*n < 0)
- return 0;
- return 1;
+ if (*n > nb_sectors) {
+ *n = nb_sectors;
+ } else if (*n < 0) {
+ return 0;
+ }
+ return BDRV_BLOCK_DATA;
}
static int write_target_commit(BlockDriverState *bs, int64_t sector_num,
static void write_target_close(BlockDriverState *bs) {
BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
- bdrv_delete(s->qcow);
+ bdrv_unref(s->qcow);
g_free(s->qcow_filename);
}
.bdrv_close = write_target_close,
};
-static int enable_write_target(BDRVVVFATState *s)
+static int enable_write_target(BDRVVVFATState *s, Error **errp)
{
BlockDriver *bdrv_qcow;
QEMUOptionParameter *options;
s->qcow_filename = g_malloc(1024);
ret = get_tmp_filename(s->qcow_filename, 1024);
if (ret < 0) {
- g_free(s->qcow_filename);
- s->qcow_filename = NULL;
- return ret;
+ error_setg_errno(errp, -ret, "can't create temporary file");
+ goto err;
}
bdrv_qcow = bdrv_find_format("qcow");
set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512);
set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:");
- if (bdrv_create(bdrv_qcow, s->qcow_filename, options) < 0)
- return -1;
-
- s->qcow = bdrv_new("");
- if (s->qcow == NULL) {
- return -1;
+ ret = bdrv_create(bdrv_qcow, s->qcow_filename, options, errp);
+ free_option_parameters(options);
+ if (ret < 0) {
+ goto err;
}
- ret = bdrv_open(s->qcow, s->qcow_filename, NULL,
- BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, bdrv_qcow);
+ s->qcow = NULL;
+ ret = bdrv_open(&s->qcow, s->qcow_filename, NULL, NULL,
+ BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH,
+ bdrv_qcow, errp);
if (ret < 0) {
- return ret;
+ goto err;
}
#ifndef _WIN32
unlink(s->qcow_filename);
#endif
- s->bs->backing_hd = calloc(sizeof(BlockDriverState), 1);
+ bdrv_set_backing_hd(s->bs, bdrv_new("", &error_abort));
s->bs->backing_hd->drv = &vvfat_write_target;
s->bs->backing_hd->opaque = g_malloc(sizeof(void*));
*(void**)s->bs->backing_hd->opaque = s;
return 0;
+
+err:
+ g_free(s->qcow_filename);
+ s->qcow_filename = NULL;
+ return ret;
}
static void vvfat_close(BlockDriverState *bs)
.bdrv_read = vvfat_co_read,
.bdrv_write = vvfat_co_write,
- .bdrv_co_is_allocated = vvfat_co_is_allocated,
+ .bdrv_co_get_block_status = vvfat_co_get_block_status,
};
static void bdrv_vvfat_init(void)