util.c revision 238742
1204433Sraj/* 2238742Simp * Copyright 2011 The Chromium Authors, All Rights Reserved. 3204433Sraj * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. 4204433Sraj * 5238742Simp * util_is_printable_string contributed by 6238742Simp * Pantelis Antoniou <pantelis.antoniou AT gmail.com> 7238742Simp * 8204433Sraj * This program is free software; you can redistribute it and/or 9204433Sraj * modify it under the terms of the GNU General Public License as 10204433Sraj * published by the Free Software Foundation; either version 2 of the 11204433Sraj * License, or (at your option) any later version. 12204433Sraj * 13204433Sraj * This program is distributed in the hope that it will be useful, 14204433Sraj * but WITHOUT ANY WARRANTY; without even the implied warranty of 15204433Sraj * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16204433Sraj * General Public License for more details. 17204433Sraj * 18204433Sraj * You should have received a copy of the GNU General Public License 19204433Sraj * along with this program; if not, write to the Free Software 20204433Sraj * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 21204433Sraj * USA 22204433Sraj */ 23204433Sraj 24238742Simp#include <ctype.h> 25238742Simp#include <stdio.h> 26238742Simp#include <stdlib.h> 27238742Simp#include <stdarg.h> 28238742Simp#include <string.h> 29238742Simp#include <assert.h> 30204433Sraj 31238742Simp#include <errno.h> 32238742Simp#include <fcntl.h> 33238742Simp#include <unistd.h> 34238742Simp 35238742Simp#include "libfdt.h" 36238742Simp#include "util.h" 37238742Simp 38204433Srajchar *xstrdup(const char *s) 39204433Sraj{ 40204433Sraj int len = strlen(s) + 1; 41204433Sraj char *dup = xmalloc(len); 42204433Sraj 43204433Sraj memcpy(dup, s, len); 44204433Sraj 45204433Sraj return dup; 46204433Sraj} 47238742Simp 48238742Simpchar *join_path(const char *path, const char *name) 49238742Simp{ 50238742Simp int lenp = strlen(path); 51238742Simp int lenn = strlen(name); 52238742Simp int len; 53238742Simp int needslash = 1; 54238742Simp char *str; 55238742Simp 56238742Simp len = lenp + lenn + 2; 57238742Simp if ((lenp > 0) && (path[lenp-1] == '/')) { 58238742Simp needslash = 0; 59238742Simp len--; 60238742Simp } 61238742Simp 62238742Simp str = xmalloc(len); 63238742Simp memcpy(str, path, lenp); 64238742Simp if (needslash) { 65238742Simp str[lenp] = '/'; 66238742Simp lenp++; 67238742Simp } 68238742Simp memcpy(str+lenp, name, lenn+1); 69238742Simp return str; 70238742Simp} 71238742Simp 72238742Simpint util_is_printable_string(const void *data, int len) 73238742Simp{ 74238742Simp const char *s = data; 75238742Simp const char *ss; 76238742Simp 77238742Simp /* zero length is not */ 78238742Simp if (len == 0) 79238742Simp return 0; 80238742Simp 81238742Simp /* must terminate with zero */ 82238742Simp if (s[len - 1] != '\0') 83238742Simp return 0; 84238742Simp 85238742Simp ss = s; 86238742Simp while (*s && isprint(*s)) 87238742Simp s++; 88238742Simp 89238742Simp /* not zero, or not done yet */ 90238742Simp if (*s != '\0' || (s + 1 - ss) < len) 91238742Simp return 0; 92238742Simp 93238742Simp return 1; 94238742Simp} 95238742Simp 96238742Simp/* 97238742Simp * Parse a octal encoded character starting at index i in string s. The 98238742Simp * resulting character will be returned and the index i will be updated to 99238742Simp * point at the character directly after the end of the encoding, this may be 100238742Simp * the '\0' terminator of the string. 101238742Simp */ 102238742Simpstatic char get_oct_char(const char *s, int *i) 103238742Simp{ 104238742Simp char x[4]; 105238742Simp char *endx; 106238742Simp long val; 107238742Simp 108238742Simp x[3] = '\0'; 109238742Simp strncpy(x, s + *i, 3); 110238742Simp 111238742Simp val = strtol(x, &endx, 8); 112238742Simp 113238742Simp assert(endx > x); 114238742Simp 115238742Simp (*i) += endx - x; 116238742Simp return val; 117238742Simp} 118238742Simp 119238742Simp/* 120238742Simp * Parse a hexadecimal encoded character starting at index i in string s. The 121238742Simp * resulting character will be returned and the index i will be updated to 122238742Simp * point at the character directly after the end of the encoding, this may be 123238742Simp * the '\0' terminator of the string. 124238742Simp */ 125238742Simpstatic char get_hex_char(const char *s, int *i) 126238742Simp{ 127238742Simp char x[3]; 128238742Simp char *endx; 129238742Simp long val; 130238742Simp 131238742Simp x[2] = '\0'; 132238742Simp strncpy(x, s + *i, 2); 133238742Simp 134238742Simp val = strtol(x, &endx, 16); 135238742Simp if (!(endx > x)) 136238742Simp die("\\x used with no following hex digits\n"); 137238742Simp 138238742Simp (*i) += endx - x; 139238742Simp return val; 140238742Simp} 141238742Simp 142238742Simpchar get_escape_char(const char *s, int *i) 143238742Simp{ 144238742Simp char c = s[*i]; 145238742Simp int j = *i + 1; 146238742Simp char val; 147238742Simp 148238742Simp assert(c); 149238742Simp switch (c) { 150238742Simp case 'a': 151238742Simp val = '\a'; 152238742Simp break; 153238742Simp case 'b': 154238742Simp val = '\b'; 155238742Simp break; 156238742Simp case 't': 157238742Simp val = '\t'; 158238742Simp break; 159238742Simp case 'n': 160238742Simp val = '\n'; 161238742Simp break; 162238742Simp case 'v': 163238742Simp val = '\v'; 164238742Simp break; 165238742Simp case 'f': 166238742Simp val = '\f'; 167238742Simp break; 168238742Simp case 'r': 169238742Simp val = '\r'; 170238742Simp break; 171238742Simp case '0': 172238742Simp case '1': 173238742Simp case '2': 174238742Simp case '3': 175238742Simp case '4': 176238742Simp case '5': 177238742Simp case '6': 178238742Simp case '7': 179238742Simp j--; /* need to re-read the first digit as 180238742Simp * part of the octal value */ 181238742Simp val = get_oct_char(s, &j); 182238742Simp break; 183238742Simp case 'x': 184238742Simp val = get_hex_char(s, &j); 185238742Simp break; 186238742Simp default: 187238742Simp val = c; 188238742Simp } 189238742Simp 190238742Simp (*i) = j; 191238742Simp return val; 192238742Simp} 193238742Simp 194238742Simpint utilfdt_read_err(const char *filename, char **buffp) 195238742Simp{ 196238742Simp int fd = 0; /* assume stdin */ 197238742Simp char *buf = NULL; 198238742Simp off_t bufsize = 1024, offset = 0; 199238742Simp int ret = 0; 200238742Simp 201238742Simp *buffp = NULL; 202238742Simp if (strcmp(filename, "-") != 0) { 203238742Simp fd = open(filename, O_RDONLY); 204238742Simp if (fd < 0) 205238742Simp return errno; 206238742Simp } 207238742Simp 208238742Simp /* Loop until we have read everything */ 209238742Simp buf = malloc(bufsize); 210238742Simp do { 211238742Simp /* Expand the buffer to hold the next chunk */ 212238742Simp if (offset == bufsize) { 213238742Simp bufsize *= 2; 214238742Simp buf = realloc(buf, bufsize); 215238742Simp if (!buf) { 216238742Simp ret = ENOMEM; 217238742Simp break; 218238742Simp } 219238742Simp } 220238742Simp 221238742Simp ret = read(fd, &buf[offset], bufsize - offset); 222238742Simp if (ret < 0) { 223238742Simp ret = errno; 224238742Simp break; 225238742Simp } 226238742Simp offset += ret; 227238742Simp } while (ret != 0); 228238742Simp 229238742Simp /* Clean up, including closing stdin; return errno on error */ 230238742Simp close(fd); 231238742Simp if (ret) 232238742Simp free(buf); 233238742Simp else 234238742Simp *buffp = buf; 235238742Simp return ret; 236238742Simp} 237238742Simp 238238742Simpchar *utilfdt_read(const char *filename) 239238742Simp{ 240238742Simp char *buff; 241238742Simp int ret = utilfdt_read_err(filename, &buff); 242238742Simp 243238742Simp if (ret) { 244238742Simp fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename, 245238742Simp strerror(ret)); 246238742Simp return NULL; 247238742Simp } 248238742Simp /* Successful read */ 249238742Simp return buff; 250238742Simp} 251238742Simp 252238742Simpint utilfdt_write_err(const char *filename, const void *blob) 253238742Simp{ 254238742Simp int fd = 1; /* assume stdout */ 255238742Simp int totalsize; 256238742Simp int offset; 257238742Simp int ret = 0; 258238742Simp const char *ptr = blob; 259238742Simp 260238742Simp if (strcmp(filename, "-") != 0) { 261238742Simp fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); 262238742Simp if (fd < 0) 263238742Simp return errno; 264238742Simp } 265238742Simp 266238742Simp totalsize = fdt_totalsize(blob); 267238742Simp offset = 0; 268238742Simp 269238742Simp while (offset < totalsize) { 270238742Simp ret = write(fd, ptr + offset, totalsize - offset); 271238742Simp if (ret < 0) { 272238742Simp ret = -errno; 273238742Simp break; 274238742Simp } 275238742Simp offset += ret; 276238742Simp } 277238742Simp /* Close the file/stdin; return errno on error */ 278238742Simp if (fd != 1) 279238742Simp close(fd); 280238742Simp return ret < 0 ? -ret : 0; 281238742Simp} 282238742Simp 283238742Simp 284238742Simpint utilfdt_write(const char *filename, const void *blob) 285238742Simp{ 286238742Simp int ret = utilfdt_write_err(filename, blob); 287238742Simp 288238742Simp if (ret) { 289238742Simp fprintf(stderr, "Couldn't write blob to '%s': %s\n", filename, 290238742Simp strerror(ret)); 291238742Simp } 292238742Simp return ret ? -1 : 0; 293238742Simp} 294238742Simp 295238742Simpint utilfdt_decode_type(const char *fmt, int *type, int *size) 296238742Simp{ 297238742Simp int qualifier = 0; 298238742Simp 299238742Simp if (!*fmt) 300238742Simp return -1; 301238742Simp 302238742Simp /* get the conversion qualifier */ 303238742Simp *size = -1; 304238742Simp if (strchr("hlLb", *fmt)) { 305238742Simp qualifier = *fmt++; 306238742Simp if (qualifier == *fmt) { 307238742Simp switch (*fmt++) { 308238742Simp/* TODO: case 'l': qualifier = 'L'; break;*/ 309238742Simp case 'h': 310238742Simp qualifier = 'b'; 311238742Simp break; 312238742Simp } 313238742Simp } 314238742Simp } 315238742Simp 316238742Simp /* we should now have a type */ 317238742Simp if ((*fmt == '\0') || !strchr("iuxs", *fmt)) 318238742Simp return -1; 319238742Simp 320238742Simp /* convert qualifier (bhL) to byte size */ 321238742Simp if (*fmt != 's') 322238742Simp *size = qualifier == 'b' ? 1 : 323238742Simp qualifier == 'h' ? 2 : 324238742Simp qualifier == 'l' ? 4 : -1; 325238742Simp *type = *fmt++; 326238742Simp 327238742Simp /* that should be it! */ 328238742Simp if (*fmt) 329238742Simp return -1; 330238742Simp return 0; 331238742Simp} 332