summaryrefslogtreecommitdiff
path: root/util.c
blob: c0f4451debf0946374314c87e50507bcf30eb107 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*
 * libuci - Library for the Unified Configuration Interface
 * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 2.1
 * as published by the Free Software Foundation
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

/*
 * This file contains wrappers to standard functions, which
 * throw exceptions upon failure.
 */
#include <stdbool.h>
#include <ctype.h>

static void *uci_malloc(struct uci_context *ctx, size_t size)
{
	void *ptr;

	ptr = malloc(size);
	if (!ptr)
		UCI_THROW(ctx, UCI_ERR_MEM);
	memset(ptr, 0, size);

	return ptr;
}

static void *uci_realloc(struct uci_context *ctx, void *ptr, size_t size)
{
	ptr = realloc(ptr, size);
	if (!ptr)
		UCI_THROW(ctx, UCI_ERR_MEM);

	return ptr;
}

static char *uci_strdup(struct uci_context *ctx, const char *str)
{
	char *ptr;

	ptr = strdup(str);
	if (!ptr)
		UCI_THROW(ctx, UCI_ERR_MEM);

	return ptr;
}

static bool uci_validate_name(const char *str)
{
	if (!*str)
		return false;

	while (*str) {
		if (!isalnum(*str) && (*str != '_'))
			return false;
		str++;
	}
	return true;
}

int uci_parse_tuple(struct uci_context *ctx, char *str, char **package, char **section, char **option, char **value)
{
	char *last = NULL;

	UCI_HANDLE_ERR(ctx);
	UCI_ASSERT(ctx, str && package && section && option);

	*package = strtok(str, ".");
	if (!*package || !uci_validate_name(*package))
		goto error;

	last = *package;
	*section = strtok(NULL, ".");
	if (!*section)
		goto lastval;

	last = *section;
	*option = strtok(NULL, ".");
	if (!*option)
		goto lastval;

	last = *option;

lastval:
	last = strchr(last, '=');
	if (last) {
		if (!value)
			goto error;

		*last = 0;
		last++;
		if (!*last)
			goto error;
		*value = last;
	}

	if (*section && !uci_validate_name(*section))
		goto error;
	if (*option && !uci_validate_name(*option))
		goto error;

	goto done;

error:
	UCI_THROW(ctx, UCI_ERR_PARSE);

done:
	return 0;
}