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 } 332