root/scripts/dtc/util.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. xstrdup
  2. xavsprintf_append
  3. xasprintf_append
  4. xasprintf
  5. join_path
  6. util_is_printable_string
  7. get_oct_char
  8. get_hex_char
  9. get_escape_char
  10. utilfdt_read_err
  11. utilfdt_read
  12. utilfdt_write_err
  13. utilfdt_write
  14. utilfdt_decode_type
  15. utilfdt_print_data
  16. util_version
  17. util_usage

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright 2011 The Chromium Authors, All Rights Reserved.
   4  * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
   5  *
   6  * util_is_printable_string contributed by
   7  *      Pantelis Antoniou <pantelis.antoniou AT gmail.com>
   8  */
   9 
  10 #include <ctype.h>
  11 #include <stdio.h>
  12 #include <stdlib.h>
  13 #include <stdarg.h>
  14 #include <string.h>
  15 #include <assert.h>
  16 
  17 #include <errno.h>
  18 #include <fcntl.h>
  19 #include <unistd.h>
  20 
  21 #include "libfdt.h"
  22 #include "util.h"
  23 #include "version_gen.h"
  24 
  25 char *xstrdup(const char *s)
  26 {
  27         int len = strlen(s) + 1;
  28         char *d = xmalloc(len);
  29 
  30         memcpy(d, s, len);
  31 
  32         return d;
  33 }
  34 
  35 int xavsprintf_append(char **strp, const char *fmt, va_list ap)
  36 {
  37         int n, size = 0;        /* start with 128 bytes */
  38         char *p;
  39         va_list ap_copy;
  40 
  41         p = *strp;
  42         if (p)
  43                 size = strlen(p);
  44 
  45         va_copy(ap_copy, ap);
  46         n = vsnprintf(NULL, 0, fmt, ap_copy) + 1;
  47         va_end(ap_copy);
  48 
  49         p = xrealloc(p, size + n);
  50 
  51         n = vsnprintf(p + size, n, fmt, ap);
  52 
  53         *strp = p;
  54         return strlen(p);
  55 }
  56 
  57 int xasprintf_append(char **strp, const char *fmt, ...)
  58 {
  59         int n;
  60         va_list ap;
  61 
  62         va_start(ap, fmt);
  63         n = xavsprintf_append(strp, fmt, ap);
  64         va_end(ap);
  65 
  66         return n;
  67 }
  68 
  69 int xasprintf(char **strp, const char *fmt, ...)
  70 {
  71         int n;
  72         va_list ap;
  73 
  74         *strp = NULL;
  75 
  76         va_start(ap, fmt);
  77         n = xavsprintf_append(strp, fmt, ap);
  78         va_end(ap);
  79 
  80         return n;
  81 }
  82 
  83 char *join_path(const char *path, const char *name)
  84 {
  85         int lenp = strlen(path);
  86         int lenn = strlen(name);
  87         int len;
  88         int needslash = 1;
  89         char *str;
  90 
  91         len = lenp + lenn + 2;
  92         if ((lenp > 0) && (path[lenp-1] == '/')) {
  93                 needslash = 0;
  94                 len--;
  95         }
  96 
  97         str = xmalloc(len);
  98         memcpy(str, path, lenp);
  99         if (needslash) {
 100                 str[lenp] = '/';
 101                 lenp++;
 102         }
 103         memcpy(str+lenp, name, lenn+1);
 104         return str;
 105 }
 106 
 107 bool util_is_printable_string(const void *data, int len)
 108 {
 109         const char *s = data;
 110         const char *ss, *se;
 111 
 112         /* zero length is not */
 113         if (len == 0)
 114                 return 0;
 115 
 116         /* must terminate with zero */
 117         if (s[len - 1] != '\0')
 118                 return 0;
 119 
 120         se = s + len;
 121 
 122         while (s < se) {
 123                 ss = s;
 124                 while (s < se && *s && isprint((unsigned char)*s))
 125                         s++;
 126 
 127                 /* not zero, or not done yet */
 128                 if (*s != '\0' || s == ss)
 129                         return 0;
 130 
 131                 s++;
 132         }
 133 
 134         return 1;
 135 }
 136 
 137 /*
 138  * Parse a octal encoded character starting at index i in string s.  The
 139  * resulting character will be returned and the index i will be updated to
 140  * point at the character directly after the end of the encoding, this may be
 141  * the '\0' terminator of the string.
 142  */
 143 static char get_oct_char(const char *s, int *i)
 144 {
 145         char x[4];
 146         char *endx;
 147         long val;
 148 
 149         x[3] = '\0';
 150         strncpy(x, s + *i, 3);
 151 
 152         val = strtol(x, &endx, 8);
 153 
 154         assert(endx > x);
 155 
 156         (*i) += endx - x;
 157         return val;
 158 }
 159 
 160 /*
 161  * Parse a hexadecimal encoded character starting at index i in string s.  The
 162  * resulting character will be returned and the index i will be updated to
 163  * point at the character directly after the end of the encoding, this may be
 164  * the '\0' terminator of the string.
 165  */
 166 static char get_hex_char(const char *s, int *i)
 167 {
 168         char x[3];
 169         char *endx;
 170         long val;
 171 
 172         x[2] = '\0';
 173         strncpy(x, s + *i, 2);
 174 
 175         val = strtol(x, &endx, 16);
 176         if (!(endx  > x))
 177                 die("\\x used with no following hex digits\n");
 178 
 179         (*i) += endx - x;
 180         return val;
 181 }
 182 
 183 char get_escape_char(const char *s, int *i)
 184 {
 185         char    c = s[*i];
 186         int     j = *i + 1;
 187         char    val;
 188 
 189         switch (c) {
 190         case 'a':
 191                 val = '\a';
 192                 break;
 193         case 'b':
 194                 val = '\b';
 195                 break;
 196         case 't':
 197                 val = '\t';
 198                 break;
 199         case 'n':
 200                 val = '\n';
 201                 break;
 202         case 'v':
 203                 val = '\v';
 204                 break;
 205         case 'f':
 206                 val = '\f';
 207                 break;
 208         case 'r':
 209                 val = '\r';
 210                 break;
 211         case '0':
 212         case '1':
 213         case '2':
 214         case '3':
 215         case '4':
 216         case '5':
 217         case '6':
 218         case '7':
 219                 j--; /* need to re-read the first digit as
 220                       * part of the octal value */
 221                 val = get_oct_char(s, &j);
 222                 break;
 223         case 'x':
 224                 val = get_hex_char(s, &j);
 225                 break;
 226         default:
 227                 val = c;
 228         }
 229 
 230         (*i) = j;
 231         return val;
 232 }
 233 
 234 int utilfdt_read_err(const char *filename, char **buffp, size_t *len)
 235 {
 236         int fd = 0;     /* assume stdin */
 237         char *buf = NULL;
 238         size_t bufsize = 1024, offset = 0;
 239         int ret = 0;
 240 
 241         *buffp = NULL;
 242         if (strcmp(filename, "-") != 0) {
 243                 fd = open(filename, O_RDONLY);
 244                 if (fd < 0)
 245                         return errno;
 246         }
 247 
 248         /* Loop until we have read everything */
 249         buf = xmalloc(bufsize);
 250         do {
 251                 /* Expand the buffer to hold the next chunk */
 252                 if (offset == bufsize) {
 253                         bufsize *= 2;
 254                         buf = xrealloc(buf, bufsize);
 255                 }
 256 
 257                 ret = read(fd, &buf[offset], bufsize - offset);
 258                 if (ret < 0) {
 259                         ret = errno;
 260                         break;
 261                 }
 262                 offset += ret;
 263         } while (ret != 0);
 264 
 265         /* Clean up, including closing stdin; return errno on error */
 266         close(fd);
 267         if (ret)
 268                 free(buf);
 269         else
 270                 *buffp = buf;
 271         if (len)
 272                 *len = bufsize;
 273         return ret;
 274 }
 275 
 276 char *utilfdt_read(const char *filename, size_t *len)
 277 {
 278         char *buff;
 279         int ret = utilfdt_read_err(filename, &buff, len);
 280 
 281         if (ret) {
 282                 fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
 283                         strerror(ret));
 284                 return NULL;
 285         }
 286         /* Successful read */
 287         return buff;
 288 }
 289 
 290 int utilfdt_write_err(const char *filename, const void *blob)
 291 {
 292         int fd = 1;     /* assume stdout */
 293         int totalsize;
 294         int offset;
 295         int ret = 0;
 296         const char *ptr = blob;
 297 
 298         if (strcmp(filename, "-") != 0) {
 299                 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
 300                 if (fd < 0)
 301                         return errno;
 302         }
 303 
 304         totalsize = fdt_totalsize(blob);
 305         offset = 0;
 306 
 307         while (offset < totalsize) {
 308                 ret = write(fd, ptr + offset, totalsize - offset);
 309                 if (ret < 0) {
 310                         ret = -errno;
 311                         break;
 312                 }
 313                 offset += ret;
 314         }
 315         /* Close the file/stdin; return errno on error */
 316         if (fd != 1)
 317                 close(fd);
 318         return ret < 0 ? -ret : 0;
 319 }
 320 
 321 
 322 int utilfdt_write(const char *filename, const void *blob)
 323 {
 324         int ret = utilfdt_write_err(filename, blob);
 325 
 326         if (ret) {
 327                 fprintf(stderr, "Couldn't write blob to '%s': %s\n", filename,
 328                         strerror(ret));
 329         }
 330         return ret ? -1 : 0;
 331 }
 332 
 333 int utilfdt_decode_type(const char *fmt, int *type, int *size)
 334 {
 335         int qualifier = 0;
 336 
 337         if (!*fmt)
 338                 return -1;
 339 
 340         /* get the conversion qualifier */
 341         *size = -1;
 342         if (strchr("hlLb", *fmt)) {
 343                 qualifier = *fmt++;
 344                 if (qualifier == *fmt) {
 345                         switch (*fmt++) {
 346 /* TODO:                case 'l': qualifier = 'L'; break;*/
 347                         case 'h':
 348                                 qualifier = 'b';
 349                                 break;
 350                         }
 351                 }
 352         }
 353 
 354         /* we should now have a type */
 355         if ((*fmt == '\0') || !strchr("iuxs", *fmt))
 356                 return -1;
 357 
 358         /* convert qualifier (bhL) to byte size */
 359         if (*fmt != 's')
 360                 *size = qualifier == 'b' ? 1 :
 361                                 qualifier == 'h' ? 2 :
 362                                 qualifier == 'l' ? 4 : -1;
 363         *type = *fmt++;
 364 
 365         /* that should be it! */
 366         if (*fmt)
 367                 return -1;
 368         return 0;
 369 }
 370 
 371 void utilfdt_print_data(const char *data, int len)
 372 {
 373         int i;
 374         const char *s;
 375 
 376         /* no data, don't print */
 377         if (len == 0)
 378                 return;
 379 
 380         if (util_is_printable_string(data, len)) {
 381                 printf(" = ");
 382 
 383                 s = data;
 384                 do {
 385                         printf("\"%s\"", s);
 386                         s += strlen(s) + 1;
 387                         if (s < data + len)
 388                                 printf(", ");
 389                 } while (s < data + len);
 390 
 391         } else if ((len % 4) == 0) {
 392                 const fdt32_t *cell = (const fdt32_t *)data;
 393 
 394                 printf(" = <");
 395                 for (i = 0, len /= 4; i < len; i++)
 396                         printf("0x%08x%s", fdt32_to_cpu(cell[i]),
 397                                i < (len - 1) ? " " : "");
 398                 printf(">");
 399         } else {
 400                 const unsigned char *p = (const unsigned char *)data;
 401                 printf(" = [");
 402                 for (i = 0; i < len; i++)
 403                         printf("%02x%s", *p++, i < len - 1 ? " " : "");
 404                 printf("]");
 405         }
 406 }
 407 
 408 void NORETURN util_version(void)
 409 {
 410         printf("Version: %s\n", DTC_VERSION);
 411         exit(0);
 412 }
 413 
 414 void NORETURN util_usage(const char *errmsg, const char *synopsis,
 415                          const char *short_opts,
 416                          struct option const long_opts[],
 417                          const char * const opts_help[])
 418 {
 419         FILE *fp = errmsg ? stderr : stdout;
 420         const char a_arg[] = "<arg>";
 421         size_t a_arg_len = strlen(a_arg) + 1;
 422         size_t i;
 423         int optlen;
 424 
 425         fprintf(fp,
 426                 "Usage: %s\n"
 427                 "\n"
 428                 "Options: -[%s]\n", synopsis, short_opts);
 429 
 430         /* prescan the --long opt length to auto-align */
 431         optlen = 0;
 432         for (i = 0; long_opts[i].name; ++i) {
 433                 /* +1 is for space between --opt and help text */
 434                 int l = strlen(long_opts[i].name) + 1;
 435                 if (long_opts[i].has_arg == a_argument)
 436                         l += a_arg_len;
 437                 if (optlen < l)
 438                         optlen = l;
 439         }
 440 
 441         for (i = 0; long_opts[i].name; ++i) {
 442                 /* helps when adding new applets or options */
 443                 assert(opts_help[i] != NULL);
 444 
 445                 /* first output the short flag if it has one */
 446                 if (long_opts[i].val > '~')
 447                         fprintf(fp, "      ");
 448                 else
 449                         fprintf(fp, "  -%c, ", long_opts[i].val);
 450 
 451                 /* then the long flag */
 452                 if (long_opts[i].has_arg == no_argument)
 453                         fprintf(fp, "--%-*s", optlen, long_opts[i].name);
 454                 else
 455                         fprintf(fp, "--%s %s%*s", long_opts[i].name, a_arg,
 456                                 (int)(optlen - strlen(long_opts[i].name) - a_arg_len), "");
 457 
 458                 /* finally the help text */
 459                 fprintf(fp, "%s\n", opts_help[i]);
 460         }
 461 
 462         if (errmsg) {
 463                 fprintf(fp, "\nError: %s\n", errmsg);
 464                 exit(EXIT_FAILURE);
 465         } else
 466                 exit(EXIT_SUCCESS);
 467 }

/* [<][>][^][v][top][bottom][index][help] */