diff --git a/src/modules/_Stdio/buffer.cmod b/src/modules/_Stdio/buffer.cmod
index c226336ae2b8dcac560184c6df7879405f824057..f5b933ed4dbbd99fadfb0aad62b0e97a36bb3110 100644
--- a/src/modules/_Stdio/buffer.cmod
+++ b/src/modules/_Stdio/buffer.cmod
@@ -457,25 +457,27 @@ PIKECLASS IOBuffer
 #undef THIS
 #define THIS (&(((struct IOBuffer_struct *)Pike_fp->current_storage)->b))
 
-  /*! @decl int(0..) input_from( Stdio.Stream f )
+  /*! @decl int(0..) input_from( Stdio.Stream f, int|void nbytes )
    *!
-   *! Read data from @[f] into this buffer.
+   *! Read data from @[f] into this buffer. If @[nbytes] is not
+   *! specified, read until there is no more data to read (currently).
    *!
    *! Returns the amount of data that was read
    *!
    *! @note
    *! Please note that this funcition will read all data from the
    *! filedescriptor unless it's set to be non-blocking.
-   *!
-   *! It is designed to only be used in non-blocking IO mode.
    */
-  PIKEFUN int(0..) input_from( object f )
+  PIKEFUN int(0..) input_from( object f, int|void _nbytes )
   {
     IOBuffer *io = THIS;
     size_t sz = io_len( io );
-    size_t bread = 0;
+    size_t bread = 0, nbytes = (size_t)-1;
     struct my_file *fd;
 
+    if( _nbytes )
+        nbytes = _nbytes->u.integer;
+
     if( (fd = get_storage( f, file_program )) )
     {
       while( 1 )
@@ -483,14 +485,14 @@ PIKECLASS IOBuffer
         unsigned char *ptr = io_add_space( io, 4096, 0 );
         int res;
 
-        res = fd_read( fd->box.fd, ptr, 4096 );
+        res = fd_read( fd->box.fd, ptr, MINIMUM(4096,nbytes) );
 
         if( res == -1 && errno == EINTR )
           continue;
 
         if( res <= 0 )
           break;
-
+        nbytes -= res;
         io->len += res;
         bread += res;
         if( res != 4096 )
@@ -500,48 +502,56 @@ PIKECLASS IOBuffer
     }
     else
     {
-      /* some other object. Just call write */
-      while( 1 )
+      /* some other object. Just call read */
+      while( nbytes )
       {
-        push_int( 4096 );
+        push_int( MINIMUM(4096,nbytes) );
         safe_apply( f, "read", 1 );
         if( TYPEOF(Pike_sp[-1]) != PIKE_T_STRING || Pike_sp[-1].u.string->len == 0 )
           break;
         if( Pike_sp[-1].u.string->size_shift )
             Pike_error("Can not handle non-8bit data\n");
         io_append( io, Pike_sp[-1].u.string->str, Pike_sp[-1].u.string->len );
+        nbytes -= Pike_sp[-1].u.string->len;
         pop_stack();
       }
     }
     RETURN bread;
   }
 
-  /*! @decl int output_to( Stdio.Stream f )
+  /*! @decl int output_to( Stdio.Stream f, int|void nbytes )
    *!
    *! Write data from the buffer to the indicated file.
    *!
    *! Will return the number of bytes that were successfully written.
+   *!
+   *! If @[nbytes] is not specified the whole buffer will be written
+   *! if possible.  Otherwise at most @[nbytes] will be written.
    */
-  PIKEFUN int(0..) output_to( object f )
+  PIKEFUN int(0..) output_to( object f, int|void _nbytes )
   {
     IOBuffer *io = THIS;
     size_t sz = io_len( io );
-    size_t written = 0;
+    size_t written = 0, nbytes = (size_t)-1;
     struct my_file *fd;
     INT_TYPE *wr = &Pike_sp->u.integer;
 
+    if( !sz )
+        io_range_error(io,  sz);
+
+    if( _nbytes )
+        nbytes = _nbytes->u.integer;
+
     if( (fd = get_storage( f, file_program )) )
     {
       /* lock this object. */
       io_lock(io);
 
-      // THREADS_ALLOW();
-      while( sz > written )
+      while( sz > written && nbytes )
       {
-        size_t rd = MIN(sz-written,4096);
+        size_t rd = MINIMUM(MINIMUM(sz-written,4096),nbytes);
         unsigned char *ptr = io_read_pointer( io );
-        int res;
-
+        ssize_t res;
         res = fd_write( fd->box.fd, ptr, rd );
         if( res == -1 && errno == EINTR )
           continue;
@@ -550,15 +560,13 @@ PIKECLASS IOBuffer
         io_consume( io, res );
         written += res;
       }
-      // THREADS_DISALLOW();
-      // io_unlock(io);
     }
     else
     {
       /* some other object. Just call write */
-      while( sz > written )
+      while( sz > written && nbytes)
       {
-        size_t rd = MIN(sz-written,4096);
+        size_t rd = MINIMUM(MINIMUM(sz-written,4096),nbytes);
         struct pike_string *s = io_read_string( io, rd );
         if( !s )
           break;