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

                              const char *desc_file_path, Error **errp)

{

    int ret;

    char access[11];

    char type[11];

    char fname[512];

    const char *p = desc;

    int64_t sectors = 0;

    int64_t flat_offset;

    char extent_path[PATH_MAX];

    BlockDriverState *extent_file;

    BDRVVmdkState *s = bs->opaque;

    VmdkExtent *extent;



    while (*p) {

        /* parse extent line:

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

         * or

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

         */

        flat_offset = -1;

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

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

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

            goto next_line;

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

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

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

                return -EINVAL;

            }

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

            flat_offset = 0;

        } else if (ret != 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;

        }



        path_combine(extent_path, sizeof(extent_path),

                desc_file_path, fname);

        ret = bdrv_file_open(&extent_file, extent_path, NULL, bs->open_flags,

                             errp);

        if (ret) {

            return ret;

        }



        /* 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) {

                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*/

            ret = vmdk_open_sparse(bs, extent_file, bs->open_flags, errp);

            if (ret) {

                bdrv_unref(extent_file);

                return ret;

            }

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

        } else {

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

            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, Error **errp)

{

    int ret;

    char access[11];

    char type[11];

    char fname[512];

    const char *p = desc;

    int64_t sectors = 0;

    int64_t flat_offset;

    char extent_path[PATH_MAX];

    BlockDriverState *extent_file;

    BDRVVmdkState *s = bs->opaque;

    VmdkExtent *extent;



    while (*p) {

        









        flat_offset = -1;

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

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

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

            goto next_line;

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

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

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

                return -EINVAL;

            }

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

            flat_offset = 0;

        } else if (ret != 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;

        }



        path_combine(extent_path, sizeof(extent_path),

                desc_file_path, fname);

        ret = bdrv_file_open(&extent_file, extent_path, NULL, bs->open_flags,

                             errp);

        if (ret) {

            return ret;

        }



        

        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) {

                return ret;

            }

            extent->flat_start_offset = flat_offset << 9;

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

            

            ret = vmdk_open_sparse(bs, extent_file, bs->open_flags, errp);

            if (ret) {

                bdrv_unref(extent_file);

                return ret;

            }

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

        } else {

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

            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, Error **VAR_3)

{

    int VAR_4;

    char VAR_5[11];

    char VAR_6[11];

    char VAR_7[512];

    const char *VAR_8 = VAR_0;

    int64_t sectors = 0;

    int64_t flat_offset;

    char VAR_9[PATH_MAX];

    BlockDriverState *extent_file;

    BDRVVmdkState *s = VAR_1->opaque;

    VmdkExtent *extent;



    while (*VAR_8) {

        









        flat_offset = -1;

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

                VAR_5, &sectors, VAR_6, VAR_7, &flat_offset);

        if (VAR_4 < 4 || strcmp(VAR_5, "RW")) {

            goto next_line;

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

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

                error_setg(VAR_3, "Invalid extent lines: \n%s", VAR_8);

                return -EINVAL;

            }

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

            flat_offset = 0;

        } else if (VAR_4 != 4) {

            error_setg(VAR_3, "Invalid extent lines: \n%s", VAR_8);

            return -EINVAL;

        }



        if (sectors <= 0 ||

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

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

            (strcmp(VAR_5, "RW"))) {

            goto next_line;

        }



        path_combine(VAR_9, sizeof(VAR_9),

                VAR_2, VAR_7);

        VAR_4 = bdrv_file_open(&extent_file, VAR_9, NULL, VAR_1->open_flags,

                             VAR_3);

        if (VAR_4) {

            return VAR_4;

        }



        

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

            



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

                            0, 0, 0, 0, 0, &extent, VAR_3);

            if (VAR_4 < 0) {

                return VAR_4;

            }

            extent->flat_start_offset = flat_offset << 9;

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

            

            VAR_4 = vmdk_open_sparse(VAR_1, extent_file, VAR_1->open_flags, VAR_3);

            if (VAR_4) {

                bdrv_unref(extent_file);

                return VAR_4;

            }

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

        } else {

            error_setg(VAR_3, "Unsupported extent VAR_6 '%s'", VAR_6);

            return -ENOTSUP;

        }

        extent->VAR_6 = g_strdup(VAR_6);

next_line:

        

        while (*VAR_8) {

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

                VAR_8++;

                break;

            }

            VAR_8++;

        }

    }

    return 0;

}

static int FUNC_0(const char *VAR_0, BlockDriverState *VAR_1,
const char *VAR_2, Error **VAR_3)
{ int VAR_4; char VAR_5[11]; char VAR_6[11]; char VAR_7[512]; const char *VAR_8 = VAR_0; int64_t sectors = 0; int64_t flat_offset; char VAR_9[PATH_MAX]; BlockDriverState *extent_file; BDRVVmdkState *s = VAR_1->opaque; VmdkExtent *extent; while (*VAR_8) { flat_offset = -1; VAR_4 = sscanf(VAR_8, "%10s %" SCNd64 " %10s \"%511[^\n\r\"]\" %" SCNd64,
VAR_5, &sectors, VAR_6, VAR_7, &flat_offset); if (VAR_4 < 4 || strcmp(VAR_5, "RW")) { goto next_line; } else if (!strcmp(VAR_6, "FLAT")) { if (VAR_4 != 5 || flat_offset < 0) { error_setg(VAR_3, "Invalid extent lines: \n%s", VAR_8); return -EINVAL; } } else if (!strcmp(VAR_6, "VMFS")) { flat_offset = 0; } else if (VAR_4 != 4) { error_setg(VAR_3, "Invalid extent lines: \n%s", VAR_8); return -EINVAL; } if (sectors <= 0 ||
(strcmp(VAR_6, "FLAT") && strcmp(VAR_6, "SPARSE") &&
strcmp(VAR_6, "VMFS") && strcmp(VAR_6, "VMFSSPARSE")) ||
(strcmp(VAR_5, "RW"))) { goto next_line; } path_combine(VAR_9, sizeof(VAR_9),
VAR_2, VAR_7); VAR_4 = bdrv_file_open(&extent_file, VAR_9, NULL, VAR_1->open_flags,
VAR_3); if (VAR_4) { return VAR_4; } if (!strcmp(VAR_6, "FLAT") || !strcmp(VAR_6, "VMFS")) { VAR_4 = vmdk_add_extent(VAR_1, extent_file, true, sectors,
0, 0, 0, 0, 0, &extent, VAR_3); if (VAR_4 < 0) { return VAR_4; } extent->flat_start_offset = flat_offset << 9; } else if (!strcmp(VAR_6, "SPARSE") || !strcmp(VAR_6, "VMFSSPARSE")) { VAR_4 = vmdk_open_sparse(VAR_1, extent_file, VAR_1->open_flags, VAR_3); if (VAR_4) { bdrv_unref(extent_file); return VAR_4; } extent = &s->extents[s->num_extents - 1]; } else { error_setg(VAR_3, "Unsupported extent VAR_6 '%s'", VAR_6); return -ENOTSUP; } extent->VAR_6 = g_strdup(VAR_6); next_line:
while (*VAR_8) { if (*VAR_8 == '\n') { VAR_8++; break; } VAR_8++; } } return 0; }