Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
util.c
Go to the documentation of this file.
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 
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 
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 
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  */
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  */
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 
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 
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 
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 
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 
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 
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 }