static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,

                              const char *desc_file_path, QDict *options,

                              Error **errp)

{

    int ret;

    int matches;

    char access[11];

    char type[11];

    char fname[512];

    const char *p = desc;

    int64_t sectors = 0;

    int64_t flat_offset;

    char *extent_path;

    BdrvChild *extent_file;

    BDRVVmdkState *s = bs->opaque;

    VmdkExtent *extent;

    char extent_opt_prefix[32];

    Error *local_err = NULL;



    while (*p) {

        /* parse extent line in one of below formats:

         *

         * RW [size in sectors] FLAT "file-name.vmdk" OFFSET

         * RW [size in sectors] SPARSE "file-name.vmdk"

         * RW [size in sectors] VMFS "file-name.vmdk"

         * RW [size in sectors] VMFSSPARSE "file-name.vmdk"

         */

        flat_offset = -1;

        matches = sscanf(p, "%10s %" SCNd64 " %10s \"%511[^\n\r\"]\" %" SCNd64,

                         access, &sectors, type, fname, &flat_offset);

        if (matches < 4 || strcmp(access, "RW")) {

            goto next_line;

        } else if (!strcmp(type, "FLAT")) {

            if (matches != 5 || flat_offset < 0) {

                error_setg(errp, "Invalid extent lines: \n%s", p);

                return -EINVAL;

            }

        } else if (!strcmp(type, "VMFS")) {

            if (matches == 4) {

                flat_offset = 0;

            } else {

                error_setg(errp, "Invalid extent lines:\n%s", p);

                return -EINVAL;

            }

        } else if (matches != 4) {

            error_setg(errp, "Invalid extent lines:\n%s", p);

            return -EINVAL;

        }



        if (sectors <= 0 ||

            (strcmp(type, "FLAT") && strcmp(type, "SPARSE") &&

             strcmp(type, "VMFS") && strcmp(type, "VMFSSPARSE")) ||

            (strcmp(access, "RW"))) {

            goto next_line;

        }



        if (!path_is_absolute(fname) && !path_has_protocol(fname) &&

            !desc_file_path[0])

        {

            error_setg(errp, "Cannot use relative extent paths with VMDK "

                       "descriptor file '%s'", bs->file->bs->filename);

            return -EINVAL;

        }



        extent_path = g_malloc0(PATH_MAX);

        path_combine(extent_path, PATH_MAX, desc_file_path, fname);



        ret = snprintf(extent_opt_prefix, 32, "extents.%d", s->num_extents);

        assert(ret < 32);



        extent_file = bdrv_open_child(extent_path, options, extent_opt_prefix,

                                      bs, &child_file, false, &local_err);

        g_free(extent_path);

        if (local_err) {

            error_propagate(errp, local_err);

            return -EINVAL;

        }



        /* save to extents array */

        if (!strcmp(type, "FLAT") || !strcmp(type, "VMFS")) {

            /* FLAT extent */



            ret = vmdk_add_extent(bs, extent_file, true, sectors,

                            0, 0, 0, 0, 0, &extent, errp);

            if (ret < 0) {

                bdrv_unref_child(bs, extent_file);

                return ret;

            }

            extent->flat_start_offset = flat_offset << 9;

        } else if (!strcmp(type, "SPARSE") || !strcmp(type, "VMFSSPARSE")) {

            /* SPARSE extent and VMFSSPARSE extent are both "COWD" sparse file*/

            char *buf = vmdk_read_desc(extent_file->bs, 0, errp);

            if (!buf) {

                ret = -EINVAL;

            } else {

                ret = vmdk_open_sparse(bs, extent_file, bs->open_flags, buf,

                                       options, errp);

            }

            g_free(buf);

            if (ret) {

                bdrv_unref_child(bs, extent_file);

                return ret;

            }

            extent = &s->extents[s->num_extents - 1];

        } else {

            error_setg(errp, "Unsupported extent type '%s'", type);

            bdrv_unref_child(bs, extent_file);

            return -ENOTSUP;

        }

        extent->type = g_strdup(type);

next_line:

        /* move to next line */

        while (*p) {

            if (*p == '\n') {

                p++;

                break;

            }

            p++;

        }

    }

    return 0;

}

static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,

                              const char *desc_file_path, QDict *options,

                              Error **errp)

{

    int ret;

    int matches;

    char access[11];

    char type[11];

    char fname[512];

    const char *p = desc;

    int64_t sectors = 0;

    int64_t flat_offset;

    char *extent_path;

    BdrvChild *extent_file;

    BDRVVmdkState *s = bs->opaque;

    VmdkExtent *extent;

    char extent_opt_prefix[32];

    Error *local_err = NULL;



    while (*p) {

        













        flat_offset = -1;

        matches = sscanf(p, "%10s %" SCNd64 " %10s \"%511[^\n\r\"]\" %" SCNd64,

                         access, &sectors, type, fname, &flat_offset);

        if (matches < 4 || strcmp(access, "RW")) {

            goto next_line;

        } else if (!strcmp(type, "FLAT")) {

            if (matches != 5 || flat_offset < 0) {

                error_setg(errp, "Invalid extent lines: \n%s", p);

                return -EINVAL;

            }

        } else if (!strcmp(type, "VMFS")) {

            if (matches == 4) {

                flat_offset = 0;

            } else {

                error_setg(errp, "Invalid extent lines:\n%s", p);

                return -EINVAL;

            }

        } else if (matches != 4) {

            error_setg(errp, "Invalid extent lines:\n%s", p);

            return -EINVAL;

        }



        if (sectors <= 0 ||

            (strcmp(type, "FLAT") && strcmp(type, "SPARSE") &&

             strcmp(type, "VMFS") && strcmp(type, "VMFSSPARSE")) ||

            (strcmp(access, "RW"))) {

            goto next_line;

        }



        if (!path_is_absolute(fname) && !path_has_protocol(fname) &&

            !desc_file_path[0])

        {

            error_setg(errp, "Cannot use relative extent paths with VMDK "

                       "descriptor file '%s'", bs->file->bs->filename);

            return -EINVAL;

        }



        extent_path = g_malloc0(PATH_MAX);

        path_combine(extent_path, PATH_MAX, desc_file_path, fname);



        ret = snprintf(extent_opt_prefix, 32, "extents.%d", s->num_extents);

        assert(ret < 32);



        extent_file = bdrv_open_child(extent_path, options, extent_opt_prefix,

                                      bs, &child_file, false, &local_err);

        g_free(extent_path);

        if (local_err) {

            error_propagate(errp, local_err);

            return -EINVAL;

        }



        

        if (!strcmp(type, "FLAT") || !strcmp(type, "VMFS")) {

            



            ret = vmdk_add_extent(bs, extent_file, true, sectors,

                            0, 0, 0, 0, 0, &extent, errp);

            if (ret < 0) {

                bdrv_unref_child(bs, extent_file);

                return ret;

            }

            extent->flat_start_offset = flat_offset << 9;

        } else if (!strcmp(type, "SPARSE") || !strcmp(type, "VMFSSPARSE")) {

            

            char *buf = vmdk_read_desc(extent_file->bs, 0, errp);

            if (!buf) {

                ret = -EINVAL;

            } else {

                ret = vmdk_open_sparse(bs, extent_file, bs->open_flags, buf,

                                       options, errp);

            }

            g_free(buf);

            if (ret) {

                bdrv_unref_child(bs, extent_file);

                return ret;

            }

            extent = &s->extents[s->num_extents - 1];

        } else {

            error_setg(errp, "Unsupported extent type '%s'", type);

            bdrv_unref_child(bs, extent_file);

            return -ENOTSUP;

        }

        extent->type = g_strdup(type);

next_line:

        

        while (*p) {

            if (*p == '\n') {

                p++;

                break;

            }

            p++;

        }

    }

    return 0;

}

static int FUNC_0(const char *VAR_0, BlockDriverState *VAR_1,

                              const char *VAR_2, QDict *VAR_3,

                              Error **VAR_4)

{

    int VAR_5;

    int VAR_6;

    char VAR_7[11];

    char VAR_8[11];

    char VAR_9[512];

    const char *VAR_10 = VAR_0;

    int64_t sectors = 0;

    int64_t flat_offset;

    char *VAR_11;

    BdrvChild *extent_file;

    BDRVVmdkState *s = VAR_1->opaque;

    VmdkExtent *extent;

    char VAR_12[32];

    Error *local_err = NULL;



    while (*VAR_10) {

        













        flat_offset = -1;

        VAR_6 = sscanf(VAR_10, "%10s %" SCNd64 " %10s \"%511[^\n\r\"]\" %" SCNd64,

                         VAR_7, &sectors, VAR_8, VAR_9, &flat_offset);

        if (VAR_6 < 4 || strcmp(VAR_7, "RW")) {

            goto next_line;

        } else if (!strcmp(VAR_8, "FLAT")) {

            if (VAR_6 != 5 || flat_offset < 0) {

                error_setg(VAR_4, "Invalid extent lines: \n%s", VAR_10);

                return -EINVAL;

            }

        } else if (!strcmp(VAR_8, "VMFS")) {

            if (VAR_6 == 4) {

                flat_offset = 0;

            } else {

                error_setg(VAR_4, "Invalid extent lines:\n%s", VAR_10);

                return -EINVAL;

            }

        } else if (VAR_6 != 4) {

            error_setg(VAR_4, "Invalid extent lines:\n%s", VAR_10);

            return -EINVAL;

        }



        if (sectors <= 0 ||

            (strcmp(VAR_8, "FLAT") && strcmp(VAR_8, "SPARSE") &&

             strcmp(VAR_8, "VMFS") && strcmp(VAR_8, "VMFSSPARSE")) ||

            (strcmp(VAR_7, "RW"))) {

            goto next_line;

        }



        if (!path_is_absolute(VAR_9) && !path_has_protocol(VAR_9) &&

            !VAR_2[0])

        {

            error_setg(VAR_4, "Cannot use relative extent paths with VMDK "

                       "descriptor file '%s'", VAR_1->file->VAR_1->filename);

            return -EINVAL;

        }



        VAR_11 = g_malloc0(PATH_MAX);

        path_combine(VAR_11, PATH_MAX, VAR_2, VAR_9);



        VAR_5 = snprintf(VAR_12, 32, "extents.%d", s->num_extents);

        assert(VAR_5 < 32);



        extent_file = bdrv_open_child(VAR_11, VAR_3, VAR_12,

                                      VAR_1, &child_file, false, &local_err);

        g_free(VAR_11);

        if (local_err) {

            error_propagate(VAR_4, local_err);

            return -EINVAL;

        }



        

        if (!strcmp(VAR_8, "FLAT") || !strcmp(VAR_8, "VMFS")) {

            



            VAR_5 = vmdk_add_extent(VAR_1, extent_file, true, sectors,

                            0, 0, 0, 0, 0, &extent, VAR_4);

            if (VAR_5 < 0) {

                bdrv_unref_child(VAR_1, extent_file);

                return VAR_5;

            }

            extent->flat_start_offset = flat_offset << 9;

        } else if (!strcmp(VAR_8, "SPARSE") || !strcmp(VAR_8, "VMFSSPARSE")) {

            

            char *VAR_13 = vmdk_read_desc(extent_file->VAR_1, 0, VAR_4);

            if (!VAR_13) {

                VAR_5 = -EINVAL;

            } else {

                VAR_5 = vmdk_open_sparse(VAR_1, extent_file, VAR_1->open_flags, VAR_13,

                                       VAR_3, VAR_4);

            }

            g_free(VAR_13);

            if (VAR_5) {

                bdrv_unref_child(VAR_1, extent_file);

                return VAR_5;

            }

            extent = &s->extents[s->num_extents - 1];

        } else {

            error_setg(VAR_4, "Unsupported extent VAR_8 '%s'", VAR_8);

            bdrv_unref_child(VAR_1, extent_file);

            return -ENOTSUP;

        }

        extent->VAR_8 = g_strdup(VAR_8);

next_line:

        

        while (*VAR_10) {

            if (*VAR_10 == '\n') {

                VAR_10++;

                break;

            }

            VAR_10++;

        }

    }

    return 0;

}

static int FUNC_0(const char *VAR_0, BlockDriverState *VAR_1,
const char *VAR_2, QDict *VAR_3,
Error **VAR_4)
{ int VAR_5; int VAR_6; char VAR_7[11]; char VAR_8[11]; char VAR_9[512]; const char *VAR_10 = VAR_0; int64_t sectors = 0; int64_t flat_offset; char *VAR_11; BdrvChild *extent_file; BDRVVmdkState *s = VAR_1->opaque; VmdkExtent *extent; char VAR_12[32]; Error *local_err = NULL; while (*VAR_10) { flat_offset = -1; VAR_6 = sscanf(VAR_10, "%10s %" SCNd64 " %10s \"%511[^\n\r\"]\" %" SCNd64,
VAR_7, &sectors, VAR_8, VAR_9, &flat_offset); if (VAR_6 < 4 || strcmp(VAR_7, "RW")) { goto next_line; } else if (!strcmp(VAR_8, "FLAT")) { if (VAR_6 != 5 || flat_offset < 0) { error_setg(VAR_4, "Invalid extent lines: \n%s", VAR_10); return -EINVAL; } } else if (!strcmp(VAR_8, "VMFS")) { if (VAR_6 == 4) { flat_offset = 0; } else { error_setg(VAR_4, "Invalid extent lines:\n%s", VAR_10); return -EINVAL; } } else if (VAR_6 != 4) { error_setg(VAR_4, "Invalid extent lines:\n%s", VAR_10); return -EINVAL; } if (sectors <= 0 ||
(strcmp(VAR_8, "FLAT") && strcmp(VAR_8, "SPARSE") &&
strcmp(VAR_8, "VMFS") && strcmp(VAR_8, "VMFSSPARSE")) ||
(strcmp(VAR_7, "RW"))) { goto next_line; } if (!path_is_absolute(VAR_9) && !path_has_protocol(VAR_9) &&
!VAR_2[0])
{ error_setg(VAR_4, "Cannot use relative extent paths with VMDK "
"descriptor file '%s'", VAR_1->file->VAR_1->filename); return -EINVAL; } VAR_11 = g_malloc0(PATH_MAX); path_combine(VAR_11, PATH_MAX, VAR_2, VAR_9); VAR_5 = snprintf(VAR_12, 32, "extents.%d", s->num_extents); assert(VAR_5 < 32); extent_file = bdrv_open_child(VAR_11, VAR_3, VAR_12,
VAR_1, &child_file, false, &local_err); g_free(VAR_11); if (local_err) { error_propagate(VAR_4, local_err); return -EINVAL; } if (!strcmp(VAR_8, "FLAT") || !strcmp(VAR_8, "VMFS")) { VAR_5 = vmdk_add_extent(VAR_1, extent_file, true, sectors,
0, 0, 0, 0, 0, &extent, VAR_4); if (VAR_5 < 0) { bdrv_unref_child(VAR_1, extent_file); return VAR_5; } extent->flat_start_offset = flat_offset << 9; } else if (!strcmp(VAR_8, "SPARSE") || !strcmp(VAR_8, "VMFSSPARSE")) { char *VAR_13 = vmdk_read_desc(extent_file->VAR_1, 0, VAR_4); if (!VAR_13) { VAR_5 = -EINVAL; } else { VAR_5 = vmdk_open_sparse(VAR_1, extent_file, VAR_1->open_flags, VAR_13,
VAR_3, VAR_4); } g_free(VAR_13); if (VAR_5) { bdrv_unref_child(VAR_1, extent_file); return VAR_5; } extent = &s->extents[s->num_extents - 1]; } else { error_setg(VAR_4, "Unsupported extent VAR_8 '%s'", VAR_8); bdrv_unref_child(VAR_1, extent_file); return -ENOTSUP; } extent->VAR_8 = g_strdup(VAR_8); next_line:
while (*VAR_10) { if (*VAR_10 == '\n') { VAR_10++; break; } VAR_10++; } } return 0; }