Ignore:
Timestamp:
Nov 6, 2007, 11:01:53 AM (13 years ago)
Author:
Bruno Cornec
Message:
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod? silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian? keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René? Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/stable/mindi-busybox/libbb/xfuncs.c

    r821 r1770  
    44 *
    55 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
     6 * Copyright (C) 2006 Rob Landley
     7 * Copyright (C) 2006 Denis Vlasenko
    68 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     9 * Licensed under GPL version 2, see file LICENSE in this tarball for details.
    810 */
    911
    10 #include <sys/types.h>
    11 #include <sys/stat.h>
    12 #include <sys/wait.h>
    13 #include <stdio.h>
    14 #include <string.h>
    15 #include <stdlib.h>
    16 #include <unistd.h>
    17 #include <fcntl.h>
    18 #include "busybox.h"
     12#include "libbb.h"
     13
     14/* All the functions starting with "x" call bb_error_msg_and_die() if they
     15 * fail, so callers never need to check for errors.  If it returned, it
     16 * succeeded. */
    1917
    2018#ifndef DMALLOC
    21 #ifdef L_xmalloc
     19/* dmalloc provides variants of these that do abort() on failure.
     20 * Since dmalloc's prototypes overwrite the impls here as they are
     21 * included after these prototypes in libbb.h, all is well.
     22 */
     23// Warn if we can't allocate size bytes of memory.
     24void *malloc_or_warn(size_t size)
     25{
     26    void *ptr = malloc(size);
     27    if (ptr == NULL && size != 0)
     28        bb_error_msg(bb_msg_memory_exhausted);
     29    return ptr;
     30}
     31
     32// Die if we can't allocate size bytes of memory.
    2233void *xmalloc(size_t size)
    2334{
     
    2738    return ptr;
    2839}
    29 #endif
    30 
    31 #ifdef L_xrealloc
     40
     41// Die if we can't resize previously allocated memory.  (This returns a pointer
     42// to the new memory, which may or may not be the same as the old memory.
     43// It'll copy the contents to a new chunk and free the old one if necessary.)
    3244void *xrealloc(void *ptr, size_t size)
    3345{
     
    3749    return ptr;
    3850}
    39 #endif
    40 
    41 #ifdef L_xzalloc
     51#endif /* DMALLOC */
     52
     53// Die if we can't allocate and zero size bytes of memory.
    4254void *xzalloc(size_t size)
    4355{
     
    4658    return ptr;
    4759}
    48 #endif
    49 
    50 #ifdef L_xcalloc
    51 void *xcalloc(size_t nmemb, size_t size)
    52 {
    53     void *ptr = calloc(nmemb, size);
    54     if (ptr == NULL && nmemb != 0 && size != 0)
    55         bb_error_msg_and_die(bb_msg_memory_exhausted);
    56     return ptr;
    57 }
    58 #endif
    59 #endif /* DMALLOC */
    60 
    61 #ifdef L_xstrdup
    62 char * bb_xstrdup (const char *s)
     60
     61// Die if we can't copy a string to freshly allocated memory.
     62char * xstrdup(const char *s)
    6363{
    6464    char *t;
     
    6767        return NULL;
    6868
    69     t = strdup (s);
     69    t = strdup(s);
    7070
    7171    if (t == NULL)
     
    7474    return t;
    7575}
    76 #endif
    77 
    78 #ifdef L_xstrndup
    79 char * bb_xstrndup (const char *s, int n)
    80 {
     76
     77// Die if we can't allocate n+1 bytes (space for the null terminator) and copy
     78// the (possibly truncated to length n) string into it.
     79char * xstrndup(const char *s, int n)
     80{
     81    int m;
    8182    char *t;
    8283
    8384    if (ENABLE_DEBUG && s == NULL)
    84         bb_error_msg_and_die("bb_xstrndup bug");
    85 
    86     t = xmalloc(++n);
    87 
    88     return safe_strncpy(t,s,n);
    89 }
    90 #endif
    91 
    92 #ifdef L_xfopen
    93 FILE *bb_xfopen(const char *path, const char *mode)
    94 {
    95     FILE *fp;
    96     if ((fp = fopen(path, mode)) == NULL)
    97         bb_perror_msg_and_die("%s", path);
     85        bb_error_msg_and_die("xstrndup bug");
     86
     87    /* We can just xmalloc(n+1) and strncpy into it, */
     88    /* but think about xstrndup("abc", 10000) wastage! */
     89    m = n;
     90    t = (char*) s;
     91    while (m) {
     92        if (!*t) break;
     93        m--;
     94        t++;
     95    }
     96    n -= m;
     97    t = xmalloc(n + 1);
     98    t[n] = '\0';
     99
     100    return memcpy(t, s, n);
     101}
     102
     103// Die if we can't open a file and return a FILE * to it.
     104// Notice we haven't got xfread(), This is for use with fscanf() and friends.
     105FILE *xfopen(const char *path, const char *mode)
     106{
     107    FILE *fp = fopen(path, mode);
     108    if (fp == NULL)
     109        bb_perror_msg_and_die("can't open '%s'", path);
    98110    return fp;
    99111}
    100 #endif
    101 
    102 #ifdef L_xopen
    103 int bb_xopen(const char *pathname, int flags)
    104 {
    105     return bb_xopen3(pathname, flags, 0777);
    106 }
    107 #endif
    108 
    109 #ifdef L_xopen3
    110 int bb_xopen3(const char *pathname, int flags, int mode)
     112
     113// Die if we can't open a file and return a fd.
     114int xopen3(const char *pathname, int flags, int mode)
    111115{
    112116    int ret;
     
    114118    ret = open(pathname, flags, mode);
    115119    if (ret < 0) {
    116         bb_perror_msg_and_die("%s", pathname);
     120        bb_perror_msg_and_die("can't open '%s'", pathname);
    117121    }
    118122    return ret;
    119123}
    120 #endif
    121 
    122 #ifdef L_xread
    123 ssize_t bb_xread(int fd, void *buf, size_t count)
    124 {
    125     ssize_t size;
    126 
    127     size = read(fd, buf, count);
    128     if (size < 0) {
    129         bb_perror_msg_and_die(bb_msg_read_error);
    130     }
    131     return(size);
    132 }
    133 #endif
    134 
    135 #ifdef L_xread_all
    136 void bb_xread_all(int fd, void *buf, size_t count)
    137 {
    138     ssize_t size;
    139 
    140     while (count) {
    141         if ((size = bb_xread(fd, buf, count)) == 0) {   /* EOF */
    142             bb_error_msg_and_die("Short read");
    143         }
    144         count -= size;
    145         buf = ((char *) buf) + size;
    146     }
    147     return;
    148 }
    149 #endif
    150 
    151 #ifdef L_xread_char
    152 unsigned char bb_xread_char(int fd)
    153 {
    154     char tmp;
    155 
    156     bb_xread_all(fd, &tmp, 1);
    157 
    158     return(tmp);
    159 }
    160 #endif
    161 
    162 #ifdef L_xferror
    163 void bb_xferror(FILE *fp, const char *fn)
     124
     125// Die if we can't open an existing file and return a fd.
     126int xopen(const char *pathname, int flags)
     127{
     128    return xopen3(pathname, flags, 0666);
     129}
     130
     131// Warn if we can't open a file and return a fd.
     132int open3_or_warn(const char *pathname, int flags, int mode)
     133{
     134    int ret;
     135
     136    ret = open(pathname, flags, mode);
     137    if (ret < 0) {
     138        bb_perror_msg("can't open '%s'", pathname);
     139    }
     140    return ret;
     141}
     142
     143// Warn if we can't open a file and return a fd.
     144int open_or_warn(const char *pathname, int flags)
     145{
     146    return open3_or_warn(pathname, flags, 0666);
     147}
     148
     149void xpipe(int filedes[2])
     150{
     151    if (pipe(filedes))
     152        bb_perror_msg_and_die("can't create pipe");
     153}
     154
     155void xunlink(const char *pathname)
     156{
     157    if (unlink(pathname))
     158        bb_perror_msg_and_die("can't remove file '%s'", pathname);
     159}
     160
     161// Turn on nonblocking I/O on a fd
     162int ndelay_on(int fd)
     163{
     164    return fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) | O_NONBLOCK);
     165}
     166
     167int ndelay_off(int fd)
     168{
     169    return fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) & ~O_NONBLOCK);
     170}
     171
     172void xdup2(int from, int to)
     173{
     174    if (dup2(from, to) != to)
     175        bb_perror_msg_and_die("can't duplicate file descriptor");
     176}
     177
     178// "Renumber" opened fd
     179void xmove_fd(int from, int to)
     180{
     181    if (from == to)
     182        return;
     183    xdup2(from, to);
     184    close(from);
     185}
     186
     187// Die with an error message if we can't write the entire buffer.
     188void xwrite(int fd, const void *buf, size_t count)
     189{
     190    if (count) {
     191        ssize_t size = full_write(fd, buf, count);
     192        if (size != count)
     193            bb_error_msg_and_die("short write");
     194    }
     195}
     196
     197// Die with an error message if we can't lseek to the right spot.
     198off_t xlseek(int fd, off_t offset, int whence)
     199{
     200    off_t off = lseek(fd, offset, whence);
     201    if (off == (off_t)-1) {
     202        if (whence == SEEK_SET)
     203            bb_perror_msg_and_die("lseek(%"OFF_FMT"u)", offset);
     204        bb_perror_msg_and_die("lseek");
     205    }
     206    return off;
     207}
     208
     209// Die with supplied filename if this FILE * has ferror set.
     210void die_if_ferror(FILE *fp, const char *fn)
    164211{
    165212    if (ferror(fp)) {
    166         bb_error_msg_and_die("%s", fn);
    167     }
    168 }
    169 #endif
    170 
    171 #ifdef L_xferror_stdout
    172 void bb_xferror_stdout(void)
    173 {
    174     bb_xferror(stdout, bb_msg_standard_output);
    175 }
    176 #endif
    177 
    178 #ifdef L_xfflush_stdout
    179 void bb_xfflush_stdout(void)
     213        /* ferror doesn't set useful errno */
     214        bb_error_msg_and_die("%s: I/O error", fn);
     215    }
     216}
     217
     218// Die with an error message if stdout has ferror set.
     219void die_if_ferror_stdout(void)
     220{
     221    die_if_ferror(stdout, bb_msg_standard_output);
     222}
     223
     224// Die with an error message if we have trouble flushing stdout.
     225void xfflush_stdout(void)
    180226{
    181227    if (fflush(stdout)) {
     
    183229    }
    184230}
     231
     232void sig_block(int sig)
     233{
     234    sigset_t ss;
     235    sigemptyset(&ss);
     236    sigaddset(&ss, sig);
     237    sigprocmask(SIG_BLOCK, &ss, NULL);
     238}
     239
     240void sig_unblock(int sig)
     241{
     242    sigset_t ss;
     243    sigemptyset(&ss);
     244    sigaddset(&ss, sig);
     245    sigprocmask(SIG_UNBLOCK, &ss, NULL);
     246}
     247
     248#if 0
     249void sig_blocknone(void)
     250{
     251    sigset_t ss;
     252    sigemptyset(&ss);
     253    sigprocmask(SIG_SETMASK, &ss, NULL);
     254}
    185255#endif
    186256
    187 #ifdef L_spawn
    188 // This does a fork/exec in one call, using vfork().
    189 pid_t bb_spawn(char **argv)
    190 {
    191     static int failed;
    192     pid_t pid;
    193     void *app = find_applet_by_name(argv[0]);
    194 
    195     // Be nice to nommu machines.
    196     failed = 0;
    197     pid = vfork();
    198     if (pid < 0) return pid;
    199     if (!pid) {
    200         execvp(app ? CONFIG_BUSYBOX_EXEC_PATH : *argv, argv);
    201 
    202         // We're sharing a stack with blocked parent, let parent know we failed
    203         // and then exit to unblock parent (but don't run atexit() stuff, which
    204         // would screw up parent.)
    205 
    206         failed = -1;
    207         _exit(0);
    208     }
    209     return failed ? failed : pid;
    210 }
     257void sig_catch(int sig, void (*f)(int))
     258{
     259    struct sigaction sa;
     260    sa.sa_handler = f;
     261    sa.sa_flags = 0;
     262    sigemptyset(&sa.sa_mask);
     263    sigaction(sig, &sa, NULL);
     264}
     265
     266void sig_pause(void)
     267{
     268    sigset_t ss;
     269    sigemptyset(&ss);
     270    sigsuspend(&ss);
     271}
     272
     273
     274void xsetenv(const char *key, const char *value)
     275{
     276    if (setenv(key, value, 1))
     277        bb_error_msg_and_die(bb_msg_memory_exhausted);
     278}
     279
     280// Converts unsigned long long value into compact 4-char
     281// representation. Examples: "1234", "1.2k", " 27M", "123T"
     282// Fifth char is always '\0'
     283void smart_ulltoa5(unsigned long long ul, char buf[5])
     284{
     285    const char *fmt;
     286    char c;
     287    unsigned v,idx = 0;
     288    ul *= 10;
     289    if (ul > 9999*10) { // do not scale if 9999 or less
     290        while (ul >= 10000) {
     291            ul /= 1024;
     292            idx++;
     293        }
     294    }
     295    v = ul; // ullong divisions are expensive, avoid them
     296
     297    fmt = " 123456789";
     298    if (!idx) {     // 9999 or less: use 1234 format
     299        c = buf[0] = " 123456789"[v/10000];
     300        if (c != ' ') fmt = "0123456789";
     301        c = buf[1] = fmt[v/1000%10];
     302        if (c != ' ') fmt = "0123456789";
     303        buf[2] = fmt[v/100%10];
     304        buf[3] = "0123456789"[v/10%10];
     305    } else {
     306        if (v >= 10*10) {   // scaled value is >=10: use 123M format
     307            c = buf[0] = " 123456789"[v/1000];
     308            if (c != ' ') fmt = "0123456789";
     309            buf[1] = fmt[v/100%10];
     310            buf[2] = "0123456789"[v/10%10];
     311        } else {    // scaled value is <10: use 1.2M format
     312            buf[0] = "0123456789"[v/10];
     313            buf[1] = '.';
     314            buf[2] = "0123456789"[v%10];
     315        }
     316        // see http://en.wikipedia.org/wiki/Tera
     317        buf[3] = " kMGTPEZY"[idx];
     318    }
     319    buf[4] = '\0';
     320}
     321
     322// Convert unsigned integer to ascii, writing into supplied buffer.
     323// A truncated result contains the first few digits of the result ala strncpy.
     324// Returns a pointer past last generated digit, does _not_ store NUL.
     325void BUG_sizeof_unsigned_not_4(void);
     326char *utoa_to_buf(unsigned n, char *buf, unsigned buflen)
     327{
     328    unsigned i, out, res;
     329    if (sizeof(unsigned) != 4)
     330        BUG_sizeof_unsigned_not_4();
     331    if (buflen) {
     332        out = 0;
     333        for (i = 1000000000; i; i /= 10) {
     334            res = n / i;
     335            if (res || out || i == 1) {
     336                if (!--buflen) break;
     337                out++;
     338                n -= res*i;
     339                *buf++ = '0' + res;
     340            }
     341        }
     342    }
     343    return buf;
     344}
     345
     346// Convert signed integer to ascii, like utoa_to_buf()
     347char *itoa_to_buf(int n, char *buf, unsigned buflen)
     348{
     349    if (buflen && n<0) {
     350        n = -n;
     351        *buf++ = '-';
     352        buflen--;
     353    }
     354    return utoa_to_buf((unsigned)n, buf, buflen);
     355}
     356
     357// The following two functions use a static buffer, so calling either one a
     358// second time will overwrite previous results.
     359//
     360// The largest 32 bit integer is -2 billion plus null terminator, or 12 bytes.
     361// Int should always be 32 bits on any remotely Unix-like system, see
     362// http://www.unix.org/whitepapers/64bit.html for the reasons why.
     363
     364static char local_buf[12];
     365
     366// Convert unsigned integer to ascii using a static buffer (returned).
     367char *utoa(unsigned n)
     368{
     369    *(utoa_to_buf(n, local_buf, sizeof(local_buf))) = '\0';
     370
     371    return local_buf;
     372}
     373
     374// Convert signed integer to ascii using a static buffer (returned).
     375char *itoa(int n)
     376{
     377    *(itoa_to_buf(n, local_buf, sizeof(local_buf))) = '\0';
     378
     379    return local_buf;
     380}
     381
     382// Emit a string of hex representation of bytes
     383char *bin2hex(char *p, const char *cp, int count)
     384{
     385    while (count) {
     386        unsigned char c = *cp++;
     387        /* put lowercase hex digits */
     388        *p++ = 0x20 | bb_hexdigits_upcase[c >> 4];
     389        *p++ = 0x20 | bb_hexdigits_upcase[c & 0xf];
     390        count--;
     391    }
     392    return p;
     393}
     394
     395// Die with an error message if we can't set gid.  (Because resource limits may
     396// limit this user to a given number of processes, and if that fills up the
     397// setgid() will fail and we'll _still_be_root_, which is bad.)
     398void xsetgid(gid_t gid)
     399{
     400    if (setgid(gid)) bb_perror_msg_and_die("setgid");
     401}
     402
     403// Die with an error message if we can't set uid.  (See xsetgid() for why.)
     404void xsetuid(uid_t uid)
     405{
     406    if (setuid(uid)) bb_perror_msg_and_die("setuid");
     407}
     408
     409// Return how long the file at fd is, if there's any way to determine it.
     410off_t fdlength(int fd)
     411{
     412    off_t bottom = 0, top = 0, pos;
     413    long size;
     414
     415    // If the ioctl works for this, return it.
     416
     417    if (ioctl(fd, BLKGETSIZE, &size) >= 0) return size*512;
     418
     419    // FIXME: explain why lseek(SEEK_END) is not used here!
     420
     421    // If not, do a binary search for the last location we can read.  (Some
     422    // block devices don't do BLKGETSIZE right.)
     423
     424    do {
     425        char temp;
     426
     427        pos = bottom + (top - bottom) / 2;
     428
     429        // If we can read from the current location, it's bigger.
     430
     431        if (lseek(fd, pos, SEEK_SET)>=0 && safe_read(fd, &temp, 1)==1) {
     432            if (bottom == top) bottom = top = (top+1) * 2;
     433            else bottom = pos;
     434
     435        // If we can't, it's smaller.
     436
     437        } else {
     438            if (bottom == top) {
     439                if (!top) return 0;
     440                bottom = top/2;
     441            }
     442            else top = pos;
     443        }
     444    } while (bottom + 1 != top);
     445
     446    return pos + 1;
     447}
     448
     449// Die with an error message if we can't malloc() enough space and do an
     450// sprintf() into that space.
     451char *xasprintf(const char *format, ...)
     452{
     453    va_list p;
     454    int r;
     455    char *string_ptr;
     456
     457#if 1
     458    // GNU extension
     459    va_start(p, format);
     460    r = vasprintf(&string_ptr, format, p);
     461    va_end(p);
     462#else
     463    // Bloat for systems that haven't got the GNU extension.
     464    va_start(p, format);
     465    r = vsnprintf(NULL, 0, format, p);
     466    va_end(p);
     467    string_ptr = xmalloc(r+1);
     468    va_start(p, format);
     469    r = vsnprintf(string_ptr, r+1, format, p);
     470    va_end(p);
    211471#endif
    212472
    213 #ifdef L_xspawn
    214 pid_t bb_xspawn(char **argv)
    215 {
    216     pid_t pid = bb_spawn(argv);
    217     if (pid < 0) bb_perror_msg_and_die("%s", *argv);
    218     return pid;
    219 }
     473    if (r < 0) bb_error_msg_and_die(bb_msg_memory_exhausted);
     474    return string_ptr;
     475}
     476
     477#if 0 /* If we will ever meet a libc which hasn't [f]dprintf... */
     478int fdprintf(int fd, const char *format, ...)
     479{
     480    va_list p;
     481    int r;
     482    char *string_ptr;
     483
     484#if 1
     485    // GNU extension
     486    va_start(p, format);
     487    r = vasprintf(&string_ptr, format, p);
     488    va_end(p);
     489#else
     490    // Bloat for systems that haven't got the GNU extension.
     491    va_start(p, format);
     492    r = vsnprintf(NULL, 0, format, p) + 1;
     493    va_end(p);
     494    string_ptr = malloc(r);
     495    if (string_ptr) {
     496        va_start(p, format);
     497        r = vsnprintf(string_ptr, r, format, p);
     498        va_end(p);
     499    }
    220500#endif
    221501
    222 #ifdef L_wait4
    223 int wait4pid(int pid)
    224 {
    225     int status;
    226 
    227     if (pid == -1 || waitpid(pid, &status, 0) == -1) return -1;
    228     if (WIFEXITED(status)) return WEXITSTATUS(status);
    229     if (WIFSIGNALED(status)) return WTERMSIG(status);
    230     return 0;
    231 }
    232 #endif 
    233 
    234 #ifdef L_setuid
    235 void xsetgid(gid_t gid)
    236 {
    237     if (setgid(gid)) bb_error_msg_and_die("setgid");
    238 }
    239 
    240 void xsetuid(uid_t uid)
    241 {
    242     if (setuid(uid)) bb_error_msg_and_die("setuid");
     502    if (r >= 0) {
     503        full_write(fd, string_ptr, r);
     504        free(string_ptr);
     505    }
     506    return r;
    243507}
    244508#endif
     509
     510// Die with an error message if we can't copy an entire FILE * to stdout, then
     511// close that file.
     512void xprint_and_close_file(FILE *file)
     513{
     514    fflush(stdout);
     515    // copyfd outputs error messages for us.
     516    if (bb_copyfd_eof(fileno(file), 1) == -1)
     517        xfunc_die();
     518
     519    fclose(file);
     520}
     521
     522// Die if we can't chdir to a new path.
     523void xchdir(const char *path)
     524{
     525    if (chdir(path))
     526        bb_perror_msg_and_die("chdir(%s)", path);
     527}
     528
     529// Print a warning message if opendir() fails, but don't die.
     530DIR *warn_opendir(const char *path)
     531{
     532    DIR *dp;
     533
     534    dp = opendir(path);
     535    if (!dp)
     536        bb_perror_msg("can't open '%s'", path);
     537    return dp;
     538}
     539
     540// Die with an error message if opendir() fails.
     541DIR *xopendir(const char *path)
     542{
     543    DIR *dp;
     544
     545    dp = opendir(path);
     546    if (!dp)
     547        bb_perror_msg_and_die("can't open '%s'", path);
     548    return dp;
     549}
     550
     551// Die with an error message if we can't open a new socket.
     552int xsocket(int domain, int type, int protocol)
     553{
     554    int r = socket(domain, type, protocol);
     555
     556    if (r < 0) {
     557        /* Hijack vaguely related config option */
     558#if ENABLE_VERBOSE_RESOLUTION_ERRORS
     559        const char *s = "INET";
     560        if (domain == AF_PACKET) s = "PACKET";
     561        if (domain == AF_NETLINK) s = "NETLINK";
     562USE_FEATURE_IPV6(if (domain == AF_INET6) s = "INET6";)
     563        bb_perror_msg_and_die("socket(AF_%s)", s);
     564#else
     565        bb_perror_msg_and_die("socket");
     566#endif
     567    }
     568
     569    return r;
     570}
     571
     572// Die with an error message if we can't bind a socket to an address.
     573void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen)
     574{
     575    if (bind(sockfd, my_addr, addrlen)) bb_perror_msg_and_die("bind");
     576}
     577
     578// Die with an error message if we can't listen for connections on a socket.
     579void xlisten(int s, int backlog)
     580{
     581    if (listen(s, backlog)) bb_perror_msg_and_die("listen");
     582}
     583
     584/* Die with an error message if sendto failed.
     585 * Return bytes sent otherwise  */
     586ssize_t xsendto(int s, const  void *buf, size_t len, const struct sockaddr *to,
     587                socklen_t tolen)
     588{
     589    ssize_t ret = sendto(s, buf, len, 0, to, tolen);
     590    if (ret < 0) {
     591        if (ENABLE_FEATURE_CLEAN_UP)
     592            close(s);
     593        bb_perror_msg_and_die("sendto");
     594    }
     595    return ret;
     596}
     597
     598// xstat() - a stat() which dies on failure with meaningful error message
     599void xstat(const char *name, struct stat *stat_buf)
     600{
     601    if (stat(name, stat_buf))
     602        bb_perror_msg_and_die("can't stat '%s'", name);
     603}
     604
     605// selinux_or_die() - die if SELinux is disabled.
     606void selinux_or_die(void)
     607{
     608#if ENABLE_SELINUX
     609    int rc = is_selinux_enabled();
     610    if (rc == 0) {
     611        bb_error_msg_and_die("SELinux is disabled");
     612    } else if (rc < 0) {
     613        bb_error_msg_and_die("is_selinux_enabled() failed");
     614    }
     615#else
     616    bb_error_msg_and_die("SELinux support is disabled");
     617#endif
     618}
     619
     620/* It is perfectly ok to pass in a NULL for either width or for
     621 * height, in which case that value will not be set.  */
     622int get_terminal_width_height(int fd, int *width, int *height)
     623{
     624    struct winsize win = { 0, 0, 0, 0 };
     625    int ret = ioctl(fd, TIOCGWINSZ, &win);
     626
     627    if (height) {
     628        if (!win.ws_row) {
     629            char *s = getenv("LINES");
     630            if (s) win.ws_row = atoi(s);
     631        }
     632        if (win.ws_row <= 1 || win.ws_row >= 30000)
     633            win.ws_row = 24;
     634        *height = (int) win.ws_row;
     635    }
     636
     637    if (width) {
     638        if (!win.ws_col) {
     639            char *s = getenv("COLUMNS");
     640            if (s) win.ws_col = atoi(s);
     641        }
     642        if (win.ws_col <= 1 || win.ws_col >= 30000)
     643            win.ws_col = 80;
     644        *width = (int) win.ws_col;
     645    }
     646
     647    return ret;
     648}
     649
     650void ioctl_or_perror_and_die(int fd, int request, void *argp, const char *fmt,...)
     651{
     652    va_list p;
     653
     654    if (ioctl(fd, request, argp) < 0) {
     655        va_start(p, fmt);
     656        bb_verror_msg(fmt, p, strerror(errno));
     657        /* xfunc_die can actually longjmp, so be nice */
     658        va_end(p);
     659        xfunc_die();
     660    }
     661}
     662
     663int ioctl_or_perror(int fd, int request, void *argp, const char *fmt,...)
     664{
     665    va_list p;
     666    int ret = ioctl(fd, request, argp);
     667
     668    if (ret < 0) {
     669        va_start(p, fmt);
     670        bb_verror_msg(fmt, p, strerror(errno));
     671        va_end(p);
     672    }
     673    return ret;
     674}
     675
     676#if ENABLE_IOCTL_HEX2STR_ERROR
     677int bb_ioctl_or_warn(int fd, int request, void *argp, const char *ioctl_name)
     678{
     679    int ret;
     680
     681    ret = ioctl(fd, request, argp);
     682    if (ret < 0)
     683        bb_perror_msg("%s", ioctl_name);
     684    return ret;
     685}
     686void bb_xioctl(int fd, int request, void *argp, const char *ioctl_name)
     687{
     688    if (ioctl(fd, request, argp) < 0)
     689        bb_perror_msg_and_die("%s", ioctl_name);
     690}
     691#else
     692int bb_ioctl_or_warn(int fd, int request, void *argp)
     693{
     694    int ret;
     695
     696    ret = ioctl(fd, request, argp);
     697    if (ret < 0)
     698        bb_perror_msg("ioctl %#x failed", request);
     699    return ret;
     700}
     701void bb_xioctl(int fd, int request, void *argp)
     702{
     703    if (ioctl(fd, request, argp) < 0)
     704        bb_perror_msg_and_die("ioctl %#x failed", request);
     705}
     706#endif
Note: See TracChangeset for help on using the changeset viewer.