Beispiel #1
0
/**
 * virConfParseString:
 * @ctxt: the parsing context
 *
 * Parse one string
 *
 * Returns a pointer to the string or NULL in case of error
 */
static char *
virConfParseString(virConfParserCtxtPtr ctxt)
{
    const char *base;
    char *ret = NULL;

    if (CUR == '\'') {
        NEXT;
        base = ctxt->cur;
        while ((ctxt->cur < ctxt->end) && (CUR != '\'') && (!IS_EOL(CUR)))
            NEXT;
        if (CUR != '\'') {
            virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("unterminated string"));
            return NULL;
        }
        if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0)
            return NULL;
        NEXT;
    } else if ((ctxt->cur + 6 < ctxt->end) &&
               (STRPREFIX(ctxt->cur, "\"\"\""))) {
        /* String starts with python-style triple quotes """ */
        ctxt->cur += 3;
        base = ctxt->cur;

        /* Find the ending triple quotes */
        while ((ctxt->cur + 2 < ctxt->end) &&
               !(STRPREFIX(ctxt->cur, "\"\"\""))) {
            if (CUR == '\n')
                ctxt->line++;
            NEXT;
        }

        if (!STRPREFIX(ctxt->cur, "\"\"\"")) {
            virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("unterminated string"));
            return NULL;
        }
        if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0)
            return NULL;
        ctxt->cur += 3;
    } else if (CUR == '"') {
        NEXT;
        base = ctxt->cur;
        while ((ctxt->cur < ctxt->end) && (CUR != '"') && (!IS_EOL(CUR)))
            NEXT;
        if (CUR != '"') {
            virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("unterminated string"));
            return NULL;
        }
        if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0)
            return NULL;
        NEXT;
    }
    return ret;
}
Beispiel #2
0
/**
 * virConfParseName:
 * @ctxt: the parsing context
 *
 * Parse one name
 *
 * Returns a copy of the new string, NULL in case of error
 */
static char *
virConfParseName(virConfParserCtxtPtr ctxt)
{
    const char *base;
    char *ret;

    SKIP_BLANKS;
    base = ctxt->cur;
    /* TODO: probably need encoding support and UTF-8 parsing ! */
    if (!c_isalpha(CUR) &&
            !((ctxt->conf->flags & VIR_CONF_FLAG_VMX_FORMAT) && (CUR == '.'))) {
        virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("expecting a name"));
        return NULL;
    }
    while ((ctxt->cur < ctxt->end) &&
            (c_isalnum(CUR) || (CUR == '_') ||
             ((ctxt->conf->flags & VIR_CONF_FLAG_VMX_FORMAT) &&
              ((CUR == ':') || (CUR == '.') || (CUR == '-'))) ||
             ((ctxt->conf->flags & VIR_CONF_FLAG_LXC_FORMAT) &&
              (CUR == '.'))))
        NEXT;
    if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0)
        return NULL;
    return ret;
}
Beispiel #3
0
/**
 * virConfParseLong:
 * @ctxt: the parsing context
 * @val: the result
 *
 * Parse one long int value
 *
 * Returns 0 in case of success and -1 in case of error
 */
static int
virConfParseLong(virConfParserCtxtPtr ctxt, long *val)
{
    long l = 0;
    int neg = 0;

    if (CUR == '-') {
        neg = 1;
        NEXT;
    } else if (CUR == '+') {
        NEXT;
    }
    if ((ctxt->cur >= ctxt->end) || (!c_isdigit(CUR))) {
        virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("unterminated number"));
        return -1;
    }
    while ((ctxt->cur < ctxt->end) && (c_isdigit(CUR))) {
        l = l * 10 + (CUR - '0');
        NEXT;
    }
    if (neg)
        l = -l;
    *val = l;
    return 0;
}
Beispiel #4
0
/**
 * virConfReadFile:
 * @filename: the path to the configuration file.
 * @flags: combination of virConfFlag(s)
 *
 * Reads a configuration file.
 *
 * Returns a handle to lookup settings or NULL if it failed to
 *         read or parse the file, use virConfFree() to free the data.
 */
virConfPtr
virConfReadFile(const char *filename, unsigned int flags)
{
    char *content;
    int len;
    virConfPtr conf = NULL;

    VIR_DEBUG("filename=%s", NULLSTR(filename));

    if (filename == NULL) {
        virConfError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
        return NULL;
    }

    if ((len = virFileReadAll(filename, MAX_CONFIG_FILE_SIZE, &content)) < 0)
        return NULL;

    if (len && len < MAX_CONFIG_FILE_SIZE && content[len - 1] != '\n') {
        VIR_DEBUG("appending newline to busted config file %s", filename);
        if (VIR_REALLOC_N(content, len + 1) < 0)
            goto cleanup;
        content[len++] = '\n';
        content[len] = '\0';
    }

    conf = virConfParse(filename, content, len, flags);

 cleanup:
    VIR_FREE(content);

    return conf;
}
Beispiel #5
0
static int remoteConfigGetAuth(virConfPtr conf, const char *key, int *auth, const char *filename) {
    virConfValuePtr p;

    p = virConfGetValue (conf, key);
    if (!p)
        return 0;

    if (checkType (p, filename, key, VIR_CONF_STRING) < 0)
        return -1;

    if (!p->str)
        return 0;

    if (STREQ(p->str, "none")) {
        *auth = VIR_NET_SERVER_SERVICE_AUTH_NONE;
#if HAVE_SASL
    } else if (STREQ(p->str, "sasl")) {
        *auth = VIR_NET_SERVER_SERVICE_AUTH_SASL;
#endif
    } else if (STREQ(p->str, "polkit")) {
        *auth = VIR_NET_SERVER_SERVICE_AUTH_POLKIT;
    } else {
        virConfError(VIR_ERR_CONFIG_UNSUPPORTED,
                     _("remoteReadConfigFile: %s: %s: unsupported auth %s"),
                     filename, key, p->str);
        return -1;
    }

    return 0;
}
Beispiel #6
0
/**
 * virConfWriteFile:
 * @filename: the path to the configuration file.
 * @conf: the conf
 *
 * Writes a configuration file back to a file.
 *
 * Returns the number of bytes written or -1 in case of error.
 */
int
virConfWriteFile(const char *filename, virConfPtr conf)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    virConfEntryPtr cur;
    int ret;
    int fd;
    char *content;
    unsigned int use;

    if (conf == NULL)
        return -1;

    cur = conf->entries;
    while (cur != NULL) {
        virConfSaveEntry(&buf, cur);
        cur = cur->next;
    }

    if (virBufferError(&buf)) {
        virBufferFreeAndReset(&buf);
        virReportOOMError();
        return -1;
    }

    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
    if (fd < 0) {
        virBufferFreeAndReset(&buf);
        virConfError(NULL, VIR_ERR_WRITE_FAILED, _("failed to open file"));
        return -1;
    }

    use = virBufferUse(&buf);
    content = virBufferContentAndReset(&buf);
    ret = safewrite(fd, content, use);
    VIR_FREE(content);
    VIR_FORCE_CLOSE(fd);
    if (ret != (int)use) {
        virConfError(NULL, VIR_ERR_WRITE_FAILED, _("failed to save content"));
        return -1;
    }

    return ret;
}
Beispiel #7
0
/**
 * virConfReadMem:
 * @memory: pointer to the content of the configuration file
 * @len: length in byte
 * @flags: combination of virConfFlag(s)
 *
 * Reads a configuration file loaded in memory. The string can be
 * zero terminated in which case @len can be 0
 *
 * Returns a handle to lookup settings or NULL if it failed to
 *         parse the content, use virConfFree() to free the data.
 */
virConfPtr
virConfReadMem(const char *memory, int len, unsigned int flags)
{
    if ((memory == NULL) || (len < 0)) {
        virConfError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
        return NULL;
    }
    if (len == 0)
        len = strlen(memory);

    return virConfParse("memory conf", memory, len, flags);
}
Beispiel #8
0
/* A helper function used by each of the following macros.  */
static int
checkType (virConfValuePtr p, const char *filename,
           const char *key, virConfType required_type)
{
    if (p->type != required_type) {
        virConfError(VIR_ERR_CONFIG_UNSUPPORTED,
                     _("remoteReadConfigFile: %s: %s: invalid type:"
                       " got %s; expected %s"), filename, key,
                     virConfTypeName (p->type),
                     virConfTypeName (required_type));
        return -1;
    }
    return 0;
}
Beispiel #9
0
/**
 * virConfParseStatement:
 * @ctxt: the parsing context
 *
 * Parse one statement in the conf file
 *
 * Returns 0 in case of success and -1 in case of error
 */
static int
virConfParseStatement(virConfParserCtxtPtr ctxt)
{
    const char *base;
    char *name;
    virConfValuePtr value;
    char *comm = NULL;

    SKIP_BLANKS_AND_EOL;
    if (CUR == '#') {
        return virConfParseComment(ctxt);
    }
    name = virConfParseName(ctxt);
    if (name == NULL)
        return -1;
    SKIP_BLANKS;
    if (CUR != '=') {
        virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("expecting an assignment"));
        VIR_FREE(name);
        return -1;
    }
    NEXT;
    SKIP_BLANKS;
    value = virConfParseValue(ctxt);
    if (value == NULL) {
        VIR_FREE(name);
        return -1;
    }
    SKIP_BLANKS;
    if (CUR == '#') {
        NEXT;
        base = ctxt->cur;
        while ((ctxt->cur < ctxt->end) && (!IS_EOL(CUR))) NEXT;
        comm = strndup(base, ctxt->cur - base);
        if (comm == NULL) {
            virReportOOMError();
            VIR_FREE(name);
            virConfFreeValue(value);
            return -1;
        }
    }
    if (virConfAddEntry(ctxt->conf, name, value, comm) == NULL) {
        VIR_FREE(name);
        virConfFreeValue(value);
        VIR_FREE(comm);
        return -1;
    }
    return 0;
}
Beispiel #10
0
/**
 * virConfParseSeparator:
 * @ctxt: the parsing context
 *
 * Parse one separator between statement if not at the end.
 *
 * Returns 0 in case of success and -1 in case of error
 */
static int
virConfParseSeparator(virConfParserCtxtPtr ctxt)
{
    SKIP_BLANKS;
    if (ctxt->cur >= ctxt->end)
        return 0;
    if (IS_EOL(CUR)) {
        SKIP_BLANKS_AND_EOL;
    } else if (CUR == ';') {
        NEXT;
        SKIP_BLANKS_AND_EOL;
    } else {
        virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("expecting a separator"));
        return -1;
    }
    return 0;
}
Beispiel #11
0
/**
 * virConfReadFile:
 * @filename: the path to the configuration file.
 * @flags: combination of virConfFlag(s)
 *
 * Reads a configuration file.
 *
 * Returns a handle to lookup settings or NULL if it failed to
 *         read or parse the file, use virConfFree() to free the data.
 */
virConfPtr
virConfReadFile(const char *filename, unsigned int flags)
{
    char *content;
    int len;
    virConfPtr conf;

    if (filename == NULL) {
        virConfError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
        return NULL;
    }

    if ((len = virFileReadAll(filename, MAX_CONFIG_FILE_SIZE, &content)) < 0) {
        return NULL;
    }

    conf = virConfParse(filename, content, len, flags);

    VIR_FREE(content);

    return conf;
}
Beispiel #12
0
/**
 * virConfParseValue:
 * @ctxt: the parsing context
 *
 * Parse one value
 *
 * Returns a pointer to the value or NULL in case of error
 */
static virConfValuePtr
virConfParseValue(virConfParserCtxtPtr ctxt)
{
    virConfValuePtr ret, lst = NULL, tmp, prev;
    virConfType type = VIR_CONF_NONE;
    char *str = NULL;
    long  l = 0;

    SKIP_BLANKS;
    if (ctxt->cur >= ctxt->end) {
        virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("expecting a value"));
        return NULL;
    }
    if ((CUR == '"') || (CUR == '\'') ||
            (ctxt->conf->flags & VIR_CONF_FLAG_LXC_FORMAT)) {
        type = VIR_CONF_STRING;
        str = virConfParseString(ctxt);
        if (str == NULL)
            return NULL;
    } else if (CUR == '[') {
        if (ctxt->conf->flags & VIR_CONF_FLAG_VMX_FORMAT) {
            virConfError(ctxt, VIR_ERR_CONF_SYNTAX,
                         _("lists not allowed in VMX format"));
            return NULL;
        }
        type = VIR_CONF_LIST;
        NEXT;
        SKIP_BLANKS_AND_EOL;
        if ((ctxt->cur < ctxt->end) && (CUR != ']')) {
            if ((lst = virConfParseValue(ctxt)) == NULL)
                return NULL;
            SKIP_BLANKS_AND_EOL;
        }
        while ((ctxt->cur < ctxt->end) && (CUR != ']')) {

            /* Tell Clang that when execution reaches this point
               "lst" is guaranteed to be non-NULL.  This stops it
               from issuing an invalid NULL-dereference warning about
               "prev = lst; while (prev->next..." below.  */
            sa_assert(lst);

            if (CUR != ',') {
                virConfError(ctxt, VIR_ERR_CONF_SYNTAX,
                             _("expecting a separator in list"));
                virConfFreeList(lst);
                return NULL;
            }
            NEXT;
            SKIP_BLANKS_AND_EOL;
            if (CUR == ']') {
                break;
            }
            tmp = virConfParseValue(ctxt);
            if (tmp == NULL) {
                virConfFreeList(lst);
                return NULL;
            }
            prev = lst;
            while (prev->next != NULL) prev = prev->next;
            prev->next = tmp;
            SKIP_BLANKS_AND_EOL;
        }
        if (CUR == ']') {
            NEXT;
        } else {
            virConfError(ctxt, VIR_ERR_CONF_SYNTAX,
                         _("list is not closed with ]"));
            virConfFreeList(lst);
            return NULL;
        }
    } else if (c_isdigit(CUR) || (CUR == '-') || (CUR == '+')) {
        if (ctxt->conf->flags & VIR_CONF_FLAG_VMX_FORMAT) {
            virConfError(ctxt, VIR_ERR_CONF_SYNTAX,
                         _("numbers not allowed in VMX format"));
            return NULL;
        }
        if (virConfParseLong(ctxt, &l) < 0) {
            return NULL;
        }
        type = VIR_CONF_LONG;
    } else {
        virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("expecting a value"));
        return NULL;
    }
    if (VIR_ALLOC(ret) < 0) {
        virConfFreeList(lst);
        VIR_FREE(str);
        return NULL;
    }
    ret->type = type;
    ret->l = l;
    ret->str = str;
    ret->list = lst;
    return ret;
}
Beispiel #13
0
/**
 * virConfParseString:
 * @ctxt: the parsing context
 *
 * Parse one string
 *
 * Returns a pointer to the string or NULL in case of error
 */
static char *
virConfParseString(virConfParserCtxtPtr ctxt)
{
    const char *base;
    char *ret = NULL;

    if (CUR == '\'') {
        NEXT;
        base = ctxt->cur;
        while ((ctxt->cur < ctxt->end) && (CUR != '\'') && (!IS_EOL(CUR)))
            NEXT;
        if (CUR != '\'') {
            virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("unterminated string"));
            return NULL;
        }
        if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0)
            return NULL;
        NEXT;
    } else if ((ctxt->cur + 6 < ctxt->end) &&
               (STRPREFIX(ctxt->cur, "\"\"\""))) {
        /* String starts with python-style triple quotes """ */
        ctxt->cur += 3;
        base = ctxt->cur;

        /* Find the ending triple quotes */
        while ((ctxt->cur + 2 < ctxt->end) &&
                !(STRPREFIX(ctxt->cur, "\"\"\""))) {
            if (CUR == '\n')
                ctxt->line++;
            NEXT;
        }

        if (!STRPREFIX(ctxt->cur, "\"\"\"")) {
            virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("unterminated string"));
            return NULL;
        }
        if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0)
            return NULL;
        ctxt->cur += 3;
    } else if (CUR == '"') {
        NEXT;
        base = ctxt->cur;
        while ((ctxt->cur < ctxt->end) && (CUR != '"') && (!IS_EOL(CUR)))
            NEXT;
        if (CUR != '"') {
            virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("unterminated string"));
            return NULL;
        }
        if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0)
            return NULL;
        NEXT;
    } else if (ctxt->conf->flags & VIR_CONF_FLAG_LXC_FORMAT) {
        base = ctxt->cur;
        /* LXC config format doesn't support comments after the value */
        while ((ctxt->cur < ctxt->end) && (!IS_EOL(CUR)))
            NEXT;
        /* Reverse to exclude the trailing blanks from the value */
        while ((ctxt->cur > base) && (c_isblank(CUR)))
            ctxt->cur--;
        if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0)
            return NULL;
    }
    return ret;
}
Beispiel #14
0
/* Allocate an array of malloc'd strings from the config file, filename
 * (used only in diagnostics), using handle "conf".  Upon error, return -1
 * and free any allocated memory.  Otherwise, save the array in *list_arg
 * and return 0.
 */
static int
remoteConfigGetStringList(virConfPtr conf, const char *key, char ***list_arg,
                          const char *filename)
{
    char **list;
    virConfValuePtr p = virConfGetValue (conf, key);
    if (!p)
        return 0;

    switch (p->type) {
    case VIR_CONF_STRING:
        if (VIR_ALLOC_N(list, 2) < 0) {
            virConfError(VIR_ERR_CONFIG_UNSUPPORTED,
                         _("failed to allocate memory for %s config list"),
                         key);
            return -1;
        }
        list[0] = strdup (p->str);
        list[1] = NULL;
        if (list[0] == NULL) {
            virConfError(VIR_ERR_CONFIG_UNSUPPORTED,
                         _("failed to allocate memory for %s config list value"),
                         key);
            VIR_FREE(list);
            return -1;
        }
        break;

    case VIR_CONF_LIST: {
        int i, len = 0;
        virConfValuePtr pp;
        for (pp = p->list; pp; pp = pp->next)
            len++;
        if (VIR_ALLOC_N(list, 1+len) < 0) {
            virConfError(VIR_ERR_CONFIG_UNSUPPORTED,
                         _("failed to allocate memory for %s config list"),
                         key);
            return -1;
        }
        for (i = 0, pp = p->list; pp; ++i, pp = pp->next) {
            if (pp->type != VIR_CONF_STRING) {
                virConfError(VIR_ERR_CONFIG_UNSUPPORTED,
                             _("remoteReadConfigFile: %s: %s:"
                               " must be a string or list of strings"),
                             filename, key);
                VIR_FREE(list);
                return -1;
            }
            list[i] = strdup (pp->str);
            if (list[i] == NULL) {
                int j;
                for (j = 0 ; j < i ; j++)
                    VIR_FREE(list[j]);
                VIR_FREE(list);
                virConfError(VIR_ERR_CONFIG_UNSUPPORTED,
                             _("failed to allocate memory for %s config list value"),
                             key);
                return -1;
            }

        }
        list[i] = NULL;
        break;
    }

    default:
        virConfError(VIR_ERR_CONFIG_UNSUPPORTED,
                     _("remoteReadConfigFile: %s: %s:"
                       " must be a string or list of strings"),
                     filename, key);
        return -1;
    }

    *list_arg = list;
    return 0;
}