cSvn-UI for SVN Repositories

cGit-UI – is a web interface for Subversion (SVN) Repositories. cSvn CGI script is writen in C and therefore it's fast enough

6 Commits   0 Branches   2 Tags
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) }