bfc1508d (kx 2023-03-24 03:55:33 +0300 1)
bfc1508d (kx 2023-03-24 03:55:33 +0300 2) #ifdef HAVE_CONFIG_H
bfc1508d (kx 2023-03-24 03:55:33 +0300 3) #include <config.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 4) #endif
bfc1508d (kx 2023-03-24 03:55:33 +0300 5)
bfc1508d (kx 2023-03-24 03:55:33 +0300 6) #include <stdlib.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 7) #include <stdio.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 8) #include <sys/sysinfo.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 9) #include <sys/types.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 10) #include <stdint.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 11) #include <dirent.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 12) #include <sys/stat.h> /* chmod(2) */
bfc1508d (kx 2023-03-24 03:55:33 +0300 13) #include <sys/file.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 14) #include <sys/mman.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 15) #include <fcntl.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 16) #include <limits.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 17) #include <string.h> /* strdup(3) */
bfc1508d (kx 2023-03-24 03:55:33 +0300 18) #include <libgen.h> /* basename(3) */
bfc1508d (kx 2023-03-24 03:55:33 +0300 19) #include <ctype.h> /* tolower(3) */
bfc1508d (kx 2023-03-24 03:55:33 +0300 20) #include <errno.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 21) #include <time.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 22) #include <sys/time.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 23) #include <pwd.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 24) #include <grp.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 25) #include <stdarg.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 26) #include <poll.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 27) #include <unistd.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 28)
bfc1508d (kx 2023-03-24 03:55:33 +0300 29) #include <defs.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 30) #include <wrapper.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 31)
bfc1508d (kx 2023-03-24 03:55:33 +0300 32)
bfc1508d (kx 2023-03-24 03:55:33 +0300 33) #define WRAPPER_ERRMSG_SIZE 4096
bfc1508d (kx 2023-03-24 03:55:33 +0300 34)
bfc1508d (kx 2023-03-24 03:55:33 +0300 35) void wrapper_error( const char *fmt, ... )
bfc1508d (kx 2023-03-24 03:55:33 +0300 36) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 37) va_list arg_ptr;
bfc1508d (kx 2023-03-24 03:55:33 +0300 38) char buf[WRAPPER_ERRMSG_SIZE];
bfc1508d (kx 2023-03-24 03:55:33 +0300 39) char msg[WRAPPER_ERRMSG_SIZE];
bfc1508d (kx 2023-03-24 03:55:33 +0300 40) char *format = "%s: %s\n";
bfc1508d (kx 2023-03-24 03:55:33 +0300 41)
bfc1508d (kx 2023-03-24 03:55:33 +0300 42) va_start( arg_ptr, fmt );
bfc1508d (kx 2023-03-24 03:55:33 +0300 43)
bfc1508d (kx 2023-03-24 03:55:33 +0300 44) vsnprintf( msg, WRAPPER_ERRMSG_SIZE, (const void *)fmt, arg_ptr );
bfc1508d (kx 2023-03-24 03:55:33 +0300 45)
bfc1508d (kx 2023-03-24 03:55:33 +0300 46) va_end( arg_ptr ); /* Reset variable arguments. */
bfc1508d (kx 2023-03-24 03:55:33 +0300 47)
bfc1508d (kx 2023-03-24 03:55:33 +0300 48) snprintf( buf, WRAPPER_ERRMSG_SIZE, format, "wrapper", msg );
bfc1508d (kx 2023-03-24 03:55:33 +0300 49)
bfc1508d (kx 2023-03-24 03:55:33 +0300 50) (void)write( STDERR_FILENO, buf, strlen( buf ) );
bfc1508d (kx 2023-03-24 03:55:33 +0300 51)
bfc1508d (kx 2023-03-24 03:55:33 +0300 52) exit( 1 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 53) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 54)
bfc1508d (kx 2023-03-24 03:55:33 +0300 55) wrapper_errfunc wrapper_fatal = wrapper_error;
bfc1508d (kx 2023-03-24 03:55:33 +0300 56)
bfc1508d (kx 2023-03-24 03:55:33 +0300 57)
bfc1508d (kx 2023-03-24 03:55:33 +0300 58) char *xstrdup( const char *str )
bfc1508d (kx 2023-03-24 03:55:33 +0300 59) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 60) char *ret;
bfc1508d (kx 2023-03-24 03:55:33 +0300 61)
bfc1508d (kx 2023-03-24 03:55:33 +0300 62) ret = strdup( str );
bfc1508d (kx 2023-03-24 03:55:33 +0300 63) if( !ret )
bfc1508d (kx 2023-03-24 03:55:33 +0300 64) wrapper_fatal( "Out of memory, strdup failed" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 65) return ret;
bfc1508d (kx 2023-03-24 03:55:33 +0300 66) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 67)
bfc1508d (kx 2023-03-24 03:55:33 +0300 68) void *xmalloc( size_t size )
bfc1508d (kx 2023-03-24 03:55:33 +0300 69) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 70) void *ret;
bfc1508d (kx 2023-03-24 03:55:33 +0300 71)
bfc1508d (kx 2023-03-24 03:55:33 +0300 72) ret = malloc( size );
bfc1508d (kx 2023-03-24 03:55:33 +0300 73) if( !ret )
bfc1508d (kx 2023-03-24 03:55:33 +0300 74) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 75) wrapper_fatal( "Out of memory, malloc failed (tried to allocate %lu bytes)", (unsigned long)size );
bfc1508d (kx 2023-03-24 03:55:33 +0300 76) return NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 77) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 78) memset( ret, 0, size );
bfc1508d (kx 2023-03-24 03:55:33 +0300 79) return ret;
bfc1508d (kx 2023-03-24 03:55:33 +0300 80) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 81)
bfc1508d (kx 2023-03-24 03:55:33 +0300 82) void *xrealloc( void *ptr, size_t size )
bfc1508d (kx 2023-03-24 03:55:33 +0300 83) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 84) void *ret = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 85)
bfc1508d (kx 2023-03-24 03:55:33 +0300 86) ret = realloc( ptr, size );
bfc1508d (kx 2023-03-24 03:55:33 +0300 87) if( !ret && !size )
bfc1508d (kx 2023-03-24 03:55:33 +0300 88) ret = realloc( ptr, 1 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 89) if( !ret )
bfc1508d (kx 2023-03-24 03:55:33 +0300 90) wrapper_fatal( "Out of memory, realloc failed" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 91) return ret;
bfc1508d (kx 2023-03-24 03:55:33 +0300 92) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 93)
bfc1508d (kx 2023-03-24 03:55:33 +0300 94) /************************************************************************
bfc1508d (kx 2023-03-24 03:55:33 +0300 95) Limit size of IO chunks, because huge chunks only cause pain.
bfc1508d (kx 2023-03-24 03:55:33 +0300 96) OS X 64-bit is buggy, returning EINVAL if len >= INT_MAX; and even in
bfc1508d (kx 2023-03-24 03:55:33 +0300 97) the absence of bugs, large chunks can result in bad latencies when
bfc1508d (kx 2023-03-24 03:55:33 +0300 98) you decide to kill the process.
bfc1508d (kx 2023-03-24 03:55:33 +0300 99)
bfc1508d (kx 2023-03-24 03:55:33 +0300 100) We pick 8 MiB as our default, but if the platform defines SSIZE_MAX
bfc1508d (kx 2023-03-24 03:55:33 +0300 101) that is smaller than that, clip it to SSIZE_MAX, as a call to read(2)
bfc1508d (kx 2023-03-24 03:55:33 +0300 102) or write(2) larger than that is allowed to fail. As the last resort,
bfc1508d (kx 2023-03-24 03:55:33 +0300 103) we allow a port to pass via CFLAGS e.g. "-DMAX_IO_SIZE=value" to
bfc1508d (kx 2023-03-24 03:55:33 +0300 104) override this, if the definition of SSIZE_MAX given by the platform
bfc1508d (kx 2023-03-24 03:55:33 +0300 105) is broken.
bfc1508d (kx 2023-03-24 03:55:33 +0300 106) ************************************************************************/
bfc1508d (kx 2023-03-24 03:55:33 +0300 107) #ifndef MAX_IO_SIZE
bfc1508d (kx 2023-03-24 03:55:33 +0300 108) # define MAX_IO_SIZE_DEFAULT (8*1024*1024)
bfc1508d (kx 2023-03-24 03:55:33 +0300 109) # if defined(SSIZE_MAX) && (SSIZE_MAX < MAX_IO_SIZE_DEFAULT)
bfc1508d (kx 2023-03-24 03:55:33 +0300 110) # define MAX_IO_SIZE SSIZE_MAX
bfc1508d (kx 2023-03-24 03:55:33 +0300 111) # else
bfc1508d (kx 2023-03-24 03:55:33 +0300 112) # define MAX_IO_SIZE MAX_IO_SIZE_DEFAULT
bfc1508d (kx 2023-03-24 03:55:33 +0300 113) # endif
bfc1508d (kx 2023-03-24 03:55:33 +0300 114) #endif
bfc1508d (kx 2023-03-24 03:55:33 +0300 115)
bfc1508d (kx 2023-03-24 03:55:33 +0300 116) /*
bfc1508d (kx 2023-03-24 03:55:33 +0300 117) xopen() is the same as open(), but it die()s if the open() fails.
bfc1508d (kx 2023-03-24 03:55:33 +0300 118) */
bfc1508d (kx 2023-03-24 03:55:33 +0300 119) int xopen( const char *path, int oflag, ... )
bfc1508d (kx 2023-03-24 03:55:33 +0300 120) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 121) mode_t mode = 0;
bfc1508d (kx 2023-03-24 03:55:33 +0300 122) va_list ap;
bfc1508d (kx 2023-03-24 03:55:33 +0300 123)
bfc1508d (kx 2023-03-24 03:55:33 +0300 124) /*
bfc1508d (kx 2023-03-24 03:55:33 +0300 125) va_arg() will have undefined behavior if the specified type is not
bfc1508d (kx 2023-03-24 03:55:33 +0300 126) compatible with the argument type. Since integers are promoted to
bfc1508d (kx 2023-03-24 03:55:33 +0300 127) ints, we fetch the next argument as an int, and then cast it to a
bfc1508d (kx 2023-03-24 03:55:33 +0300 128) mode_t to avoid undefined behavior.
bfc1508d (kx 2023-03-24 03:55:33 +0300 129) */
bfc1508d (kx 2023-03-24 03:55:33 +0300 130) va_start( ap, oflag );
bfc1508d (kx 2023-03-24 03:55:33 +0300 131) if( oflag & O_CREAT )
bfc1508d (kx 2023-03-24 03:55:33 +0300 132) mode = va_arg( ap, int );
bfc1508d (kx 2023-03-24 03:55:33 +0300 133) va_end( ap );
bfc1508d (kx 2023-03-24 03:55:33 +0300 134)
bfc1508d (kx 2023-03-24 03:55:33 +0300 135) for( ;; )
bfc1508d (kx 2023-03-24 03:55:33 +0300 136) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 137) int fd = open( path, oflag, mode );
bfc1508d (kx 2023-03-24 03:55:33 +0300 138) if( fd >= 0 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 139) return fd;
bfc1508d (kx 2023-03-24 03:55:33 +0300 140) if( errno == EINTR )
bfc1508d (kx 2023-03-24 03:55:33 +0300 141) continue;
bfc1508d (kx 2023-03-24 03:55:33 +0300 142)
bfc1508d (kx 2023-03-24 03:55:33 +0300 143) if( (oflag & O_RDWR) == O_RDWR )
bfc1508d (kx 2023-03-24 03:55:33 +0300 144) wrapper_fatal( "could not open '%s' for reading and writing", path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 145) else if( (oflag & O_WRONLY) == O_WRONLY )
bfc1508d (kx 2023-03-24 03:55:33 +0300 146) wrapper_fatal( "could not open '%s' for writing", path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 147) else
bfc1508d (kx 2023-03-24 03:55:33 +0300 148) wrapper_fatal( "could not open '%s' for reading", path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 149) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 150) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 151)
bfc1508d (kx 2023-03-24 03:55:33 +0300 152) static int handle_nonblock( int fd, short poll_events, int err )
bfc1508d (kx 2023-03-24 03:55:33 +0300 153) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 154) struct pollfd pfd;
bfc1508d (kx 2023-03-24 03:55:33 +0300 155)
bfc1508d (kx 2023-03-24 03:55:33 +0300 156) if( err != EAGAIN && err != EWOULDBLOCK )
bfc1508d (kx 2023-03-24 03:55:33 +0300 157) return 0;
bfc1508d (kx 2023-03-24 03:55:33 +0300 158)
bfc1508d (kx 2023-03-24 03:55:33 +0300 159) pfd.fd = fd;
bfc1508d (kx 2023-03-24 03:55:33 +0300 160) pfd.events = poll_events;
bfc1508d (kx 2023-03-24 03:55:33 +0300 161)
bfc1508d (kx 2023-03-24 03:55:33 +0300 162) /*
bfc1508d (kx 2023-03-24 03:55:33 +0300 163) no need to check for errors, here;
bfc1508d (kx 2023-03-24 03:55:33 +0300 164) a subsequent read/write will detect unrecoverable errors
bfc1508d (kx 2023-03-24 03:55:33 +0300 165) */
bfc1508d (kx 2023-03-24 03:55:33 +0300 166) poll( &pfd, 1, -1 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 167) return 1;
bfc1508d (kx 2023-03-24 03:55:33 +0300 168) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 169)
bfc1508d (kx 2023-03-24 03:55:33 +0300 170) /*
bfc1508d (kx 2023-03-24 03:55:33 +0300 171) xread() is the same a read(), but it automatically restarts read()
bfc1508d (kx 2023-03-24 03:55:33 +0300 172) operations with a recoverable error (EAGAIN and EINTR). xread()
bfc1508d (kx 2023-03-24 03:55:33 +0300 173) DOES NOT GUARANTEE that "len" bytes is read even if the data is available.
bfc1508d (kx 2023-03-24 03:55:33 +0300 174) */
bfc1508d (kx 2023-03-24 03:55:33 +0300 175) ssize_t xread(int fd, void *buf, size_t len)
bfc1508d (kx 2023-03-24 03:55:33 +0300 176) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 177) ssize_t nr;
bfc1508d (kx 2023-03-24 03:55:33 +0300 178)
bfc1508d (kx 2023-03-24 03:55:33 +0300 179) if( len > MAX_IO_SIZE )
bfc1508d (kx 2023-03-24 03:55:33 +0300 180) len = MAX_IO_SIZE;
bfc1508d (kx 2023-03-24 03:55:33 +0300 181)
bfc1508d (kx 2023-03-24 03:55:33 +0300 182) while( 1 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 183) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 184) nr = read( fd, buf, len );
bfc1508d (kx 2023-03-24 03:55:33 +0300 185) if( nr < 0 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 186) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 187) if( errno == EINTR )
bfc1508d (kx 2023-03-24 03:55:33 +0300 188) continue;
bfc1508d (kx 2023-03-24 03:55:33 +0300 189) if( handle_nonblock(fd, POLLIN, errno) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 190) continue;
bfc1508d (kx 2023-03-24 03:55:33 +0300 191) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 192) return nr;
bfc1508d (kx 2023-03-24 03:55:33 +0300 193) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 194) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 195)
bfc1508d (kx 2023-03-24 03:55:33 +0300 196) /*
bfc1508d (kx 2023-03-24 03:55:33 +0300 197) xwrite() is the same a write(), but it automatically restarts write()
bfc1508d (kx 2023-03-24 03:55:33 +0300 198) operations with a recoverable error (EAGAIN and EINTR). xwrite() DOES NOT
bfc1508d (kx 2023-03-24 03:55:33 +0300 199) GUARANTEE that "len" bytes is written even if the operation is successful.
bfc1508d (kx 2023-03-24 03:55:33 +0300 200) */
bfc1508d (kx 2023-03-24 03:55:33 +0300 201) ssize_t xwrite( int fd, const void *buf, size_t len )
bfc1508d (kx 2023-03-24 03:55:33 +0300 202) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 203) ssize_t nr;
bfc1508d (kx 2023-03-24 03:55:33 +0300 204)
bfc1508d (kx 2023-03-24 03:55:33 +0300 205) if( len > MAX_IO_SIZE )
bfc1508d (kx 2023-03-24 03:55:33 +0300 206) len = MAX_IO_SIZE;
bfc1508d (kx 2023-03-24 03:55:33 +0300 207)
bfc1508d (kx 2023-03-24 03:55:33 +0300 208) while( 1 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 209) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 210) nr = write( fd, buf, len );
bfc1508d (kx 2023-03-24 03:55:33 +0300 211) if( nr < 0 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 212) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 213) if( errno == EINTR )
bfc1508d (kx 2023-03-24 03:55:33 +0300 214) continue;
bfc1508d (kx 2023-03-24 03:55:33 +0300 215) if( handle_nonblock(fd, POLLOUT, errno) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 216) continue;
bfc1508d (kx 2023-03-24 03:55:33 +0300 217) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 218) return nr;
bfc1508d (kx 2023-03-24 03:55:33 +0300 219) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 220) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 221)
bfc1508d (kx 2023-03-24 03:55:33 +0300 222) ssize_t read_in_full( int fd, void *buf, size_t count )
bfc1508d (kx 2023-03-24 03:55:33 +0300 223) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 224) char *p = buf;
bfc1508d (kx 2023-03-24 03:55:33 +0300 225) ssize_t total = 0;
bfc1508d (kx 2023-03-24 03:55:33 +0300 226)
bfc1508d (kx 2023-03-24 03:55:33 +0300 227) while( count > 0 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 228) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 229) ssize_t loaded = xread( fd, p, count );
bfc1508d (kx 2023-03-24 03:55:33 +0300 230)
bfc1508d (kx 2023-03-24 03:55:33 +0300 231) if (loaded < 0)
bfc1508d (kx 2023-03-24 03:55:33 +0300 232) return -1;
bfc1508d (kx 2023-03-24 03:55:33 +0300 233)
bfc1508d (kx 2023-03-24 03:55:33 +0300 234) if (loaded == 0)
bfc1508d (kx 2023-03-24 03:55:33 +0300 235) return total;
bfc1508d (kx 2023-03-24 03:55:33 +0300 236)
bfc1508d (kx 2023-03-24 03:55:33 +0300 237) count -= loaded;
bfc1508d (kx 2023-03-24 03:55:33 +0300 238) p += loaded;
bfc1508d (kx 2023-03-24 03:55:33 +0300 239) total += loaded;
bfc1508d (kx 2023-03-24 03:55:33 +0300 240) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 241)
bfc1508d (kx 2023-03-24 03:55:33 +0300 242) return total;
bfc1508d (kx 2023-03-24 03:55:33 +0300 243) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 244)
bfc1508d (kx 2023-03-24 03:55:33 +0300 245) ssize_t write_in_full( int fd, const void *buf, size_t count )
bfc1508d (kx 2023-03-24 03:55:33 +0300 246) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 247) const char *p = buf;
bfc1508d (kx 2023-03-24 03:55:33 +0300 248) ssize_t total = 0;
bfc1508d (kx 2023-03-24 03:55:33 +0300 249)
bfc1508d (kx 2023-03-24 03:55:33 +0300 250) while( count > 0 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 251) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 252) ssize_t written = xwrite( fd, p, count );
bfc1508d (kx 2023-03-24 03:55:33 +0300 253) if( written < 0 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 254) return -1;
bfc1508d (kx 2023-03-24 03:55:33 +0300 255)
bfc1508d (kx 2023-03-24 03:55:33 +0300 256) if( !written )
bfc1508d (kx 2023-03-24 03:55:33 +0300 257) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 258) errno = ENOSPC;
bfc1508d (kx 2023-03-24 03:55:33 +0300 259) return -1;
bfc1508d (kx 2023-03-24 03:55:33 +0300 260) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 261) count -= written;
bfc1508d (kx 2023-03-24 03:55:33 +0300 262) p += written;
bfc1508d (kx 2023-03-24 03:55:33 +0300 263) total += written;
bfc1508d (kx 2023-03-24 03:55:33 +0300 264) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 265)
bfc1508d (kx 2023-03-24 03:55:33 +0300 266) return total;
bfc1508d (kx 2023-03-24 03:55:33 +0300 267) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 268)
bfc1508d (kx 2023-03-24 03:55:33 +0300 269) int xdup( int fd )
bfc1508d (kx 2023-03-24 03:55:33 +0300 270) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 271) int ret = dup( fd );
bfc1508d (kx 2023-03-24 03:55:33 +0300 272) if( ret < 0 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 273) wrapper_fatal( "dup failed" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 274) return ret;
bfc1508d (kx 2023-03-24 03:55:33 +0300 275) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 276)
bfc1508d (kx 2023-03-24 03:55:33 +0300 277) /*
bfc1508d (kx 2023-03-24 03:55:33 +0300 278) xfopen() is the same as fopen(), but it die()s if the fopen() fails.
bfc1508d (kx 2023-03-24 03:55:33 +0300 279) */
bfc1508d (kx 2023-03-24 03:55:33 +0300 280) FILE *xfopen( const char *path, const char *mode )
bfc1508d (kx 2023-03-24 03:55:33 +0300 281) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 282) for( ;; )
bfc1508d (kx 2023-03-24 03:55:33 +0300 283) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 284) FILE *fp = fopen( path, mode );
bfc1508d (kx 2023-03-24 03:55:33 +0300 285) if (fp)
bfc1508d (kx 2023-03-24 03:55:33 +0300 286) return fp;
bfc1508d (kx 2023-03-24 03:55:33 +0300 287) if (errno == EINTR)
bfc1508d (kx 2023-03-24 03:55:33 +0300 288) continue;
bfc1508d (kx 2023-03-24 03:55:33 +0300 289)
bfc1508d (kx 2023-03-24 03:55:33 +0300 290) if( *mode && mode[1] == '+' )
bfc1508d (kx 2023-03-24 03:55:33 +0300 291) wrapper_fatal( "could not open '%s' for reading and writing", path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 292) else if( *mode == 'w' || *mode == 'a' )
bfc1508d (kx 2023-03-24 03:55:33 +0300 293) wrapper_fatal( "could not open '%s' for writing", path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 294) else
bfc1508d (kx 2023-03-24 03:55:33 +0300 295) wrapper_fatal( "could not open '%s' for reading", path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 296) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 297) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 298)
bfc1508d (kx 2023-03-24 03:55:33 +0300 299) FILE *xfdopen( int fd, const char *mode )
bfc1508d (kx 2023-03-24 03:55:33 +0300 300) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 301) FILE *stream = fdopen( fd, mode );
bfc1508d (kx 2023-03-24 03:55:33 +0300 302) if( stream == NULL )
bfc1508d (kx 2023-03-24 03:55:33 +0300 303) wrapper_fatal( "Out of memory? fdopen failed" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 304) return stream;
bfc1508d (kx 2023-03-24 03:55:33 +0300 305) }