1 /*
2 * Copyright 2011 The Chromium Authors, All Rights Reserved.
3 * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
4 *
5 * util_is_printable_string contributed by
6 * Pantelis Antoniou <pantelis.antoniou AT gmail.com>
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 of the
11 * License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but 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 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 * USA
22 */
23
24 #include <ctype.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <stdarg.h>
28 #include <string.h>
29 #include <assert.h>
30
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34
35 #include "libfdt.h"
36 #include "util.h"
37
xstrdup(const char * s)38 char *xstrdup(const char *s)
39 {
40 int len = strlen(s) + 1;
41 char *dup = xmalloc(len);
42
43 memcpy(dup, s, len);
44
45 return dup;
46 }
47
join_path(const char * path,const char * name)48 char *join_path(const char *path, const char *name)
49 {
50 int lenp = strlen(path);
51 int lenn = strlen(name);
52 int len;
53 int needslash = 1;
54 char *str;
55
56 len = lenp + lenn + 2;
57 if ((lenp > 0) && (path[lenp-1] == '/')) {
58 needslash = 0;
59 len--;
60 }
61
62 str = xmalloc(len);
63 memcpy(str, path, lenp);
64 if (needslash) {
65 str[lenp] = '/';
66 lenp++;
67 }
68 memcpy(str+lenp, name, lenn+1);
69 return str;
70 }
71
util_is_printable_string(const void * data,int len)72 int util_is_printable_string(const void *data, int len)
73 {
74 const char *s = data;
75 const char *ss;
76
77 /* zero length is not */
78 if (len == 0)
79 return 0;
80
81 /* must terminate with zero */
82 if (s[len - 1] != '\0')
83 return 0;
84
85 ss = s;
86 while (*s && isprint(*s))
87 s++;
88
89 /* not zero, or not done yet */
90 if (*s != '\0' || (s + 1 - ss) < len)
91 return 0;
92
93 return 1;
94 }
95
96 /*
97 * Parse a octal encoded character starting at index i in string s. The
98 * resulting character will be returned and the index i will be updated to
99 * point at the character directly after the end of the encoding, this may be
100 * the '\0' terminator of the string.
101 */
get_oct_char(const char * s,int * i)102 static char get_oct_char(const char *s, int *i)
103 {
104 char x[4];
105 char *endx;
106 long val;
107
108 x[3] = '\0';
109 strncpy(x, s + *i, 3);
110
111 val = strtol(x, &endx, 8);
112
113 assert(endx > x);
114
115 (*i) += endx - x;
116 return val;
117 }
118
119 /*
120 * Parse a hexadecimal encoded character starting at index i in string s. The
121 * resulting character will be returned and the index i will be updated to
122 * point at the character directly after the end of the encoding, this may be
123 * the '\0' terminator of the string.
124 */
get_hex_char(const char * s,int * i)125 static char get_hex_char(const char *s, int *i)
126 {
127 char x[3];
128 char *endx;
129 long val;
130
131 x[2] = '\0';
132 strncpy(x, s + *i, 2);
133
134 val = strtol(x, &endx, 16);
135 if (!(endx > x))
136 die("\\x used with no following hex digits\n");
137
138 (*i) += endx - x;
139 return val;
140 }
141
get_escape_char(const char * s,int * i)142 char get_escape_char(const char *s, int *i)
143 {
144 char c = s[*i];
145 int j = *i + 1;
146 char val;
147
148 assert(c);
149 switch (c) {
150 case 'a':
151 val = '\a';
152 break;
153 case 'b':
154 val = '\b';
155 break;
156 case 't':
157 val = '\t';
158 break;
159 case 'n':
160 val = '\n';
161 break;
162 case 'v':
163 val = '\v';
164 break;
165 case 'f':
166 val = '\f';
167 break;
168 case 'r':
169 val = '\r';
170 break;
171 case '0':
172 case '1':
173 case '2':
174 case '3':
175 case '4':
176 case '5':
177 case '6':
178 case '7':
179 j--; /* need to re-read the first digit as
180 * part of the octal value */
181 val = get_oct_char(s, &j);
182 break;
183 case 'x':
184 val = get_hex_char(s, &j);
185 break;
186 default:
187 val = c;
188 }
189
190 (*i) = j;
191 return val;
192 }
193
utilfdt_read_err(const char * filename,char ** buffp)194 int utilfdt_read_err(const char *filename, char **buffp)
195 {
196 int fd = 0; /* assume stdin */
197 char *buf = NULL;
198 off_t bufsize = 1024, offset = 0;
199 int ret = 0;
200
201 *buffp = NULL;
202 if (strcmp(filename, "-") != 0) {
203 fd = open(filename, O_RDONLY);
204 if (fd < 0)
205 return errno;
206 }
207
208 /* Loop until we have read everything */
209 buf = malloc(bufsize);
210 do {
211 /* Expand the buffer to hold the next chunk */
212 if (offset == bufsize) {
213 bufsize *= 2;
214 buf = realloc(buf, bufsize);
215 if (!buf) {
216 ret = ENOMEM;
217 break;
218 }
219 }
220
221 ret = read(fd, &buf[offset], bufsize - offset);
222 if (ret < 0) {
223 ret = errno;
224 break;
225 }
226 offset += ret;
227 } while (ret != 0);
228
229 /* Clean up, including closing stdin; return errno on error */
230 close(fd);
231 if (ret)
232 free(buf);
233 else
234 *buffp = buf;
235 return ret;
236 }
237
utilfdt_read(const char * filename)238 char *utilfdt_read(const char *filename)
239 {
240 char *buff;
241 int ret = utilfdt_read_err(filename, &buff);
242
243 if (ret) {
244 fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
245 strerror(ret));
246 return NULL;
247 }
248 /* Successful read */
249 return buff;
250 }
251
utilfdt_write_err(const char * filename,const void * blob)252 int utilfdt_write_err(const char *filename, const void *blob)
253 {
254 int fd = 1; /* assume stdout */
255 int totalsize;
256 int offset;
257 int ret = 0;
258 const char *ptr = blob;
259
260 if (strcmp(filename, "-") != 0) {
261 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
262 if (fd < 0)
263 return errno;
264 }
265
266 totalsize = fdt_totalsize(blob);
267 offset = 0;
268
269 while (offset < totalsize) {
270 ret = write(fd, ptr + offset, totalsize - offset);
271 if (ret < 0) {
272 ret = -errno;
273 break;
274 }
275 offset += ret;
276 }
277 /* Close the file/stdin; return errno on error */
278 if (fd != 1)
279 close(fd);
280 return ret < 0 ? -ret : 0;
281 }
282
283
utilfdt_write(const char * filename,const void * blob)284 int utilfdt_write(const char *filename, const void *blob)
285 {
286 int ret = utilfdt_write_err(filename, blob);
287
288 if (ret) {
289 fprintf(stderr, "Couldn't write blob to '%s': %s\n", filename,
290 strerror(ret));
291 }
292 return ret ? -1 : 0;
293 }
294
utilfdt_decode_type(const char * fmt,int * type,int * size)295 int utilfdt_decode_type(const char *fmt, int *type, int *size)
296 {
297 int qualifier = 0;
298
299 if (!*fmt)
300 return -1;
301
302 /* get the conversion qualifier */
303 *size = -1;
304 if (strchr("hlLb", *fmt)) {
305 qualifier = *fmt++;
306 if (qualifier == *fmt) {
307 switch (*fmt++) {
308 /* TODO: case 'l': qualifier = 'L'; break;*/
309 case 'h':
310 qualifier = 'b';
311 break;
312 }
313 }
314 }
315
316 /* we should now have a type */
317 if ((*fmt == '\0') || !strchr("iuxs", *fmt))
318 return -1;
319
320 /* convert qualifier (bhL) to byte size */
321 if (*fmt != 's')
322 *size = qualifier == 'b' ? 1 :
323 qualifier == 'h' ? 2 :
324 qualifier == 'l' ? 4 : -1;
325 *type = *fmt++;
326
327 /* that should be it! */
328 if (*fmt)
329 return -1;
330 return 0;
331 }
332