Viewing file: util.c (8.5 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright 2011 The Chromium Authors, All Rights Reserved. * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. * * util_is_printable_string contributed by * Pantelis Antoniou <pantelis.antoniou AT gmail.com> */
#include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <assert.h> #include <inttypes.h>
#include <errno.h> #include <fcntl.h> #include <unistd.h>
#include "libfdt.h" #include "util.h" #include "version_gen.h"
char *xstrdup(const char *s) { int len = strlen(s) + 1; char *d = xmalloc(len);
memcpy(d, s, len);
return d; }
int xavsprintf_append(char **strp, const char *fmt, va_list ap) { int n, size = 0; /* start with 128 bytes */ char *p; va_list ap_copy;
p = *strp; if (p) size = strlen(p);
va_copy(ap_copy, ap); n = vsnprintf(NULL, 0, fmt, ap_copy) + 1; va_end(ap_copy);
p = xrealloc(p, size + n);
n = vsnprintf(p + size, n, fmt, ap);
*strp = p; return strlen(p); }
int xasprintf_append(char **strp, const char *fmt, ...) { int n; va_list ap;
va_start(ap, fmt); n = xavsprintf_append(strp, fmt, ap); va_end(ap);
return n; }
int xasprintf(char **strp, const char *fmt, ...) { int n; va_list ap;
*strp = NULL;
va_start(ap, fmt); n = xavsprintf_append(strp, fmt, ap); va_end(ap);
return n; }
char *join_path(const char *path, const char *name) { int lenp = strlen(path); int lenn = strlen(name); int len; int needslash = 1; char *str;
len = lenp + lenn + 2; if ((lenp > 0) && (path[lenp-1] == '/')) { needslash = 0; len--; }
str = xmalloc(len); memcpy(str, path, lenp); if (needslash) { str[lenp] = '/'; lenp++; } memcpy(str+lenp, name, lenn+1); return str; }
bool util_is_printable_string(const void *data, int len) { const char *s = data; const char *ss, *se;
/* zero length is not */ if (len == 0) return 0;
/* must terminate with zero */ if (s[len - 1] != '\0') return 0;
se = s + len;
while (s < se) { ss = s; while (s < se && *s && isprint((unsigned char)*s)) s++;
/* not zero, or not done yet */ if (*s != '\0' || s == ss) return 0;
s++; }
return 1; }
/* * Parse a octal encoded character starting at index i in string s. The * resulting character will be returned and the index i will be updated to * point at the character directly after the end of the encoding, this may be * the '\0' terminator of the string. */ static char get_oct_char(const char *s, int *i) { char x[4]; char *endx; long val;
x[3] = '\0'; strncpy(x, s + *i, 3);
val = strtol(x, &endx, 8);
assert(endx > x);
(*i) += endx - x; return val; }
/* * Parse a hexadecimal encoded character starting at index i in string s. The * resulting character will be returned and the index i will be updated to * point at the character directly after the end of the encoding, this may be * the '\0' terminator of the string. */ static char get_hex_char(const char *s, int *i) { char x[3]; char *endx; long val;
x[2] = '\0'; strncpy(x, s + *i, 2);
val = strtol(x, &endx, 16); if (!(endx > x)) die("\\x used with no following hex digits\n");
(*i) += endx - x; return val; }
char get_escape_char(const char *s, int *i) { char c = s[*i]; int j = *i + 1; char val;
switch (c) { case 'a': val = '\a'; break; case 'b': val = '\b'; break; case 't': val = '\t'; break; case 'n': val = '\n'; break; case 'v': val = '\v'; break; case 'f': val = '\f'; break; case 'r': val = '\r'; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': j--; /* need to re-read the first digit as * part of the octal value */ val = get_oct_char(s, &j); break; case 'x': val = get_hex_char(s, &j); break; default: val = c; }
(*i) = j; return val; }
int utilfdt_read_err(const char *filename, char **buffp, size_t *len) { int fd = 0; /* assume stdin */ char *buf = NULL; size_t bufsize = 1024, offset = 0; int ret = 0;
*buffp = NULL; if (strcmp(filename, "-") != 0) { fd = open(filename, O_RDONLY); if (fd < 0) return errno; }
/* Loop until we have read everything */ buf = xmalloc(bufsize); do { /* Expand the buffer to hold the next chunk */ if (offset == bufsize) { bufsize *= 2; buf = xrealloc(buf, bufsize); }
ret = read(fd, &buf[offset], bufsize - offset); if (ret < 0) { ret = errno; break; } offset += ret; } while (ret != 0);
/* Clean up, including closing stdin; return errno on error */ close(fd); if (ret) free(buf); else *buffp = buf; if (len) *len = bufsize; return ret; }
char *utilfdt_read(const char *filename, size_t *len) { char *buff; int ret = utilfdt_read_err(filename, &buff, len);
if (ret) { fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename, strerror(ret)); return NULL; } /* Successful read */ return buff; }
int utilfdt_write_err(const char *filename, const void *blob) { int fd = 1; /* assume stdout */ int totalsize; int offset; int ret = 0; const char *ptr = blob;
if (strcmp(filename, "-") != 0) { fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) return errno; }
totalsize = fdt_totalsize(blob); offset = 0;
while (offset < totalsize) { ret = write(fd, ptr + offset, totalsize - offset); if (ret < 0) { ret = -errno; break; } offset += ret; } /* Close the file/stdin; return errno on error */ if (fd != 1) close(fd); return ret < 0 ? -ret : 0; }
int utilfdt_write(const char *filename, const void *blob) { int ret = utilfdt_write_err(filename, blob);
if (ret) { fprintf(stderr, "Couldn't write blob to '%s': %s\n", filename, strerror(ret)); } return ret ? -1 : 0; }
int utilfdt_decode_type(const char *fmt, int *type, int *size) { int qualifier = 0;
if (!*fmt) return -1;
/* get the conversion qualifier */ *size = -1; if (strchr("hlLb", *fmt)) { qualifier = *fmt++; if (qualifier == *fmt) { switch (*fmt++) { /* TODO: case 'l': qualifier = 'L'; break;*/ case 'h': qualifier = 'b'; break; } } }
/* we should now have a type */ if ((*fmt == '\0') || !strchr("iuxs", *fmt)) return -1;
/* convert qualifier (bhL) to byte size */ if (*fmt != 's') *size = qualifier == 'b' ? 1 : qualifier == 'h' ? 2 : qualifier == 'l' ? 4 : -1; *type = *fmt++;
/* that should be it! */ if (*fmt) return -1; return 0; }
void utilfdt_print_data(const char *data, int len) { int i; const char *s;
/* no data, don't print */ if (len == 0) return;
if (util_is_printable_string(data, len)) { printf(" = ");
s = data; do { printf("\"%s\"", s); s += strlen(s) + 1; if (s < data + len) printf(", "); } while (s < data + len);
} else if ((len % 4) == 0) { const fdt32_t *cell = (const fdt32_t *)data;
printf(" = <"); for (i = 0, len /= 4; i < len; i++) printf("0x%08" PRIx32 "%s", fdt32_to_cpu(cell[i]), i < (len - 1) ? " " : ""); printf(">"); } else { const unsigned char *p = (const unsigned char *)data; printf(" = ["); for (i = 0; i < len; i++) printf("%02x%s", *p++, i < len - 1 ? " " : ""); printf("]"); } }
void NORETURN util_version(void) { printf("Version: %s\n", DTC_VERSION); exit(0); }
void NORETURN util_usage(const char *errmsg, const char *synopsis, const char *short_opts, struct option const long_opts[], const char * const opts_help[]) { FILE *fp = errmsg ? stderr : stdout; const char a_arg[] = "<arg>"; size_t a_arg_len = strlen(a_arg) + 1; size_t i; int optlen;
fprintf(fp, "Usage: %s\n" "\n" "Options: -[%s]\n", synopsis, short_opts);
/* prescan the --long opt length to auto-align */ optlen = 0; for (i = 0; long_opts[i].name; ++i) { /* +1 is for space between --opt and help text */ int l = strlen(long_opts[i].name) + 1; if (long_opts[i].has_arg == a_argument) l += a_arg_len; if (optlen < l) optlen = l; }
for (i = 0; long_opts[i].name; ++i) { /* helps when adding new applets or options */ assert(opts_help[i] != NULL);
/* first output the short flag if it has one */ if (long_opts[i].val > '~') fprintf(fp, " "); else fprintf(fp, " -%c, ", long_opts[i].val);
/* then the long flag */ if (long_opts[i].has_arg == no_argument) fprintf(fp, "--%-*s", optlen, long_opts[i].name); else fprintf(fp, "--%s %s%*s", long_opts[i].name, a_arg, (int)(optlen - strlen(long_opts[i].name) - a_arg_len), "");
/* finally the help text */ fprintf(fp, "%s\n", opts_help[i]); }
if (errmsg) { fprintf(fp, "\nError: %s\n", errmsg); exit(EXIT_FAILURE); } else exit(EXIT_SUCCESS); }
|