[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v5 09/12] VMDK: open/read/write for monolithicFl
From: |
Stefan Hajnoczi |
Subject: |
Re: [Qemu-devel] [PATCH v5 09/12] VMDK: open/read/write for monolithicFlat image |
Date: |
Wed, 29 Jun 2011 16:57:41 +0100 |
On Tue, Jun 28, 2011 at 2:32 AM, Fam Zheng <address@hidden> wrote:
> +/* find an option value out of descriptor file */
> +static int vmdk_parse_description(const char *desc, const char *opt_name,
> + char *buf, int buf_size)
> +{
> + char *opt_pos, *opt_end;
> + const char *end = desc + strlen(desc);
> +
> + opt_pos = strstr(desc, opt_name);
> + if (!opt_pos) {
> + return -1;
> + }
> + /* Skip "=\"" following opt_name */
> + opt_pos += strlen(opt_name) + 2;
> + if (opt_pos >= end) {
> + return -1;
> + }
This can produce false positives because strstr(desc, opt_name) will
match anything that contains the opt_name string. Also we don't
verify that "=\"" follow the opt_name. Luckily we only use this for
"createType" which will hopefully never cause false positives.
> + opt_end = opt_pos;
> + while (opt_end < end && *opt_end != '"') {
> + opt_end++;
> + }
> + if (opt_end == end || buf_size < opt_end - opt_pos + 1) {
> + return -1;
> + }
> + pstrcpy(buf, opt_end - opt_pos + 1, opt_pos);
> + return 0;
> +}
> +
> +static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
> + const char *desc_file_path)
> +{
> + int ret = 0;
> + int r;
> + char access[11];
> + char type[11];
> + char fname[512];
> + const char *p = desc;
> + int64_t sectors = 0;
> + int64_t flat_offset;
> +
> + while (*p) {
> + if (strncmp(p, "RW", strlen("RW"))) {
> + goto next_line;
> + }
This check is duplicated below and can be removed.
> + /* parse extent line:
> + * RW [size in sectors] FLAT "file-name.vmdk" OFFSET
> + * or
> + * RW [size in sectors] SPARSE "file-name.vmdk"
> + */
> + flat_offset = -1;
> + sscanf(p, "%10s %lld %10s %512s",
> + access, §ors, type, fname);
Please check the sscanf(3) return value to ensure the format string
matched. The value of access[], type[], fname[], sectors will be
unchanged at the point where sscanf(3) fails so your checks will not
work.
Declared as char fname[512] but using "%512s" format string. The
format string needs to be 511 to leave space for the NUL terminator.
> + if (!strcmp(type, "FLAT")) {
> + sscanf(p, "%10s %lld %10s %512s %lld",
> + access, §ors, type, fname, &flat_offset);
> + if (flat_offset == -1) {
> + return -EINVAL;
> + }
> + }
> +
> + /* trim the quotation marks around */
> + if (fname[0] == '"') {
> + memmove(fname, fname + 1, strlen(fname) + 1);
This copies 1 byte too many, just strlen(fname) will do.
> + if (fname[strlen(fname) - 1] == '"') {
> + fname[strlen(fname) - 1] = '\0';
> + }
> + }
If starts as fname[] = {'"', '\0'} then this if statement checks
fname[-1] == '"'!
> + if (!(strlen(access) && sectors && strlen(type) && strlen(fname))) {
> + goto next_line;
> + }
These can be replaced by checking the sscanf(3) return value above.
Validating sectors is still a good idea though.
> + if (strcmp(type, "FLAT") && strcmp(type, "SPARSE")) {
> + goto next_line;
> + }
> + if (strcmp(access, "RW")) {
> + goto next_line;
> + }
> + ret++;
This variable is unused.
> + /* save to extents array */
> + if (!strcmp(type, "FLAT")) {
> + /* FLAT extent */
> + char extent_path[PATH_MAX];
> + BlockDriverState *extent_file;
> + BlockDriver *drv;
> + VmdkExtent *extent;
> +
> + extent_file = bdrv_new("");
> + drv = bdrv_find_format("file");
> + if (!drv) {
bdrv_delete(extent_file);
> + return -EINVAL;
> + }
> + path_combine(extent_path, sizeof(extent_path),
> + desc_file_path, fname);
> + r = bdrv_open(extent_file, extent_path,
> + BDRV_O_RDWR | BDRV_O_NO_BACKING, drv);
We should honor the bs->open_flags. Otherwise
cache=none|writeback|writethrough|unsafe is ignored on the actual
extent files.
> + if (r) {
bdrv_delete(extent_file);
> + return -EINVAL;
> + }
> + extent = vmdk_add_extent(bs, extent_file, true, sectors,
> + 0, 0, 0, 0, sectors);
> + extent->flat_start_offset = flat_offset;
> + } else {
> + /* SPARSE extent, not supported for now */
> + fprintf(stderr,
> + "VMDK: Not supported extent type \"%s\""".\n", type);
> + return -ENOTSUP;
> + }
> +next_line:
> + /* move to next line */
> + while (*p && *p != '\n') {
> + p++;
> + }
> + p++;
> + }
> + return 0;
> +}
> +
> +static int vmdk_open_desc_file(BlockDriverState *bs, int flags)
> +{
> + int ret;
> + char buf[2048];
> + char ct[128];
> + BDRVVmdkState *s = bs->opaque;
> +
> + ret = bdrv_pread(bs->file, 0, buf, sizeof(buf));
> + if (ret < 0) {
> + return ret;
> + }
> + buf[2047] = '\0';
> + if (vmdk_parse_description(buf, "createType", ct, sizeof(ct))) {
> + return -EINVAL;
> + }
> + if (strcmp(ct, "monolithicFlat")) {
> + fprintf(stderr,
> + "VMDK: Not supported image type \"%s\""".\n", ct);
> + return -ENOTSUP;
> + }
> + s->desc_offset = 0;
> + ret = vmdk_parse_extents(buf, bs, bs->file->filename);
> + if (ret) {
> + return ret;
> + }
> +
> + /* try to open parent images, if exist */
> + if (vmdk_parent_open(bs)) {
> + qemu_free(s->extents);
This duplicates extent freeing code from vmdk_close(). Please reuse
that (maybe by moving it into a vmdk_free_extents() function), it also
frees l1_table, l2_cache, and l1_backup_table.
Stefan
- [Qemu-devel] [PATCH v5 00/12] Adding VMDK monolithic flat support, Fam Zheng, 2011/06/27
- [Qemu-devel] [PATCH v5 01/12] VMDK: introduce VmdkExtent, Fam Zheng, 2011/06/27
- [Qemu-devel] [PATCH v5 02/12] VMDK: bugfix, align offset to cluster in get_whole_cluster, Fam Zheng, 2011/06/27
- [Qemu-devel] [PATCH v5 03/12] VMDK: probe for monolithicFlat images, Fam Zheng, 2011/06/27
- [Qemu-devel] [PATCH v5 04/12] VMDK: separate vmdk_open by format version, Fam Zheng, 2011/06/27
- [Qemu-devel] [PATCH v5 05/12] VMDK: add field BDRVVmdkState.desc_offset, Fam Zheng, 2011/06/27
- [Qemu-devel] [PATCH v5 06/12] VMDK: flush multiple extents, Fam Zheng, 2011/06/27
- [Qemu-devel] [PATCH v5 07/12] VMDK: move 'static' cid_update flag to bs field, Fam Zheng, 2011/06/27
- [Qemu-devel] [PATCH v5 09/12] VMDK: open/read/write for monolithicFlat image, Fam Zheng, 2011/06/27
- Re: [Qemu-devel] [PATCH v5 09/12] VMDK: open/read/write for monolithicFlat image,
Stefan Hajnoczi <=
- [Qemu-devel] [PATCH v5 08/12] VMDK: change get_cluster_offset return type, Fam Zheng, 2011/06/27
- [Qemu-devel] [PATCH v5 11/12] VMDK: fix coding style, Fam Zheng, 2011/06/27
- [Qemu-devel] [PATCH v5 10/12] VMDK: create different subformats, Fam Zheng, 2011/06/27
- [Qemu-devel] [PATCH v5 12/12] BlockDriver: add bdrv_get_allocated_file_size() operation, Fam Zheng, 2011/06/27