From 445133eb42c25dc9271cf05fc8b6a5055327e168 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?=
 <grubba@grubba.org>
Date: Thu, 1 Apr 1999 00:01:46 +0200
Subject: [PATCH] write() now accepts an array(string) as the first argument,
 and will use writev() if it exists. If an error occurs write() and
 write_oob() will now return the number of bytes successfully written if any
 and -1 if none were.

Rev: src/modules/files/file.c:1.140
---
 src/modules/files/file.c | 146 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 136 insertions(+), 10 deletions(-)

diff --git a/src/modules/files/file.c b/src/modules/files/file.c
index 0a07807ef9..ff8565a94f 100644
--- a/src/modules/files/file.c
+++ b/src/modules/files/file.c
@@ -3,9 +3,9 @@
 ||| Pike is distributed as GPL (General Public License)
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
-
+/**/
 #include "global.h"
-RCSID("$Id: file.c,v 1.139 1999/02/01 09:49:12 hubbe Exp $");
+RCSID("$Id: file.c,v 1.140 1999/03/31 22:01:46 grubba Exp $");
 #include "fdlib.h"
 #include "interpret.h"
 #include "svalue.h"
@@ -29,12 +29,12 @@ RCSID("$Id: file.c,v 1.139 1999/02/01 09:49:12 hubbe Exp $");
 
 #ifdef HAVE_SYS_TYPE_H
 #include <sys/types.h>
-#endif
+#endif /* HAVE_SYS_TYPE_H */
 
 #include <sys/stat.h>
 #ifdef HAVE_SYS_PARAM_H
 #include <sys/param.h>
-#endif
+#endif /* HAVE_SYS_PARAM_H */
 #include <errno.h>
 #include <fcntl.h>
 #include <signal.h>
@@ -47,6 +47,10 @@ RCSID("$Id: file.c,v 1.139 1999/02/01 09:49:12 hubbe Exp $");
 #  include <sys/socket.h>
 #endif
 
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif /* HAVE_SYS_UIO_H */
+
 #ifdef HAVE_WINSOCK_H
 #  include <winsock.h>
 #ifndef EWOULDBLOCK
@@ -869,9 +873,126 @@ static void file_write(INT32 args)
   INT32 written,i;
   struct pike_string *str;
 
-  if(args<1 || sp[-args].type != T_STRING)
+  if(args<1 || (sp[-args].type != T_STRING) && (sp[-args].type != T_ARRAY))
     error("Bad argument 1 to file->write().\n");
 
+  if(FD < 0)
+    error("File not open for write.\n");
+  
+  if (sp[-args].type == T_ARRAY) {
+    struct array *a = sp[-args].u.array;
+    i = a->size;
+    while(i--) {
+      if ((a->item[i].type != T_STRING) || (a->item[i].u.string->size_shift)) {
+	error("Bad argument 1 to file->write().\n");
+      }
+    }
+
+#ifdef HAVE_WRITEV
+    if (args > 1) {
+#endif /* HAVE_WRITEV */
+      ref_push_array(a);
+      push_constant_text("");
+      o_mult();
+      sp--;
+      assign_svalue(sp-args, sp);
+
+#ifdef PIKE_DEBUG
+      if (sp[-args].type != T_STRING) {
+	error("Bad return value from string multiplication.");
+      }
+#endif /* PIKE_DEBUG */
+#ifdef HAVE_WRITEV
+    } else if (!a->size) {
+      /* Special case for empty array */
+      pop_stack();
+      push_int(0);
+      return;
+    } else {
+      struct iovec *iovbase = xalloc(sizeof(struct iovec)*a->size);
+      struct iovec *iov = iovbase;
+      int iovcnt = a->size;
+
+      i = a->size;
+      while(i--) {
+	iov->iov_base = a->item[i].u.string->str;
+	iov->iov_len = a->item[i].u.string->len;
+      }
+
+      for(written = 0; iovcnt; check_signals(0,0,0)) {
+	int fd = FD;
+	int cnt = iovcnt;
+	THREADS_ALLOW();
+	if (cnt > IOV_MAX) {
+	  cnt = IOV_MAX;
+	}
+	i = writev(fd, iov, cnt);
+	THREADS_DISALLOW();
+
+#ifdef _REENTRANT
+	if (FD<0) {
+	  free(iovbase);
+	  error("File destructed while in file->write.\n");
+	}
+#endif
+	if(i<0)
+	{
+	  switch(errno)
+	  {
+	  default:
+	    free(iovbase);
+	    ERRNO=errno;
+	    pop_n_elems(args);
+	    if (!written) {
+	      push_int(-1);
+	    } else {
+	      push_int(written);
+	    }
+	    return;
+
+	  case EINTR: continue;
+	  case EWOULDBLOCK: break;
+	  }
+	  break;
+	}else{
+	  written += i;
+
+	  /* Avoid extra writev() */
+	  if(THIS->open_mode & FILE_NONBLOCKING)
+	    break;
+
+	  while(i) {
+	    if (iov->iov_len <= i) {
+	      i -= iov->iov_len;
+	      iov++;
+	      iovcnt--;
+	    } else {
+	      /* Use cast since iov_base might be a void pointer */
+	      iov->iov_base = ((char *) iov->iov_base) + i;
+	      iov->iov_len -= i;
+	      i = 0;
+	    }
+	  }
+	}
+      }
+
+      free(iovbase);
+
+      if(!IS_ZERO(& THIS->write_callback))
+      {
+	set_write_callback(FD, file_write_callback, THIS);
+	SET_INTERNAL_REFERENCE(THIS);
+      }
+      ERRNO=0;
+
+      pop_stack();
+      push_int(written);
+    }
+#endif /* HAVE_WRITEV */
+  }
+
+  /* At this point sp[-args].type is T_STRING */
+
   if(args > 1)
   {
     extern void f_sprintf(INT32);
@@ -879,9 +1000,6 @@ static void file_write(INT32 args)
     args=1;
   }
 
-  if(FD < 0)
-    error("File not open for write.\n");
-  
   str=sp[-args].u.string;
 
   for(written=0;written < str->len;check_signals(0,0,0))
@@ -902,7 +1020,11 @@ static void file_write(INT32 args)
       default:
 	ERRNO=errno;
 	pop_n_elems(args);
-	push_int(-1);
+	if (!written) {
+	  push_int(-1);
+	} else {
+	  push_int(written);
+	}
 	return;
 
       case EINTR: continue;
@@ -969,7 +1091,11 @@ static void file_write_oob(INT32 args)
       default:
 	ERRNO=errno;
 	pop_n_elems(args);
-	push_int(-1);
+	if (!written) {
+	  push_int(-1);
+	} else {
+	  push_int(written);
+	}
 	return;
 
       case EINTR: continue;
-- 
GitLab