busybox/libbb/xfuncs_printf.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * Utility routines.
   4 *
   5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
   6 * Copyright (C) 2006 Rob Landley
   7 * Copyright (C) 2006 Denys Vlasenko
   8 *
   9 * Licensed under GPLv2, see file LICENSE in this source tree.
  10 */
  11
  12/* We need to have separate xfuncs.c and xfuncs_printf.c because
  13 * with current linkers, even with section garbage collection,
  14 * if *.o module references any of XXXprintf functions, you pull in
  15 * entire printf machinery. Even if you do not use the function
  16 * which uses XXXprintf.
  17 *
  18 * xfuncs.c contains functions (not necessarily xfuncs)
  19 * which do not pull in printf, directly or indirectly.
  20 * xfunc_printf.c contains those which do.
  21 */
  22
  23#include "libbb.h"
  24
  25
  26/* All the functions starting with "x" call bb_error_msg_and_die() if they
  27 * fail, so callers never need to check for errors.  If it returned, it
  28 * succeeded. */
  29
  30#ifndef DMALLOC
  31/* dmalloc provides variants of these that do abort() on failure.
  32 * Since dmalloc's prototypes overwrite the impls here as they are
  33 * included after these prototypes in libbb.h, all is well.
  34 */
  35// Warn if we can't allocate size bytes of memory.
  36void* FAST_FUNC malloc_or_warn(size_t size)
  37{
  38        void *ptr = malloc(size);
  39        if (ptr == NULL && size != 0)
  40                bb_error_msg(bb_msg_memory_exhausted);
  41        return ptr;
  42}
  43
  44// Die if we can't allocate size bytes of memory.
  45void* FAST_FUNC xmalloc(size_t size)
  46{
  47        void *ptr = malloc(size);
  48        if (ptr == NULL && size != 0)
  49                bb_error_msg_and_die(bb_msg_memory_exhausted);
  50        return ptr;
  51}
  52
  53// Die if we can't resize previously allocated memory.  (This returns a pointer
  54// to the new memory, which may or may not be the same as the old memory.
  55// It'll copy the contents to a new chunk and free the old one if necessary.)
  56void* FAST_FUNC xrealloc(void *ptr, size_t size)
  57{
  58        ptr = realloc(ptr, size);
  59        if (ptr == NULL && size != 0)
  60                bb_error_msg_and_die(bb_msg_memory_exhausted);
  61        return ptr;
  62}
  63#endif /* DMALLOC */
  64
  65// Die if we can't allocate and zero size bytes of memory.
  66void* FAST_FUNC xzalloc(size_t size)
  67{
  68        void *ptr = xmalloc(size);
  69        memset(ptr, 0, size);
  70        return ptr;
  71}
  72
  73// Die if we can't copy a string to freshly allocated memory.
  74char* FAST_FUNC xstrdup(const char *s)
  75{
  76        char *t;
  77
  78        if (s == NULL)
  79                return NULL;
  80
  81        t = strdup(s);
  82
  83        if (t == NULL)
  84                bb_error_msg_and_die(bb_msg_memory_exhausted);
  85
  86        return t;
  87}
  88
  89// Die if we can't allocate n+1 bytes (space for the null terminator) and copy
  90// the (possibly truncated to length n) string into it.
  91char* FAST_FUNC xstrndup(const char *s, int n)
  92{
  93        int m;
  94        char *t;
  95
  96        if (ENABLE_DEBUG && s == NULL)
  97                bb_error_msg_and_die("xstrndup bug");
  98
  99        /* We can just xmalloc(n+1) and strncpy into it, */
 100        /* but think about xstrndup("abc", 10000) wastage! */
 101        m = n;
 102        t = (char*) s;
 103        while (m) {
 104                if (!*t) break;
 105                m--;
 106                t++;
 107        }
 108        n -= m;
 109        t = xmalloc(n + 1);
 110        t[n] = '\0';
 111
 112        return memcpy(t, s, n);
 113}
 114
 115// Die if we can't open a file and return a FILE* to it.
 116// Notice we haven't got xfread(), This is for use with fscanf() and friends.
 117FILE* FAST_FUNC xfopen(const char *path, const char *mode)
 118{
 119        FILE *fp = fopen(path, mode);
 120        if (fp == NULL)
 121                bb_perror_msg_and_die("can't open '%s'", path);
 122        return fp;
 123}
 124
 125// Die if we can't open a file and return a fd.
 126int FAST_FUNC xopen3(const char *pathname, int flags, int mode)
 127{
 128        int ret;
 129
 130        ret = open(pathname, flags, mode);
 131        if (ret < 0) {
 132                bb_perror_msg_and_die("can't open '%s'", pathname);
 133        }
 134        return ret;
 135}
 136
 137// Die if we can't open a file and return a fd.
 138int FAST_FUNC xopen(const char *pathname, int flags)
 139{
 140        return xopen3(pathname, flags, 0666);
 141}
 142
 143/* Die if we can't open an existing file readonly with O_NONBLOCK
 144 * and return the fd.
 145 * Note that for ioctl O_RDONLY is sufficient.
 146 */
 147int FAST_FUNC xopen_nonblocking(const char *pathname)
 148{
 149        return xopen(pathname, O_RDONLY | O_NONBLOCK);
 150}
 151
 152// Warn if we can't open a file and return a fd.
 153int FAST_FUNC open3_or_warn(const char *pathname, int flags, int mode)
 154{
 155        int ret;
 156
 157        ret = open(pathname, flags, mode);
 158        if (ret < 0) {
 159                bb_perror_msg("can't open '%s'", pathname);
 160        }
 161        return ret;
 162}
 163
 164// Warn if we can't open a file and return a fd.
 165int FAST_FUNC open_or_warn(const char *pathname, int flags)
 166{
 167        return open3_or_warn(pathname, flags, 0666);
 168}
 169
 170void FAST_FUNC xunlink(const char *pathname)
 171{
 172        if (unlink(pathname))
 173                bb_perror_msg_and_die("can't remove file '%s'", pathname);
 174}
 175
 176void FAST_FUNC xrename(const char *oldpath, const char *newpath)
 177{
 178        if (rename(oldpath, newpath))
 179                bb_perror_msg_and_die("can't move '%s' to '%s'", oldpath, newpath);
 180}
 181
 182int FAST_FUNC rename_or_warn(const char *oldpath, const char *newpath)
 183{
 184        int n = rename(oldpath, newpath);
 185        if (n)
 186                bb_perror_msg("can't move '%s' to '%s'", oldpath, newpath);
 187        return n;
 188}
 189
 190void FAST_FUNC xpipe(int filedes[2])
 191{
 192        if (pipe(filedes))
 193                bb_perror_msg_and_die("can't create pipe");
 194}
 195
 196void FAST_FUNC xdup2(int from, int to)
 197{
 198        if (dup2(from, to) != to)
 199                bb_perror_msg_and_die("can't duplicate file descriptor");
 200}
 201
 202// "Renumber" opened fd
 203void FAST_FUNC xmove_fd(int from, int to)
 204{
 205        if (from == to)
 206                return;
 207        xdup2(from, to);
 208        close(from);
 209}
 210
 211// Die with an error message if we can't write the entire buffer.
 212void FAST_FUNC xwrite(int fd, const void *buf, size_t count)
 213{
 214        if (count) {
 215                ssize_t size = full_write(fd, buf, count);
 216                if ((size_t)size != count)
 217                        bb_error_msg_and_die("short write");
 218        }
 219}
 220void FAST_FUNC xwrite_str(int fd, const char *str)
 221{
 222        xwrite(fd, str, strlen(str));
 223}
 224
 225void FAST_FUNC xclose(int fd)
 226{
 227        if (close(fd))
 228                bb_perror_msg_and_die("close failed");
 229}
 230
 231// Die with an error message if we can't lseek to the right spot.
 232off_t FAST_FUNC xlseek(int fd, off_t offset, int whence)
 233{
 234        off_t off = lseek(fd, offset, whence);
 235        if (off == (off_t)-1) {
 236                if (whence == SEEK_SET)
 237                        bb_perror_msg_and_die("lseek(%"OFF_FMT"u)", offset);
 238                bb_perror_msg_and_die("lseek");
 239        }
 240        return off;
 241}
 242
 243int FAST_FUNC xmkstemp(char *template)
 244{
 245        int fd = mkstemp(template);
 246        if (fd < 0)
 247                bb_perror_msg_and_die("can't create temp file '%s'", template);
 248        return fd;
 249}
 250
 251// Die with supplied filename if this FILE* has ferror set.
 252void FAST_FUNC die_if_ferror(FILE *fp, const char *fn)
 253{
 254        if (ferror(fp)) {
 255                /* ferror doesn't set useful errno */
 256                bb_error_msg_and_die("%s: I/O error", fn);
 257        }
 258}
 259
 260// Die with an error message if stdout has ferror set.
 261void FAST_FUNC die_if_ferror_stdout(void)
 262{
 263        die_if_ferror(stdout, bb_msg_standard_output);
 264}
 265
 266int FAST_FUNC fflush_all(void)
 267{
 268        return fflush(NULL);
 269}
 270
 271
 272int FAST_FUNC bb_putchar(int ch)
 273{
 274        return putchar(ch);
 275}
 276
 277/* Die with an error message if we can't copy an entire FILE* to stdout,
 278 * then close that file. */
 279void FAST_FUNC xprint_and_close_file(FILE *file)
 280{
 281        fflush_all();
 282        // copyfd outputs error messages for us.
 283        if (bb_copyfd_eof(fileno(file), STDOUT_FILENO) == -1)
 284                xfunc_die();
 285
 286        fclose(file);
 287}
 288
 289// Die with an error message if we can't malloc() enough space and do an
 290// sprintf() into that space.
 291char* FAST_FUNC xasprintf(const char *format, ...)
 292{
 293        va_list p;
 294        int r;
 295        char *string_ptr;
 296
 297        va_start(p, format);
 298        r = vasprintf(&string_ptr, format, p);
 299        va_end(p);
 300
 301        if (r < 0)
 302                bb_error_msg_and_die(bb_msg_memory_exhausted);
 303        return string_ptr;
 304}
 305
 306void FAST_FUNC xsetenv(const char *key, const char *value)
 307{
 308        if (setenv(key, value, 1))
 309                bb_error_msg_and_die(bb_msg_memory_exhausted);
 310}
 311
 312/* Handles "VAR=VAL" strings, even those which are part of environ
 313 * _right now_
 314 */
 315void FAST_FUNC bb_unsetenv(const char *var)
 316{
 317        char *tp = strchr(var, '=');
 318
 319        if (!tp) {
 320                unsetenv(var);
 321                return;
 322        }
 323
 324        /* In case var was putenv'ed, we can't replace '='
 325         * with NUL and unsetenv(var) - it won't work,
 326         * env is modified by the replacement, unsetenv
 327         * sees "VAR" instead of "VAR=VAL" and does not remove it!
 328         * horror :( */
 329        tp = xstrndup(var, tp - var);
 330        unsetenv(tp);
 331        free(tp);
 332}
 333
 334void FAST_FUNC bb_unsetenv_and_free(char *var)
 335{
 336        bb_unsetenv(var);
 337        free(var);
 338}
 339
 340// Die with an error message if we can't set gid.  (Because resource limits may
 341// limit this user to a given number of processes, and if that fills up the
 342// setgid() will fail and we'll _still_be_root_, which is bad.)
 343void FAST_FUNC xsetgid(gid_t gid)
 344{
 345        if (setgid(gid)) bb_perror_msg_and_die("setgid");
 346}
 347
 348// Die with an error message if we can't set uid.  (See xsetgid() for why.)
 349void FAST_FUNC xsetuid(uid_t uid)
 350{
 351        if (setuid(uid)) bb_perror_msg_and_die("setuid");
 352}
 353
 354// Die if we can't chdir to a new path.
 355void FAST_FUNC xchdir(const char *path)
 356{
 357        if (chdir(path))
 358                bb_perror_msg_and_die("chdir(%s)", path);
 359}
 360
 361void FAST_FUNC xchroot(const char *path)
 362{
 363        if (chroot(path))
 364                bb_perror_msg_and_die("can't change root directory to %s", path);
 365}
 366
 367// Print a warning message if opendir() fails, but don't die.
 368DIR* FAST_FUNC warn_opendir(const char *path)
 369{
 370        DIR *dp;
 371
 372        dp = opendir(path);
 373        if (!dp)
 374                bb_perror_msg("can't open '%s'", path);
 375        return dp;
 376}
 377
 378// Die with an error message if opendir() fails.
 379DIR* FAST_FUNC xopendir(const char *path)
 380{
 381        DIR *dp;
 382
 383        dp = opendir(path);
 384        if (!dp)
 385                bb_perror_msg_and_die("can't open '%s'", path);
 386        return dp;
 387}
 388
 389// Die with an error message if we can't open a new socket.
 390int FAST_FUNC xsocket(int domain, int type, int protocol)
 391{
 392        int r = socket(domain, type, protocol);
 393
 394        if (r < 0) {
 395                /* Hijack vaguely related config option */
 396#if ENABLE_VERBOSE_RESOLUTION_ERRORS
 397                const char *s = "INET";
 398# ifdef AF_PACKET
 399                if (domain == AF_PACKET) s = "PACKET";
 400# endif
 401# ifdef AF_NETLINK
 402                if (domain == AF_NETLINK) s = "NETLINK";
 403# endif
 404IF_FEATURE_IPV6(if (domain == AF_INET6) s = "INET6";)
 405                bb_perror_msg_and_die("socket(AF_%s,%d,%d)", s, type, protocol);
 406#else
 407                bb_perror_msg_and_die("socket");
 408#endif
 409        }
 410
 411        return r;
 412}
 413
 414// Die with an error message if we can't bind a socket to an address.
 415void FAST_FUNC xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen)
 416{
 417        if (bind(sockfd, my_addr, addrlen)) bb_perror_msg_and_die("bind");
 418}
 419
 420// Die with an error message if we can't listen for connections on a socket.
 421void FAST_FUNC xlisten(int s, int backlog)
 422{
 423        if (listen(s, backlog)) bb_perror_msg_and_die("listen");
 424}
 425
 426/* Die with an error message if sendto failed.
 427 * Return bytes sent otherwise  */
 428ssize_t FAST_FUNC xsendto(int s, const void *buf, size_t len, const struct sockaddr *to,
 429                                socklen_t tolen)
 430{
 431        ssize_t ret = sendto(s, buf, len, 0, to, tolen);
 432        if (ret < 0) {
 433                if (ENABLE_FEATURE_CLEAN_UP)
 434                        close(s);
 435                bb_perror_msg_and_die("sendto");
 436        }
 437        return ret;
 438}
 439
 440// xstat() - a stat() which dies on failure with meaningful error message
 441void FAST_FUNC xstat(const char *name, struct stat *stat_buf)
 442{
 443        if (stat(name, stat_buf))
 444                bb_perror_msg_and_die("can't stat '%s'", name);
 445}
 446
 447void FAST_FUNC xfstat(int fd, struct stat *stat_buf, const char *errmsg)
 448{
 449        /* errmsg is usually a file name, but not always:
 450         * xfstat may be called in a spot where file name is no longer
 451         * available, and caller may give e.g. "can't stat input file" string.
 452         */
 453        if (fstat(fd, stat_buf))
 454                bb_simple_perror_msg_and_die(errmsg);
 455}
 456
 457// selinux_or_die() - die if SELinux is disabled.
 458void FAST_FUNC selinux_or_die(void)
 459{
 460#if ENABLE_SELINUX
 461        int rc = is_selinux_enabled();
 462        if (rc == 0) {
 463                bb_error_msg_and_die("SELinux is disabled");
 464        } else if (rc < 0) {
 465                bb_error_msg_and_die("is_selinux_enabled() failed");
 466        }
 467#else
 468        bb_error_msg_and_die("SELinux support is disabled");
 469#endif
 470}
 471
 472int FAST_FUNC ioctl_or_perror_and_die(int fd, unsigned request, void *argp, const char *fmt,...)
 473{
 474        int ret;
 475        va_list p;
 476
 477        ret = ioctl(fd, request, argp);
 478        if (ret < 0) {
 479                va_start(p, fmt);
 480                bb_verror_msg(fmt, p, strerror(errno));
 481                /* xfunc_die can actually longjmp, so be nice */
 482                va_end(p);
 483                xfunc_die();
 484        }
 485        return ret;
 486}
 487
 488int FAST_FUNC ioctl_or_perror(int fd, unsigned request, void *argp, const char *fmt,...)
 489{
 490        va_list p;
 491        int ret = ioctl(fd, request, argp);
 492
 493        if (ret < 0) {
 494                va_start(p, fmt);
 495                bb_verror_msg(fmt, p, strerror(errno));
 496                va_end(p);
 497        }
 498        return ret;
 499}
 500
 501#if ENABLE_IOCTL_HEX2STR_ERROR
 502int FAST_FUNC bb_ioctl_or_warn(int fd, unsigned request, void *argp, const char *ioctl_name)
 503{
 504        int ret;
 505
 506        ret = ioctl(fd, request, argp);
 507        if (ret < 0)
 508                bb_simple_perror_msg(ioctl_name);
 509        return ret;
 510}
 511int FAST_FUNC bb_xioctl(int fd, unsigned request, void *argp, const char *ioctl_name)
 512{
 513        int ret;
 514
 515        ret = ioctl(fd, request, argp);
 516        if (ret < 0)
 517                bb_simple_perror_msg_and_die(ioctl_name);
 518        return ret;
 519}
 520#else
 521int FAST_FUNC bb_ioctl_or_warn(int fd, unsigned request, void *argp)
 522{
 523        int ret;
 524
 525        ret = ioctl(fd, request, argp);
 526        if (ret < 0)
 527                bb_perror_msg("ioctl %#x failed", request);
 528        return ret;
 529}
 530int FAST_FUNC bb_xioctl(int fd, unsigned request, void *argp)
 531{
 532        int ret;
 533
 534        ret = ioctl(fd, request, argp);
 535        if (ret < 0)
 536                bb_perror_msg_and_die("ioctl %#x failed", request);
 537        return ret;
 538}
 539#endif
 540
 541char* FAST_FUNC xmalloc_ttyname(int fd)
 542{
 543        char *buf = xzalloc(128);
 544        int r = ttyname_r(fd, buf, 127);
 545        if (r) {
 546                free(buf);
 547                buf = NULL;
 548        }
 549        return buf;
 550}
 551
 552void FAST_FUNC generate_uuid(uint8_t *buf)
 553{
 554        /* http://www.ietf.org/rfc/rfc4122.txt
 555         *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 556         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 557         * |                          time_low                             |
 558         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 559         * |       time_mid                |         time_hi_and_version   |
 560         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 561         * |clk_seq_and_variant            |         node (0-1)            |
 562         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 563         * |                         node (2-5)                            |
 564         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 565         * IOW, uuid has this layout:
 566         * uint32_t time_low (big endian)
 567         * uint16_t time_mid (big endian)
 568         * uint16_t time_hi_and_version (big endian)
 569         *  version is a 4-bit field:
 570         *   1 Time-based
 571         *   2 DCE Security, with embedded POSIX UIDs
 572         *   3 Name-based (MD5)
 573         *   4 Randomly generated
 574         *   5 Name-based (SHA-1)
 575         * uint16_t clk_seq_and_variant (big endian)
 576         *  variant is a 3-bit field:
 577         *   0xx Reserved, NCS backward compatibility
 578         *   10x The variant specified in rfc4122
 579         *   110 Reserved, Microsoft backward compatibility
 580         *   111 Reserved for future definition
 581         * uint8_t node[6]
 582         *
 583         * For version 4, these bits are set/cleared:
 584         * time_hi_and_version & 0x0fff | 0x4000
 585         * clk_seq_and_variant & 0x3fff | 0x8000
 586         */
 587        pid_t pid;
 588        int i;
 589
 590        i = open("/dev/urandom", O_RDONLY);
 591        if (i >= 0) {
 592                read(i, buf, 16);
 593                close(i);
 594        }
 595        /* Paranoia. /dev/urandom may be missing.
 596         * rand() is guaranteed to generate at least [0, 2^15) range,
 597         * but lowest bits in some libc are not so "random".  */
 598        srand(monotonic_us()); /* pulls in printf */
 599        pid = getpid();
 600        while (1) {
 601                for (i = 0; i < 16; i++)
 602                        buf[i] ^= rand() >> 5;
 603                if (pid == 0)
 604                        break;
 605                srand(pid);
 606                pid = 0;
 607        }
 608
 609        /* version = 4 */
 610        buf[4 + 2    ] = (buf[4 + 2    ] & 0x0f) | 0x40;
 611        /* variant = 10x */
 612        buf[4 + 2 + 2] = (buf[4 + 2 + 2] & 0x3f) | 0x80;
 613}
 614
 615#if BB_MMU
 616pid_t FAST_FUNC xfork(void)
 617{
 618        pid_t pid;
 619        pid = fork();
 620        if (pid < 0) /* wtf? */
 621                bb_perror_msg_and_die("vfork"+1);
 622        return pid;
 623}
 624#endif
 625