Something went wrong. Try again.
Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496// 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"
void fprint_path_escaped(FILE *fp, const char *path){ const char *p = path;
while (*p) { if (*p == ' ') { fputc('\\', fp); fputc(' ', fp); } else { fputc(*p, fp); }
p++; }}
char *xstrdup(const char *s){ int len = strlen(s) + 1; char *d = xmalloc(len);
memcpy(d, s, len);
return d;}
char *xstrndup(const char *s, size_t n){ size_t len = strnlen(s, n) + 1; char *d = xmalloc(len);
memcpy(d, s, len - 1); d[len - 1] = '\0';
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("iuxsr", *fmt)) return -1;
/* convert qualifier (bhL) to byte size */ if (*fmt != 's' && *fmt != 'r') *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);}