static int _ResolveInitrd()

in lsvmutils/grubcfg.c [526:690]


static int _ResolveInitrd(
    const GRUBCommand* commands,
    UINTN numCommands,
    char matched[PATH_MAX],
    char title[PATH_MAX],
    char path[PATH_MAX])
{
    int rc = -1;
    UINTN i;
    const char* defaultValue = NULL;
    StrArr arr = STRARR_INITIALIZER;
    const UINTN STACK_SIZE = 16;
    Element stack[STACK_SIZE];
    UINT32 top = 0;
    BOOLEAN hasDefault = TRUE;

    if (path)
        *path = '\0';

    /* Check parameters */
    if (!commands || !numCommands || !path)
        goto done;

    /* Clear the stack */
    Memset(stack, 0, sizeof(stack));

    /* Look for "set default=value", where value is not a variable */
    for (i = 0; i < numCommands; i++)
    {
        const GRUBCommand* cmd = &commands[i];

        if (cmd->argc < 2)
            continue;

        if (Strcmp(cmd->argv[0], "set") == 0 &&
            Strncmp(cmd->argv[1], "default=", 8) == 0 &&
            cmd->argv[1][8] != '$')
        {
            defaultValue = cmd->argv[1] + 8;
            break;
        }
    }

    /* If not found, then fallback on the "0" menu entry */
    if (!defaultValue)
    {
        defaultValue = "0";
        hasDefault = FALSE;
    }

    /* Split 'default' value into parts */
    if (StrSplit(defaultValue, ">", &arr) != 0 || arr.size < 1)
        goto done;

#if defined(DEBUG_GRUBCFG)
    for (i = 0; i < arr.size; i++)
    {
        PRINTF("DEFAULT{%s}\n", arr.data[i]);
    }
#endif

    /* Look for matching 'menuentry' */
    for (i = 0; i < numCommands; i++)
    {
        const GRUBCommand* cmd = &commands[i];

        if (Strcmp(cmd->argv[0], "menuentry") == 0)
        {
#if defined(DEBUG_GRUBCFG)
            _Indent(top);
            PRINTF0("menuentry\n");
            _Indent(top);
            PRINTF0("{\n");
#endif

            /* Check for stack overflow */
            if (top == STACK_SIZE)
                goto done;

            /* Push element onto stack */
            stack[top].command = cmd;
            top++;
        }
        else if (Strcmp(cmd->argv[0], "submenu") == 0)
        {
#if defined(DEBUG_GRUBCFG)
            _Indent(top);
            PRINTF0("submenu\n");
            _Indent(top);
            PRINTF0("{\n");
#endif

            /* Check for stack overflow */
            if (top == STACK_SIZE)
                goto done;

            /* Push element onto stack */
            stack[top].command = cmd;
            top++;
        }
        else if (Strcmp(cmd->argv[0], "initrd") == 0 && cmd->argc == 2)
        {
            if (top && Strcmp(stack[top-1].command->argv[0], "menuentry") == 0)
                Strcpy(stack[top-1].initrd, cmd->argv[1]);
        }
        else if (Strcmp(cmd->argv[0], "initrdefi") == 0 && cmd->argc == 2)
        {
            if (top && Strcmp(stack[top-1].command->argv[0], "menuentry") == 0)
                Strcpy(stack[top-1].initrd, cmd->argv[1]);
        }
        else if (Strcmp(cmd->argv[0], "}") == 0)
        {
            if (top)
            {
                /* Reset the depth at next level */
                if (top != STACK_SIZE)
                    stack[top].index = 0;

                if (Strcmp(stack[top-1].command->argv[0], "menuentry") == 0)
                {
                    if (_Match(&arr, hasDefault, stack, top, matched))
                    {
                        Strcpy(title, stack[top-1].command->argv[1]);
                        Strcpy(path, stack[top-1].initrd);
                        rc = 0;
                        goto done;
                        PRINTF0("MATCH!!!\n");
                    }
#if defined(DEBUG_GRUBCFG)
{
UINTN j;
                    _Indent(top);
                    for (j = 0; j < top; j++)
                    {
                        PRINTF("%lu>", (unsigned long)stack[j].index);
                    }
                    PRINTF(": %s\n", stack[top-1].initrd);
}
#endif
                }

                /* Pop the stack */
                top--;
                stack[top].initrd[0] = '\0';
                stack[top].index++;

#if defined(DEBUG_GRUBCFG)
                _Indent(top);
                PRINTF0("}\n");
#endif

            }
        }

        (void)cmd;
    }

    rc = 0;

done:

    StrArrRelease(&arr);

    return rc;
}