xref: /aosp_15_r20/external/selinux/libsemanage/src/parse_utils.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker /* Copyright (C) 2005 Red Hat, Inc. */
2*2d543d20SAndroid Build Coastguard Worker 
3*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
4*2d543d20SAndroid Build Coastguard Worker #include <stdio_ext.h>
5*2d543d20SAndroid Build Coastguard Worker #include <errno.h>
6*2d543d20SAndroid Build Coastguard Worker #include <string.h>
7*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
8*2d543d20SAndroid Build Coastguard Worker #include <ctype.h>
9*2d543d20SAndroid Build Coastguard Worker #include <semanage/handle.h>
10*2d543d20SAndroid Build Coastguard Worker #include "parse_utils.h"
11*2d543d20SAndroid Build Coastguard Worker #include "debug.h"
12*2d543d20SAndroid Build Coastguard Worker 
parse_init(semanage_handle_t * handle,const char * filename,void * parse_arg,parse_info_t ** info)13*2d543d20SAndroid Build Coastguard Worker int parse_init(semanage_handle_t * handle,
14*2d543d20SAndroid Build Coastguard Worker 	       const char *filename, void *parse_arg, parse_info_t ** info)
15*2d543d20SAndroid Build Coastguard Worker {
16*2d543d20SAndroid Build Coastguard Worker 
17*2d543d20SAndroid Build Coastguard Worker 	parse_info_t *tmp_info = (parse_info_t *) malloc(sizeof(parse_info_t));
18*2d543d20SAndroid Build Coastguard Worker 
19*2d543d20SAndroid Build Coastguard Worker 	if (!tmp_info) {
20*2d543d20SAndroid Build Coastguard Worker 		ERR(handle,
21*2d543d20SAndroid Build Coastguard Worker 		    "out of memory, could not allocate parse structure");
22*2d543d20SAndroid Build Coastguard Worker 		return STATUS_ERR;
23*2d543d20SAndroid Build Coastguard Worker 	}
24*2d543d20SAndroid Build Coastguard Worker 
25*2d543d20SAndroid Build Coastguard Worker 	tmp_info->filename = filename;
26*2d543d20SAndroid Build Coastguard Worker 	tmp_info->file_stream = NULL;
27*2d543d20SAndroid Build Coastguard Worker 	tmp_info->working_copy = NULL;
28*2d543d20SAndroid Build Coastguard Worker 	tmp_info->orig_line = NULL;
29*2d543d20SAndroid Build Coastguard Worker 	tmp_info->ptr = NULL;
30*2d543d20SAndroid Build Coastguard Worker 	tmp_info->lineno = 0;
31*2d543d20SAndroid Build Coastguard Worker 	tmp_info->parse_arg = parse_arg;
32*2d543d20SAndroid Build Coastguard Worker 
33*2d543d20SAndroid Build Coastguard Worker 	*info = tmp_info;
34*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
35*2d543d20SAndroid Build Coastguard Worker }
36*2d543d20SAndroid Build Coastguard Worker 
parse_release(parse_info_t * info)37*2d543d20SAndroid Build Coastguard Worker void parse_release(parse_info_t * info)
38*2d543d20SAndroid Build Coastguard Worker {
39*2d543d20SAndroid Build Coastguard Worker 
40*2d543d20SAndroid Build Coastguard Worker 	parse_close(info);
41*2d543d20SAndroid Build Coastguard Worker 	parse_dispose_line(info);
42*2d543d20SAndroid Build Coastguard Worker 	free(info);
43*2d543d20SAndroid Build Coastguard Worker }
44*2d543d20SAndroid Build Coastguard Worker 
parse_open(semanage_handle_t * handle,parse_info_t * info)45*2d543d20SAndroid Build Coastguard Worker int parse_open(semanage_handle_t * handle, parse_info_t * info)
46*2d543d20SAndroid Build Coastguard Worker {
47*2d543d20SAndroid Build Coastguard Worker 
48*2d543d20SAndroid Build Coastguard Worker 	info->file_stream = fopen(info->filename, "r");
49*2d543d20SAndroid Build Coastguard Worker 	if (!info->file_stream && (errno != ENOENT)) {
50*2d543d20SAndroid Build Coastguard Worker 		ERR(handle, "could not open file %s: %s",
51*2d543d20SAndroid Build Coastguard Worker 		    info->filename, strerror(errno));
52*2d543d20SAndroid Build Coastguard Worker 		return STATUS_ERR;
53*2d543d20SAndroid Build Coastguard Worker 	}
54*2d543d20SAndroid Build Coastguard Worker 	if (info->file_stream)
55*2d543d20SAndroid Build Coastguard Worker 		__fsetlocking(info->file_stream, FSETLOCKING_BYCALLER);
56*2d543d20SAndroid Build Coastguard Worker 
57*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
58*2d543d20SAndroid Build Coastguard Worker }
59*2d543d20SAndroid Build Coastguard Worker 
parse_close(parse_info_t * info)60*2d543d20SAndroid Build Coastguard Worker void parse_close(parse_info_t * info)
61*2d543d20SAndroid Build Coastguard Worker {
62*2d543d20SAndroid Build Coastguard Worker 
63*2d543d20SAndroid Build Coastguard Worker 	if (info->file_stream)
64*2d543d20SAndroid Build Coastguard Worker 		fclose(info->file_stream);
65*2d543d20SAndroid Build Coastguard Worker 	info->file_stream = NULL;
66*2d543d20SAndroid Build Coastguard Worker }
67*2d543d20SAndroid Build Coastguard Worker 
parse_dispose_line(parse_info_t * info)68*2d543d20SAndroid Build Coastguard Worker void parse_dispose_line(parse_info_t * info)
69*2d543d20SAndroid Build Coastguard Worker {
70*2d543d20SAndroid Build Coastguard Worker 	if (info->orig_line) {
71*2d543d20SAndroid Build Coastguard Worker 		free(info->orig_line);
72*2d543d20SAndroid Build Coastguard Worker 		info->orig_line = NULL;
73*2d543d20SAndroid Build Coastguard Worker 	}
74*2d543d20SAndroid Build Coastguard Worker 
75*2d543d20SAndroid Build Coastguard Worker 	if (info->working_copy) {
76*2d543d20SAndroid Build Coastguard Worker 		free(info->working_copy);
77*2d543d20SAndroid Build Coastguard Worker 		info->working_copy = NULL;
78*2d543d20SAndroid Build Coastguard Worker 	}
79*2d543d20SAndroid Build Coastguard Worker 
80*2d543d20SAndroid Build Coastguard Worker 	info->ptr = NULL;
81*2d543d20SAndroid Build Coastguard Worker }
82*2d543d20SAndroid Build Coastguard Worker 
parse_skip_space(semanage_handle_t * handle,parse_info_t * info)83*2d543d20SAndroid Build Coastguard Worker int parse_skip_space(semanage_handle_t * handle, parse_info_t * info)
84*2d543d20SAndroid Build Coastguard Worker {
85*2d543d20SAndroid Build Coastguard Worker 
86*2d543d20SAndroid Build Coastguard Worker 	size_t buf_len = 0;
87*2d543d20SAndroid Build Coastguard Worker 	ssize_t len;
88*2d543d20SAndroid Build Coastguard Worker 	int lineno = info->lineno;
89*2d543d20SAndroid Build Coastguard Worker 	char *buffer = NULL;
90*2d543d20SAndroid Build Coastguard Worker 	char *ptr;
91*2d543d20SAndroid Build Coastguard Worker 
92*2d543d20SAndroid Build Coastguard Worker 	if (info->ptr) {
93*2d543d20SAndroid Build Coastguard Worker 		while (*(info->ptr) && isspace(*(info->ptr)))
94*2d543d20SAndroid Build Coastguard Worker 			info->ptr++;
95*2d543d20SAndroid Build Coastguard Worker 
96*2d543d20SAndroid Build Coastguard Worker 		if (*(info->ptr))
97*2d543d20SAndroid Build Coastguard Worker 			return STATUS_SUCCESS;
98*2d543d20SAndroid Build Coastguard Worker 	}
99*2d543d20SAndroid Build Coastguard Worker 
100*2d543d20SAndroid Build Coastguard Worker 	parse_dispose_line(info);
101*2d543d20SAndroid Build Coastguard Worker 
102*2d543d20SAndroid Build Coastguard Worker 	while (info->file_stream &&
103*2d543d20SAndroid Build Coastguard Worker 	       ((len = getline(&buffer, &buf_len, info->file_stream)) > 0)) {
104*2d543d20SAndroid Build Coastguard Worker 
105*2d543d20SAndroid Build Coastguard Worker 		lineno++;
106*2d543d20SAndroid Build Coastguard Worker 
107*2d543d20SAndroid Build Coastguard Worker 		/* Eat newline, preceding whitespace */
108*2d543d20SAndroid Build Coastguard Worker 		if (buffer[len - 1] == '\n')
109*2d543d20SAndroid Build Coastguard Worker 			buffer[len - 1] = '\0';
110*2d543d20SAndroid Build Coastguard Worker 
111*2d543d20SAndroid Build Coastguard Worker 		ptr = buffer;
112*2d543d20SAndroid Build Coastguard Worker 		while (*ptr && isspace(*ptr))
113*2d543d20SAndroid Build Coastguard Worker 			ptr++;
114*2d543d20SAndroid Build Coastguard Worker 
115*2d543d20SAndroid Build Coastguard Worker 		/* Skip comments and blank lines */
116*2d543d20SAndroid Build Coastguard Worker 		if ((*ptr) && *ptr != '#') {
117*2d543d20SAndroid Build Coastguard Worker 			char *tmp = strdup(buffer);
118*2d543d20SAndroid Build Coastguard Worker 			if (!tmp)
119*2d543d20SAndroid Build Coastguard Worker 				goto omem;
120*2d543d20SAndroid Build Coastguard Worker 
121*2d543d20SAndroid Build Coastguard Worker 			info->lineno = lineno;
122*2d543d20SAndroid Build Coastguard Worker 			info->working_copy = buffer;
123*2d543d20SAndroid Build Coastguard Worker 			info->orig_line = tmp;
124*2d543d20SAndroid Build Coastguard Worker 			info->ptr = ptr;
125*2d543d20SAndroid Build Coastguard Worker 
126*2d543d20SAndroid Build Coastguard Worker 			return STATUS_SUCCESS;
127*2d543d20SAndroid Build Coastguard Worker 		}
128*2d543d20SAndroid Build Coastguard Worker 	}
129*2d543d20SAndroid Build Coastguard Worker 
130*2d543d20SAndroid Build Coastguard Worker 	free(buffer);
131*2d543d20SAndroid Build Coastguard Worker 	buffer = NULL;
132*2d543d20SAndroid Build Coastguard Worker 
133*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
134*2d543d20SAndroid Build Coastguard Worker 
135*2d543d20SAndroid Build Coastguard Worker       omem:
136*2d543d20SAndroid Build Coastguard Worker 	ERR(handle, "out of memory, could not allocate buffer");
137*2d543d20SAndroid Build Coastguard Worker 	free(buffer);
138*2d543d20SAndroid Build Coastguard Worker 	return STATUS_ERR;
139*2d543d20SAndroid Build Coastguard Worker }
140*2d543d20SAndroid Build Coastguard Worker 
parse_assert_noeof(semanage_handle_t * handle,parse_info_t * info)141*2d543d20SAndroid Build Coastguard Worker int parse_assert_noeof(semanage_handle_t * handle, parse_info_t * info)
142*2d543d20SAndroid Build Coastguard Worker {
143*2d543d20SAndroid Build Coastguard Worker 
144*2d543d20SAndroid Build Coastguard Worker 	if (!info->ptr) {
145*2d543d20SAndroid Build Coastguard Worker 		ERR(handle, "unexpected end of file (%s: %u)",
146*2d543d20SAndroid Build Coastguard Worker 		    info->filename, info->lineno);
147*2d543d20SAndroid Build Coastguard Worker 		return STATUS_ERR;
148*2d543d20SAndroid Build Coastguard Worker 	}
149*2d543d20SAndroid Build Coastguard Worker 
150*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
151*2d543d20SAndroid Build Coastguard Worker }
152*2d543d20SAndroid Build Coastguard Worker 
parse_assert_space(semanage_handle_t * handle,parse_info_t * info)153*2d543d20SAndroid Build Coastguard Worker int parse_assert_space(semanage_handle_t * handle, parse_info_t * info)
154*2d543d20SAndroid Build Coastguard Worker {
155*2d543d20SAndroid Build Coastguard Worker 
156*2d543d20SAndroid Build Coastguard Worker 	if (parse_assert_noeof(handle, info) < 0)
157*2d543d20SAndroid Build Coastguard Worker 		return STATUS_ERR;
158*2d543d20SAndroid Build Coastguard Worker 
159*2d543d20SAndroid Build Coastguard Worker 	if (*(info->ptr) && !isspace(*(info->ptr))) {
160*2d543d20SAndroid Build Coastguard Worker 		ERR(handle, "missing whitespace (%s: %u):\n%s",
161*2d543d20SAndroid Build Coastguard Worker 		    info->filename, info->lineno, info->orig_line);
162*2d543d20SAndroid Build Coastguard Worker 		return STATUS_ERR;
163*2d543d20SAndroid Build Coastguard Worker 	}
164*2d543d20SAndroid Build Coastguard Worker 
165*2d543d20SAndroid Build Coastguard Worker 	if (parse_skip_space(handle, info) < 0)
166*2d543d20SAndroid Build Coastguard Worker 		return STATUS_ERR;
167*2d543d20SAndroid Build Coastguard Worker 
168*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
169*2d543d20SAndroid Build Coastguard Worker }
170*2d543d20SAndroid Build Coastguard Worker 
parse_assert_ch(semanage_handle_t * handle,parse_info_t * info,const char ch)171*2d543d20SAndroid Build Coastguard Worker int parse_assert_ch(semanage_handle_t * handle,
172*2d543d20SAndroid Build Coastguard Worker 		    parse_info_t * info, const char ch)
173*2d543d20SAndroid Build Coastguard Worker {
174*2d543d20SAndroid Build Coastguard Worker 
175*2d543d20SAndroid Build Coastguard Worker 	if (parse_assert_noeof(handle, info) < 0)
176*2d543d20SAndroid Build Coastguard Worker 		return STATUS_ERR;
177*2d543d20SAndroid Build Coastguard Worker 
178*2d543d20SAndroid Build Coastguard Worker 	if (*(info->ptr) != ch) {
179*2d543d20SAndroid Build Coastguard Worker 		ERR(handle, "expected character \'%c\', but found \'%c\' "
180*2d543d20SAndroid Build Coastguard Worker 		    "(%s: %u):\n%s", ch, *(info->ptr), info->filename,
181*2d543d20SAndroid Build Coastguard Worker 		    info->lineno, info->orig_line);
182*2d543d20SAndroid Build Coastguard Worker 		return STATUS_ERR;
183*2d543d20SAndroid Build Coastguard Worker 	}
184*2d543d20SAndroid Build Coastguard Worker 
185*2d543d20SAndroid Build Coastguard Worker 	info->ptr++;
186*2d543d20SAndroid Build Coastguard Worker 
187*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
188*2d543d20SAndroid Build Coastguard Worker }
189*2d543d20SAndroid Build Coastguard Worker 
parse_assert_str(semanage_handle_t * handle,parse_info_t * info,const char * assert_str)190*2d543d20SAndroid Build Coastguard Worker int parse_assert_str(semanage_handle_t * handle,
191*2d543d20SAndroid Build Coastguard Worker 		     parse_info_t * info, const char *assert_str)
192*2d543d20SAndroid Build Coastguard Worker {
193*2d543d20SAndroid Build Coastguard Worker 
194*2d543d20SAndroid Build Coastguard Worker 	size_t len = strlen(assert_str);
195*2d543d20SAndroid Build Coastguard Worker 
196*2d543d20SAndroid Build Coastguard Worker 	if (parse_assert_noeof(handle, info) < 0)
197*2d543d20SAndroid Build Coastguard Worker 		return STATUS_ERR;
198*2d543d20SAndroid Build Coastguard Worker 
199*2d543d20SAndroid Build Coastguard Worker 	if (strncmp(info->ptr, assert_str, len)) {
200*2d543d20SAndroid Build Coastguard Worker 		ERR(handle, "experted string \"%s\", but found \"%s\" "
201*2d543d20SAndroid Build Coastguard Worker 		    "(%s: %u):\n%s", assert_str, info->ptr,
202*2d543d20SAndroid Build Coastguard Worker 		    info->filename, info->lineno, info->orig_line);
203*2d543d20SAndroid Build Coastguard Worker 
204*2d543d20SAndroid Build Coastguard Worker 		return STATUS_ERR;
205*2d543d20SAndroid Build Coastguard Worker 	}
206*2d543d20SAndroid Build Coastguard Worker 
207*2d543d20SAndroid Build Coastguard Worker 	info->ptr += len;
208*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
209*2d543d20SAndroid Build Coastguard Worker }
210*2d543d20SAndroid Build Coastguard Worker 
parse_optional_ch(parse_info_t * info,const char ch)211*2d543d20SAndroid Build Coastguard Worker int parse_optional_ch(parse_info_t * info, const char ch)
212*2d543d20SAndroid Build Coastguard Worker {
213*2d543d20SAndroid Build Coastguard Worker 
214*2d543d20SAndroid Build Coastguard Worker 	if (!info->ptr)
215*2d543d20SAndroid Build Coastguard Worker 		return STATUS_NODATA;
216*2d543d20SAndroid Build Coastguard Worker 	if (*(info->ptr) != ch)
217*2d543d20SAndroid Build Coastguard Worker 		return STATUS_NODATA;
218*2d543d20SAndroid Build Coastguard Worker 
219*2d543d20SAndroid Build Coastguard Worker 	info->ptr++;
220*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
221*2d543d20SAndroid Build Coastguard Worker }
222*2d543d20SAndroid Build Coastguard Worker 
parse_optional_str(parse_info_t * info,const char * str)223*2d543d20SAndroid Build Coastguard Worker int parse_optional_str(parse_info_t * info, const char *str)
224*2d543d20SAndroid Build Coastguard Worker {
225*2d543d20SAndroid Build Coastguard Worker 	size_t len = strlen(str);
226*2d543d20SAndroid Build Coastguard Worker 
227*2d543d20SAndroid Build Coastguard Worker 	if (strncmp(info->ptr, str, len))
228*2d543d20SAndroid Build Coastguard Worker 		return STATUS_NODATA;
229*2d543d20SAndroid Build Coastguard Worker 
230*2d543d20SAndroid Build Coastguard Worker 	info->ptr += len;
231*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
232*2d543d20SAndroid Build Coastguard Worker }
233*2d543d20SAndroid Build Coastguard Worker 
parse_fetch_int(semanage_handle_t * handle,parse_info_t * info,int * num,char delim)234*2d543d20SAndroid Build Coastguard Worker int parse_fetch_int(semanage_handle_t * handle,
235*2d543d20SAndroid Build Coastguard Worker 		    parse_info_t * info, int *num, char delim)
236*2d543d20SAndroid Build Coastguard Worker {
237*2d543d20SAndroid Build Coastguard Worker 
238*2d543d20SAndroid Build Coastguard Worker 	char *str = NULL;
239*2d543d20SAndroid Build Coastguard Worker 	char *test = NULL;
240*2d543d20SAndroid Build Coastguard Worker 	int value = 0;
241*2d543d20SAndroid Build Coastguard Worker 
242*2d543d20SAndroid Build Coastguard Worker 	if (parse_fetch_string(handle, info, &str, delim, 0) < 0)
243*2d543d20SAndroid Build Coastguard Worker 		goto err;
244*2d543d20SAndroid Build Coastguard Worker 
245*2d543d20SAndroid Build Coastguard Worker 	if (!isdigit((int)*str)) {
246*2d543d20SAndroid Build Coastguard Worker 		ERR(handle, "expected a numeric value: (%s: %u)\n%s",
247*2d543d20SAndroid Build Coastguard Worker 		    info->filename, info->lineno, info->orig_line);
248*2d543d20SAndroid Build Coastguard Worker 		goto err;
249*2d543d20SAndroid Build Coastguard Worker 	}
250*2d543d20SAndroid Build Coastguard Worker 
251*2d543d20SAndroid Build Coastguard Worker 	value = strtol(str, &test, 10);
252*2d543d20SAndroid Build Coastguard Worker 	if (*test != '\0') {
253*2d543d20SAndroid Build Coastguard Worker 		ERR(handle, "could not parse numeric value \"%s\": "
254*2d543d20SAndroid Build Coastguard Worker 		    "(%s: %u)\n%s", str, info->filename,
255*2d543d20SAndroid Build Coastguard Worker 		    info->lineno, info->orig_line);
256*2d543d20SAndroid Build Coastguard Worker 		goto err;
257*2d543d20SAndroid Build Coastguard Worker 	}
258*2d543d20SAndroid Build Coastguard Worker 
259*2d543d20SAndroid Build Coastguard Worker 	*num = value;
260*2d543d20SAndroid Build Coastguard Worker 	free(str);
261*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
262*2d543d20SAndroid Build Coastguard Worker 
263*2d543d20SAndroid Build Coastguard Worker       err:
264*2d543d20SAndroid Build Coastguard Worker 	ERR(handle, "could not fetch numeric value");
265*2d543d20SAndroid Build Coastguard Worker 	free(str);
266*2d543d20SAndroid Build Coastguard Worker 	return STATUS_ERR;
267*2d543d20SAndroid Build Coastguard Worker }
268*2d543d20SAndroid Build Coastguard Worker 
parse_fetch_string(semanage_handle_t * handle,parse_info_t * info,char ** str,char delim,int allow_spaces)269*2d543d20SAndroid Build Coastguard Worker int parse_fetch_string(semanage_handle_t * handle,
270*2d543d20SAndroid Build Coastguard Worker 		       parse_info_t * info, char **str, char delim, int allow_spaces)
271*2d543d20SAndroid Build Coastguard Worker {
272*2d543d20SAndroid Build Coastguard Worker 
273*2d543d20SAndroid Build Coastguard Worker 	char *start = info->ptr;
274*2d543d20SAndroid Build Coastguard Worker 	int len = 0;
275*2d543d20SAndroid Build Coastguard Worker 	char *tmp_str = NULL;
276*2d543d20SAndroid Build Coastguard Worker 
277*2d543d20SAndroid Build Coastguard Worker 	if (parse_assert_noeof(handle, info) < 0)
278*2d543d20SAndroid Build Coastguard Worker 		goto err;
279*2d543d20SAndroid Build Coastguard Worker 
280*2d543d20SAndroid Build Coastguard Worker 	while (*(info->ptr) && (allow_spaces || !isspace(*(info->ptr))) &&
281*2d543d20SAndroid Build Coastguard Worker 	       (*(info->ptr) != delim)) {
282*2d543d20SAndroid Build Coastguard Worker 		info->ptr++;
283*2d543d20SAndroid Build Coastguard Worker 		len++;
284*2d543d20SAndroid Build Coastguard Worker 	}
285*2d543d20SAndroid Build Coastguard Worker 
286*2d543d20SAndroid Build Coastguard Worker 	if (len == 0) {
287*2d543d20SAndroid Build Coastguard Worker 		ERR(handle, "expected non-empty string, but did not "
288*2d543d20SAndroid Build Coastguard Worker 		    "find one (%s: %u):\n%s", info->filename, info->lineno,
289*2d543d20SAndroid Build Coastguard Worker 		    info->orig_line);
290*2d543d20SAndroid Build Coastguard Worker 		goto err;
291*2d543d20SAndroid Build Coastguard Worker 	}
292*2d543d20SAndroid Build Coastguard Worker 
293*2d543d20SAndroid Build Coastguard Worker 	tmp_str = (char *)malloc(len + 1);
294*2d543d20SAndroid Build Coastguard Worker 	if (!tmp_str) {
295*2d543d20SAndroid Build Coastguard Worker 		ERR(handle, "out of memory");
296*2d543d20SAndroid Build Coastguard Worker 		goto err;
297*2d543d20SAndroid Build Coastguard Worker 	}
298*2d543d20SAndroid Build Coastguard Worker 
299*2d543d20SAndroid Build Coastguard Worker 	strncpy(tmp_str, start, len);
300*2d543d20SAndroid Build Coastguard Worker 	*(tmp_str + len) = '\0';
301*2d543d20SAndroid Build Coastguard Worker 	*str = tmp_str;
302*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
303*2d543d20SAndroid Build Coastguard Worker 
304*2d543d20SAndroid Build Coastguard Worker       err:
305*2d543d20SAndroid Build Coastguard Worker 	ERR(handle, "could not fetch string value");
306*2d543d20SAndroid Build Coastguard Worker 	return STATUS_ERR;
307*2d543d20SAndroid Build Coastguard Worker }
308