(handle_iconv_error): Turn diagnostics into warnings
[gnupg.git] / util / iobuf.c
index 953d9f3..2cbde7f 100644 (file)
@@ -1,5 +1,6 @@
 /* iobuf.c  -  file handling
- *     Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2003,
+ *               2004 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -30,7 +31,7 @@
 #include <fcntl.h> 
 #include <unistd.h>
 #ifdef HAVE_DOSISH_SYSTEM
- #include <windows.h>
+#include <windows.h>
 #endif
 #ifdef __riscos__
 #include <kernel.h>
 #undef FILE_FILTER_USES_STDIO
 
 #ifdef HAVE_DOSISH_SYSTEM
- #define USE_SETMODE 1
+#define USE_SETMODE 1
 #endif
 
 #ifdef FILE_FILTER_USES_STDIO
- #define my_fileno(a)  fileno ((a))
- #define my_fopen_ro(a,b) fopen ((a),(b))
- #define my_fopen(a,b)    fopen ((a),(b))
- typedef FILE *FILEP_OR_FD;
- #define INVALID_FP    NULL
- #define FILEP_OR_FD_FOR_STDIN  (stdin)
- #define FILEP_OR_FD_FOR_STDOUT  (stdout)
- typedef struct {
+#define my_fileno(a)  fileno ((a))
+#define my_fopen_ro(a,b) fopen ((a),(b))
+#define my_fopen(a,b)    fopen ((a),(b))
+typedef FILE *FILEP_OR_FD;
+#define INVALID_FP    NULL
+#define FILEP_OR_FD_FOR_STDIN  (stdin)
+#define FILEP_OR_FD_FOR_STDOUT  (stdout)
+typedef struct {
      FILE *fp;    /* open file handle */
      int keep_open;
      int no_cache;
      char fname[1]; /* name of the file */
  } file_filter_ctx_t ;
 #else
- #define my_fileno(a)  (a)
- #define my_fopen_ro(a,b) fd_cache_open ((a),(b)) 
- #define my_fopen(a,b) direct_open ((a),(b)) 
- #ifdef HAVE_DOSISH_SYSTEM
-   typedef HANDLE FILEP_OR_FD;
-   #define INVALID_FP  ((HANDLE)-1)
-   #define FILEP_OR_FD_FOR_STDIN  (GetStdHandle (STD_INPUT_HANDLE))
-   #define FILEP_OR_FD_FOR_STDOUT (GetStdHandle (STD_OUTPUT_HANDLE))
-   #undef USE_SETMODE
- #else
-   typedef int FILEP_OR_FD;
-   #define INVALID_FP  (-1)
-   #define FILEP_OR_FD_FOR_STDIN  (0)
-   #define FILEP_OR_FD_FOR_STDOUT (1)
- #endif
- typedef struct {
+#define my_fileno(a)  (a)
+#define my_fopen_ro(a,b) fd_cache_open ((a),(b)) 
+#define my_fopen(a,b) direct_open ((a),(b)) 
+#ifdef HAVE_DOSISH_SYSTEM
+typedef HANDLE FILEP_OR_FD;
+#define INVALID_FP  ((HANDLE)-1)
+#define FILEP_OR_FD_FOR_STDIN  (GetStdHandle (STD_INPUT_HANDLE))
+#define FILEP_OR_FD_FOR_STDOUT (GetStdHandle (STD_OUTPUT_HANDLE))
+#undef USE_SETMODE
+#else
+typedef int FILEP_OR_FD;
+#define INVALID_FP  (-1)
+#define FILEP_OR_FD_FOR_STDIN  (0)
+#define FILEP_OR_FD_FOR_STDOUT (1)
+#endif
+typedef struct {
      FILEP_OR_FD  fp;     /* open file handle */
      int keep_open;
      int no_cache;
@@ -96,7 +97,7 @@
  static CLOSE_CACHE close_cache;
 #endif
 
-#ifdef __MINGW32__
+#ifdef _WIN32
 typedef struct {
     int sock;
     int keep_open;
@@ -105,7 +106,7 @@ typedef struct {
     int  print_only_name; /* flags indicating that fname is not a real file*/
     char fname[1]; /* name of the file */
 } sock_filter_ctx_t ;
-#endif /*__MINGW32__*/
+#endif /*_WIN32*/
 
 /* The first partial length header block must be of size 512
  * to make it easier (and efficienter) we use a min. block size of 512
@@ -129,8 +130,28 @@ static int special_names_enabled;
 static int underflow(IOBUF a);
 static int translate_file_handle ( int fd, int for_write );
 
+
+\f
 #ifndef FILE_FILTER_USES_STDIO
 
+/* This is a replacement for strcmp.  Under W32 it does not
+   distinguish between backslash and slash.  */
+static int
+fd_cache_strcmp (const char *a, const char *b)
+{
+#ifdef HAVE_DOSISH_SYSTEM
+  for (; *a && *b; a++, b++)
+    {
+      if (*a != *b && !((*a == '/' && *b == '\\') 
+                        || (*a == '\\' && *b == '/')) )
+        break;
+    }
+  return *(const unsigned char *)a - *(const unsigned char *)b;
+#else
+  return strcmp (a, b);
+#endif
+}
+
 /*
  * Invalidate (i.e. close) a cached iobuf
  */
@@ -144,14 +165,14 @@ fd_cache_invalidate (const char *fname)
         log_debug ("fd_cache_invalidate (%s)\n", fname);
 
     for (cc=close_cache; cc; cc = cc->next ) {
-        if ( cc->fp != INVALID_FP && !strcmp (cc->fname, fname) ) {
+        if ( cc->fp != INVALID_FP && !fd_cache_strcmp (cc->fname, fname) ) {
             if( DBG_IOBUF )
                 log_debug ("                did (%s)\n", cc->fname);
-          #ifdef HAVE_DOSISH_SYSTEM
+#ifdef HAVE_DOSISH_SYSTEM
             CloseHandle (cc->fp);
-          #else
+#else
            close(cc->fp);
-         #endif
+#endif
             cc->fp = INVALID_FP;
         }
     }
@@ -252,7 +273,7 @@ fd_cache_close (const char *fname, FILEP_OR_FD fp)
     }
     /* try to reuse a slot */
     for (cc=close_cache; cc; cc = cc->next ) {
-        if ( cc->fp == INVALID_FP && !strcmp (cc->fname, fname) ) {
+        if ( cc->fp == INVALID_FP && !fd_cache_strcmp (cc->fname, fname) ) {
             cc->fp = fp;
             if( DBG_IOBUF )
                 log_debug ("fd_cache_close (%s) used existing slot\n", fname);
@@ -279,23 +300,23 @@ fd_cache_open (const char *fname, const char *mode)
 
     assert (fname);
     for (cc=close_cache; cc; cc = cc->next ) {
-        if ( cc->fp != INVALID_FP && !strcmp (cc->fname, fname) ) {
+        if ( cc->fp != INVALID_FP && !fd_cache_strcmp (cc->fname, fname) ) {
             FILEP_OR_FD fp = cc->fp;
             cc->fp = INVALID_FP;
             if( DBG_IOBUF )
                 log_debug ("fd_cache_open (%s) using cached fp\n", fname);
-          #ifdef HAVE_DOSISH_SYSTEM
+#ifdef HAVE_DOSISH_SYSTEM
             if (SetFilePointer (fp, 0, NULL, FILE_BEGIN) == 0xffffffff ) {
-                log_error ("rewind file failed on handle %p: ec=%d\n",
-                           fp, (int)GetLastError () );
+                log_error ("rewind file failed on handle %p: %s\n",
+                           fp, w32_strerror (errno));
                 fp = INVALID_FP;
             }
-          #else
+#else
             if ( lseek (fp, 0, SEEK_SET) == (off_t)-1 ) {
                 log_error("can't rewind fd %d: %s\n", fp, strerror(errno) );
                 fp = INVALID_FP;
             }
-          #endif
+#endif
             return fp;
         }
     }
@@ -398,14 +419,14 @@ file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
            *ret_len = 0;       
        }
        else {
-          #ifdef HAVE_DOSISH_SYSTEM
+#ifdef HAVE_DOSISH_SYSTEM
             unsigned long nread;
 
             nbytes = 0;
             if ( !ReadFile ( f, buf, size, &nread, NULL ) ) {
-                int ec = (int)GetLastError ();
-                if ( ec != ERROR_BROKEN_PIPE ) {
-                    log_error("%s: read error: ec=%d\n", a->fname, ec);
+                if ((int)GetLastError () != ERROR_BROKEN_PIPE) {
+                    log_error ("%s: read error: %s\n", a->fname,
+                               w32_strerror (0));
                     rc = G10ERR_READ_FILE;
                 }
             }
@@ -417,7 +438,7 @@ file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
                 nbytes = nread;
             }
 
-          #else
+#else
 
             int n;
 
@@ -439,21 +460,21 @@ file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
             else {
                 nbytes = n;
             }
-          #endif
+#endif
            *ret_len = nbytes;
        }
     }
     else if( control == IOBUFCTRL_FLUSH ) {
        if( size ) {
-          #ifdef HAVE_DOSISH_SYSTEM
+#ifdef HAVE_DOSISH_SYSTEM
             byte *p = buf;
             unsigned long n;
 
             nbytes = size;
             do {
-                if ( size && !WriteFile ( f,  p, nbytes, &n, NULL) ) {
-                    int ec = (int)GetLastError ();
-                    log_error("%s: write error: ec=%d\n", a->fname, ec);
+                if (size && !WriteFile (f,  p, nbytes, &n, NULL)) {
+                    log_error ("%s: write error: %s\n", a->fname,
+                               w32_strerror (0));
                     rc = G10ERR_WRITE_FILE;
                     break;
                 }
@@ -461,7 +482,7 @@ file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
                 nbytes -= n;
             } while ( nbytes );
             nbytes = p - buf;
-          #else
+#else
             byte *p = buf;
             int n;
 
@@ -480,7 +501,7 @@ file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
                rc = G10ERR_WRITE_FILE;
            }
             nbytes = p - buf;
-          #endif
+#endif
        }
        *ret_len = nbytes;
     }
@@ -493,14 +514,14 @@ file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
        *(char**)buf = "file_filter(fd)";
     }
     else if ( control == IOBUFCTRL_FREE ) {
-      #ifdef HAVE_DOSISH_SYSTEM
+#ifdef HAVE_DOSISH_SYSTEM
         if ( f != FILEP_OR_FD_FOR_STDIN && f != FILEP_OR_FD_FOR_STDOUT ) {
            if( DBG_IOBUF )
                log_debug("%s: close handle %p\n", a->fname, f );
             if (!a->keep_open)
                 fd_cache_close (a->no_cache?NULL:a->fname, f);
         }
-      #else
+#else
        if ( (int)f != 0 && (int)f != 1 ) {
            if( DBG_IOBUF )
                log_debug("%s: close fd %d\n", a->fname, f );
@@ -508,14 +529,14 @@ file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
                 fd_cache_close (a->no_cache?NULL:a->fname, f);
        }
        f = INVALID_FP;
-      #endif
+#endif
        m_free (a); /* we can free our context now */
     }
 #endif /* !stdio implementation */
     return rc;
 }
 
-#ifdef __MINGW32__
+#ifdef _WIN32
 /* Becuase sockets are an special object under Lose32 we have to
  * use a special filter */
 static int
@@ -587,7 +608,7 @@ sock_filter (void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
     }
     return rc;
 }
-#endif /*__MINGW32__*/
+#endif /*_WIN32*/
 
 /****************
  * This is used to implement the block write mode.
@@ -665,28 +686,21 @@ block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
                            break;
                        }
                        a->size |= c;
+                       a->partial = 2;
+                       if( !a->size ) {
+                           a->eof = 1;
+                           if( !n )
+                               rc = -1;
+                           break;
+                       }
                    }
                    else { /* next partial body length */
                        a->size = 1 << (c & 0x1f);
                    }
            /*  log_debug("partial: ctx=%p c=%02x size=%u\n", a, c, a->size);*/
                }
-               else { /* the gnupg partial length scheme - much better :-) */
-                   c = iobuf_get(chain);
-                   a->size = c << 8;
-                   c = iobuf_get(chain);
-                   a->size |= c;
-                   if( c == -1 ) {
-                       log_error("block_filter: error reading length info\n");
-                       rc = G10ERR_READ_FILE;
-                   }
-                   if( !a->size ) {
-                       a->eof = 1;
-                       if( !n )
-                           rc = -1;
-                       break;
-                   }
-               }
+               else
+                 BUG();
            }
 
            while( !rc && size && a->size ) {
@@ -760,35 +774,8 @@ block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
                }
            }
        }
-       else { /* the gnupg scheme (which is not openpgp compliant) */
-           size_t avail, n;
-
-           for(p=buf; !rc && size; ) {
-               n = size;
-               avail = a->size - a->count;
-               if( !avail ) {
-                   if( n > a->size ) {
-                       iobuf_put( chain, (a->size >> 8) & 0xff );
-                       iobuf_put( chain, a->size & 0xff );
-                       avail = a->size;
-                       a->count = 0;
-                   }
-                   else {
-                       iobuf_put( chain, (n >> 8) & 0xff );
-                       iobuf_put( chain, n & 0xff );
-                       avail = n;
-                       a->count = a->size - n;
-                   }
-               }
-               if( n > avail )
-                   n = avail;
-               if( iobuf_write(chain, p, n ) )
-                   rc = G10ERR_WRITE_FILE;
-               a->count += n;
-               p += n;
-               size -= n;
-           }
-       }
+       else
+         BUG();
     }
     else if( control == IOBUFCTRL_INIT ) {
        if( DBG_IOBUF )
@@ -844,10 +831,8 @@ block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
                }
                m_free( a->buffer ); a->buffer = NULL; a->buflen = 0;
            }
-           else {
-               iobuf_writebyte(chain, 0);
-               iobuf_writebyte(chain, 0);
-           }
+           else
+             BUG();
        }
        else if( a->size ) {
            log_error("block_filter: pending bytes!\n");
@@ -950,18 +935,18 @@ iobuf_cancel( IOBUF a )
     const char *s;
     IOBUF a2;
     int rc;
-  #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
+#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
     char *remove_name = NULL;
-  #endif
+#endif
 
     if( a && a->use == 2 ) {
        s = iobuf_get_real_fname(a);
        if( s && *s ) {
-         #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
+#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
            remove_name = m_strdup ( s );
-         #else
+#else
            remove(s);
-         #endif
+#endif
        }
     }
 
@@ -974,14 +959,14 @@ iobuf_cancel( IOBUF a )
     }
 
     rc = iobuf_close(a);
-  #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
+#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
     if ( remove_name ) {
        /* Argg, MSDOS does not allow to remove open files.  So
         * we have to do it here */
        remove ( remove_name );
        m_free ( remove_name );
     }
-  #endif
+#endif
     return rc;
 }
 
@@ -1032,7 +1017,7 @@ check_special_filename ( const char *fname )
         int i;
 
         fname += 2;
-        for (i=0; isdigit (fname[i]); i++ )
+        for (i=0; digitp (fname+i); i++ )
             ;
         if ( !fname[i] ) 
             return atoi (fname);
@@ -1040,6 +1025,16 @@ check_special_filename ( const char *fname )
     return -1;
 }
 
+/* This fucntion returns true if FNAME indicates a PIPE (stdout or
+   stderr) or a special file name if those are enabled. */
+int
+iobuf_is_pipe_filename (const char *fname)
+{
+  if (!fname || (*fname=='-' && !fname[1]) )
+    return 1;
+  return check_special_filename (fname) != -1;
+}
+
 /****************
  * Create a head iobuf for reading from a file
  * returns: NULL if an error occures and sets errno
@@ -1056,9 +1051,9 @@ iobuf_open( const char *fname )
 
     if( !fname || (*fname=='-' && !fname[1])  ) {
        fp = FILEP_OR_FD_FOR_STDIN;
-      #ifdef USE_SETMODE
+#ifdef USE_SETMODE
        setmode ( my_fileno(fp) , O_BINARY );
-      #endif
+#endif
        fname = "[stdin]";
        print_only = 1;
     }
@@ -1122,7 +1117,7 @@ IOBUF
 iobuf_sockopen ( int fd, const char *mode )
 {
     IOBUF a;
-#ifdef __MINGW32__
+#ifdef _WIN32
     sock_filter_ctx_t *scx;
     size_t len;
 
@@ -1159,9 +1154,9 @@ iobuf_create( const char *fname )
 
     if( !fname || (*fname=='-' && !fname[1]) ) {
        fp = FILEP_OR_FD_FOR_STDOUT;
-      #ifdef USE_SETMODE
+#ifdef USE_SETMODE
        setmode ( my_fileno(fp) , O_BINARY );
-      #endif
+#endif
        fname = "[stdout]";
        print_only = 1;
     }
@@ -1261,22 +1256,22 @@ iobuf_ioctl ( IOBUF a, int cmd, int intval, void *ptrval )
                 b->keep_open = intval;
                 return 0;
             }
-          #ifdef __MINGW32__
+#ifdef _WIN32
             else if( !a->chain && a->filter == sock_filter ) {
                 sock_filter_ctx_t *b = a->filter_ov;
                 b->keep_open = intval;
                 return 0;
             }
-          #endif
+#endif
     }
     else if ( cmd == 2 ) {  /* invalidate cache */
         if( DBG_IOBUF )
             log_debug("iobuf-*.*: ioctl `%s' invalidate\n",
                       ptrval? (char*)ptrval:"?");
         if ( !a && !intval && ptrval ) {
-          #ifndef FILE_FILTER_USES_STDIO
+#ifndef FILE_FILTER_USES_STDIO
             fd_cache_invalidate (ptrval);
-          #endif
+#endif
             return 0;
         }
     }
@@ -1290,13 +1285,13 @@ iobuf_ioctl ( IOBUF a, int cmd, int intval, void *ptrval )
                 b->no_cache = intval;
                 return 0;
             }
-          #ifdef __MINGW32__
+#ifdef _WIN32
             else if( !a->chain && a->filter == sock_filter ) {
                 sock_filter_ctx_t *b = a->filter_ov;
                 b->no_cache = intval;
                 return 0;
             }
-          #endif
+#endif
     }
 
     return -1;
@@ -1389,7 +1384,7 @@ iobuf_push_filter2( IOBUF a,
 /****************
  * Remove an i/o filter.
  */
-int
+static int
 pop_filter( IOBUF a, int (*f)(void *opaque, int control,
                      IOBUF chain, byte *buf, size_t *len), void *ov )
 {
@@ -1587,7 +1582,8 @@ iobuf_flush(IOBUF a)
        char *newbuf;
        size_t newsize = a->d.size + 8192;
 
-       log_debug("increasing temp iobuf from %lu to %lu\n",
+       if( DBG_IOBUF )
+         log_debug("increasing temp iobuf from %lu to %lu\n",
                    (ulong)a->d.size, (ulong)newsize );
        newbuf = m_alloc( newsize );
        memcpy( newbuf, a->d.buf, a->d.len );
@@ -1856,24 +1852,46 @@ iobuf_get_filelength( IOBUF a )
            file_filter_ctx_t *b = a->filter_ov;
            FILEP_OR_FD fp = b->fp;
 
-          #if defined(HAVE_DOSISH_SYSTEM) && !defined(FILE_FILTER_USES_STDIO)
+#if defined(HAVE_DOSISH_SYSTEM) && !defined(FILE_FILTER_USES_STDIO)
             ulong size;
 
-            if ( (size=GetFileSize (fp, NULL)) != 0xffffffff ) 
+            if  ((size=GetFileSize (fp, NULL)) != 0xffffffff)
                 return size;
-            log_error ("GetFileSize for handle %p failed: ec=%d\n",
-                       fp, (int)GetLastError () );
-          #else
+            log_error ("GetFileSize for handle %p failed: %s\n",
+                       fp, w32_strerror (0));
+#else
             if( !fstat(my_fileno(fp), &st) )
                return st.st_size;
            log_error("fstat() failed: %s\n", strerror(errno) );
-          #endif
+#endif
            break;
        }
 
     return 0;
 }
 
+
+/* Return the file descriptor of the underlying file or -1 if it is
+   not available.  */
+int 
+iobuf_get_fd (IOBUF a)
+{
+  if (a->directfp)
+    return fileno ( (FILE*)a->directfp );
+
+  for ( ; a; a = a->chain )
+    if (!a->chain && a->filter == file_filter)
+      {
+        file_filter_ctx_t *b = a->filter_ov;
+        FILEP_OR_FD fp = b->fp;
+
+        return my_fileno (fp);
+      }
+
+  return -1;
+}
+
+
 /****************
  * Tell the file position, where the next read will take place
  */
@@ -1945,18 +1963,18 @@ iobuf_seek( IOBUF a, off_t newpos )
            return -1;
        }
 #else
-    #ifdef HAVE_DOSISH_SYSTEM
+#ifdef HAVE_DOSISH_SYSTEM
        if (SetFilePointer (b->fp, newpos, NULL, FILE_BEGIN) == 0xffffffff ) {
-           log_error ("SetFilePointer failed on handle %p: ec=%d\n",
-                      b->fp, (int)GetLastError () );
+           log_error ("SetFilePointer failed on handle %p: %s\n",
+                      b->fp, w32_strerror (0));
            return -1;
        }
-    #else
+#else
        if ( lseek (b->fp, newpos, SEEK_SET) == (off_t)-1 ) {
            log_error("can't lseek: %s\n", strerror(errno) );
            return -1;
        }
-    #endif
+#endif
 #endif
     }
     a->d.len = 0;   /* discard buffer */
@@ -2015,28 +2033,6 @@ iobuf_get_fname( IOBUF a )
     return NULL;
 }
 
-/****************
- * Start the block write mode, see rfc1991.new for details.
- * A value of 0 for N stops this mode (flushes and writes
- * the end marker)
- */
-void
-iobuf_set_block_mode( IOBUF a, size_t n )
-{
-    block_filter_ctx_t *ctx = m_alloc_clear( sizeof *ctx );
-
-    assert( a->use == 1 || a->use == 2 );
-    ctx->use = a->use;
-    if( !n ) {
-       if( a->use == 1 )
-           log_debug("pop_filter called in set_block_mode - please report\n");
-       pop_filter(a, block_filter, NULL );
-    }
-    else {
-       ctx->size = n; /* only needed for use 2 */
-       iobuf_push_filter(a, block_filter, ctx );
-    }
-}
 
 /****************
  * enable partial block mode as described in the OpenPGP draft.
@@ -2065,19 +2061,6 @@ iobuf_set_partial_block_mode( IOBUF a, size_t len )
 
 
 /****************
- * Checks whether the stream is in block mode
- * Note: This does not work if other filters are pushed on the stream.
- */
-int
-iobuf_in_block_mode( IOBUF a )
-{
-    if( a && a->filter == block_filter )
-       return 1; /* yes */
-    return 0; /* no */
-}
-
-
-/****************
  * Same as fgets() but if the buffer is too short a larger one will
  * be allocated up to some limit *max_length.
  * A line is considered a byte stream ending in a LF.
@@ -2140,7 +2123,7 @@ iobuf_read_line( IOBUF a, byte **addr_of_buffer,
 int
 iobuf_translate_file_handle ( int fd, int for_write )
 {
-  #ifdef __MINGW32__
+#ifdef _WIN32
     {
         int x;
             
@@ -2156,17 +2139,17 @@ iobuf_translate_file_handle ( int fd, int for_write )
             fd = x;
         }
     }
-  #endif
+#endif
     return fd;
 }
 
 static int
 translate_file_handle ( int fd, int for_write )
 {
-  #ifdef __MINGW32__
-   #ifdef FILE_FILTER_USES_STDIO  
+#ifdef _WIN32
+#ifdef FILE_FILTER_USES_STDIO  
     fd = iobuf_translate_file_handle (fd, for_write);
-   #else
+#else
     {
         int x;
 
@@ -2180,14 +2163,49 @@ translate_file_handle ( int fd, int for_write )
             x = fd;
 
         if (x == -1)
-            log_debug ("GetStdHandle(%d) failed: ec=%d\n",
-                       fd, (int)GetLastError () );
+            log_debug ("GetStdHandle(%d) failed: %s\n",
+                       fd, w32_strerror (0));
 
         fd = x;
     }
-   #endif
-  #endif
+#endif
+#endif
     return fd;
 }
 
 
+void
+iobuf_skip_rest(IOBUF a, unsigned long n, int partial)
+{
+    if ( partial ) {
+       for (;;) {
+           if (a->nofast || a->d.start >= a->d.len) {
+               if (iobuf_readbyte (a) == -1) {
+                   break;
+               }
+           } else {
+               unsigned long count = a->d.len - a->d.start;
+               a->nbytes += count;
+               a->d.start = a->d.len;
+           }
+       }
+    } else {
+       unsigned long remaining = n;
+       while (remaining > 0) {
+           if (a->nofast || a->d.start >= a->d.len) {
+               if (iobuf_readbyte (a) == -1) {
+                   break;
+               }
+               --remaining;
+           } else {
+               unsigned long count = a->d.len - a->d.start;
+               if (count > remaining) {
+                   count = remaining;
+               }
+               a->nbytes += count;
+               a->d.start += count;
+               remaining -= count;
+           }
+       }
+    }
+}