1 /* parse_util.c - the opkg package management system
2 
3    Copyright (C) 2009 Ubiq Technologies <graham.gower@gmail.com>
4 
5    Steven M. Ayer
6    Copyright (C) 2002 Compaq Computer Corporation
7 
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12 
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17 */
18 
19 #include <ctype.h>
20 
21 #include "opkg_utils.h"
22 #include "libbb/libbb.h"
23 
24 #include "parse_util.h"
25 #include "pkg_parse.h"
26 
is_field(const char * type,const char * line)27 int is_field(const char *type, const char *line)
28 {
29 	if (!strncmp(line, type, strlen(type)))
30 		return 1;
31 	return 0;
32 }
33 
parse_simple(const char * type,const char * line)34 char *parse_simple(const char *type, const char *line)
35 {
36 	char *field = trim_xstrdup(line + strlen(type) + 1);
37 	if (strlen(field) == 0) {
38 		free(field);
39 		return NULL;
40 	}
41 	return field;
42 }
43 
44 /*
45  * Parse a comma separated string into an array.
46  */
parse_list(const char * raw,unsigned int * count,const char sep,int skip_field)47 char **parse_list(const char *raw, unsigned int *count, const char sep,
48 		  int skip_field)
49 {
50 	char **depends = NULL;
51 	const char *start, *end;
52 	int line_count = 0;
53 
54 	/* skip past the "Field:" marker */
55 	if (!skip_field) {
56 		while (*raw && *raw != ':')
57 			raw++;
58 		raw++;
59 	}
60 
61 	if (line_is_blank(raw)) {
62 		*count = line_count;
63 		return NULL;
64 	}
65 
66 	while (*raw) {
67 		depends = xrealloc(depends, sizeof(char *) * (line_count + 1));
68 
69 		while (isspace(*raw))
70 			raw++;
71 
72 		start = raw;
73 		while (*raw != sep && *raw)
74 			raw++;
75 		end = raw;
76 
77 		while (end > start && isspace(*end))
78 			end--;
79 
80 		if (sep == ' ')
81 			end++;
82 
83 		depends[line_count] = xstrndup(start, end - start);
84 
85 		line_count++;
86 		if (*raw == sep)
87 			raw++;
88 	}
89 
90 	*count = line_count;
91 	return depends;
92 }
93 
94 int
parse_from_stream_nomalloc(parse_line_t parse_line,void * item,FILE * fp,uint mask,char ** buf0,size_t buf0len)95 parse_from_stream_nomalloc(parse_line_t parse_line, void *item, FILE * fp,
96 			   uint mask, char **buf0, size_t buf0len)
97 {
98 	int ret, lineno;
99 	char *buf, *nl;
100 	size_t buflen;
101 
102 	lineno = 1;
103 	ret = 0;
104 
105 	buflen = buf0len;
106 	buf = *buf0;
107 	buf[0] = '\0';
108 
109 	while (1) {
110 		if (fgets(buf, (int)buflen, fp) == NULL) {
111 			if (ferror(fp)) {
112 				opkg_perror(ERROR, "fgets");
113 				ret = -1;
114 			} else if (strlen(*buf0) == buf0len - 1) {
115 				opkg_msg(ERROR, "Missing new line character"
116 					 " at end of file!\n");
117 				parse_line(item, *buf0, mask);
118 			}
119 			break;
120 		}
121 
122 		nl = strchr(buf, '\n');
123 		if (nl == NULL) {
124 			if (strlen(buf) < buflen - 1) {
125 				/*
126 				 * Line could be exactly buflen-1 long and
127 				 * missing a newline, but we won't know until
128 				 * fgets fails to read more data.
129 				 */
130 				opkg_msg(ERROR, "Missing new line character"
131 					 " at end of file!\n");
132 				parse_line(item, *buf0, mask);
133 				break;
134 			}
135 			if (buf0len >= EXCESSIVE_LINE_LEN) {
136 				opkg_msg(ERROR, "Excessively long line at "
137 					 "%d. Corrupt file?\n", lineno);
138 				ret = -1;
139 				break;
140 			}
141 
142 			/*
143 			 * Realloc and point buf past the data already read,
144 			 * at the NULL terminator inserted by fgets.
145 			 * |<--------------- buf0len ----------------->|
146 			 * |                     |<------- buflen ---->|
147 			 * |---------------------|---------------------|
148 			 * buf0                   buf
149 			 */
150 			buflen = buf0len + 1;
151 			buf0len *= 2;
152 			*buf0 = xrealloc(*buf0, buf0len);
153 			buf = *buf0 + buflen - 2;
154 
155 			continue;
156 		}
157 
158 		*nl = '\0';
159 
160 		lineno++;
161 
162 		if (parse_line(item, *buf0, mask))
163 			break;
164 
165 		buf = *buf0;
166 		buflen = buf0len;
167 		buf[0] = '\0';
168 	}
169 
170 	return ret;
171 }
172