This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] aio_write


Greetings,

Enclosed you will find a patch for the aio_write function. 
The goal of the patch is to come into POSIX 1003.1 compliance as defined by:

http://www.opengroup.org/onlinepubs/007904975/functions/aio_write.html

Additionally a new testcase is included which fits into the glibc test harness.

The authors of this code are Amos Waterland and myself both of the IBM LTC.

Fixed in this patch are the following bugs:

1) Check that the aio control block pointer is real. (f* operations that work
on FILE * do the same)

2) Validate that the file is open for a write operation

3) Validate the aio_nbytes aio_offset fields in the aio control block

4) If on completion of the __aio_enqueue_request errno==EINTR set errno
to 0 as this is in fact not an error and a residual of the fact that the
TEMP_FAILURE_RETRY macro does not reset errno when pwrite is interrupted.
(Can this macro be changed? Should it?)

Please Apply

-----------------
--- glibc-2.2.5/sysdeps/pthread/aio_write.c	Fri Jul  6 04:56:02 2001
+++ glibc/sysdeps/pthread/aio_write.c	Thu Jun 13 18:27:26 2002
@@ -22,11 +22,32 @@
 
 #include "aio_misc.h"
 
+#include <errno.h>
 
 int
 aio_write (aiocbp)
      struct aiocb *aiocbp;
 {
-  return (__aio_enqueue_request ((aiocb_union *) aiocbp, LIO_WRITE) == NULL
-	  ? -1 : 0);
+  int flags;
+  struct stat filestat;
+
+  if (aiocbp && ((flags=fcntl(aiocbp->aio_fildes, F_GETFL)) >=0 ) && (flags & (O_WRONLY | O_RDWR)) )
+    {
+      if ((long int) aiocbp->aio_nbytes >= 0 && (long int)aiocbp->aio_offset >=0 )
+        {
+          if(__aio_enqueue_request ((aiocb_union *) aiocbp, LIO_WRITE)==NULL)
+            return -1;
+          if (errno==EINTR)
+            __set_errno(0);
+          return 0;
+        }
+      else
+        {
+          __set_errno(EINVAL);
+          return -1;
+        }
+    }
+
+  __set_errno(EBADF);
+  return -1;
 }
--------------------
diff -uN --exclude=CVS glibc-2.2.5/rt/tst-aio_write.c glibc/rt/tst-aio_write.c
--- glibc-2.2.5/rt/tst-aio_write.c	Thu Jan  1 00:00:00 1970
+++ glibc/rt/tst-aio_write.c	Thu Jun 13 15:03:34 2002
@@ -0,0 +1,123 @@
+/* Tests for AIO in librt.
+   Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Tom Gall <tom_gall@vnet.ibm.com> and 
+   Amos Waterland <apw@us.ibm.com>, 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <aio.h>
+#include <errno.h>
+#include <error.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+/* Prototype for our test function.  */
+extern void do_prepare (int argc, char *argv[]);
+extern int do_test (int argc, char *argv[]);
+
+
+/* We might need a bit longer timeout.  */
+#define TIMEOUT 20 /* sec */
+
+/* This defines the `main' function and some more.  */
+#include <test-skeleton.c>
+
+
+/* These are for the temporary file we generate.  */
+char *name;
+int fd;
+
+#define FMT "aio_fildes: %i\treturn: %i\n"
+#define FMT2 "taio_fildes: 0x0\treturn: %i\n"
+
+void
+do_prepare (int argc, char *argv[])
+{
+}
+
+int
+do_test (int argc, char *argv[])
+{
+/* 
+ * test a couple of corner cases
+ */
+  int r;
+  struct aiocb cb;
+  char errorstring[255];
+
+  cb.aio_offset = 0;
+  cb.aio_buf = NULL;
+  cb.aio_nbytes = 0;
+  cb.aio_reqprio = 0;
+  cb.aio_sigevent.sigev_notify = SIGEV_NONE;
+
+  /* case: cb.aio_fildes is valid */
+  errno = 0; cb.aio_fildes = 1;
+  r = aio_write(&cb); 
+  if (errno)
+    {
+      sprintf(errorstring,FMT, cb.aio_fildes, r);
+      error(0,errno, errorstring);
+    }
+
+  /* case: cb.aio_fildes is NULL */
+  errno = 0;
+  r = aio_write(NULL); 
+  if (errno!=EBADF)
+    {
+      sprintf(errorstring,FMT2, r);
+      error(0,errno, errorstring);
+    }
+
+  /* case: cb.aio_fildes is not valid */
+  errno = 0; cb.aio_fildes = -1;
+  r = aio_write( &cb );
+  if (errno!=EBADF)
+    {
+      sprintf(errorstring,FMT,cb.aio_fildes, r);
+      error(0,errno, errorstring);
+    }
+
+  /* case : nbytes is invalid */
+  cb.aio_nbytes=-1;
+  cb.aio_buf = malloc(255);
+  cb.aio_fildes=open("/tmp/tst-aio_write", O_RDWR | O_CREAT,0600);
+  errno = 0; 
+  r = aio_write(&cb);
+  if (errno!=EINVAL)
+    {
+      sprintf(errorstring,FMT, cb.aio_fildes, r);
+      error(0,errno, errorstring);
+    }
+
+  /* case : offset is invalid */
+  cb.aio_offset=-1;
+  cb.aio_nbytes=255;
+  errno = 0; 
+  r = aio_write(&cb);
+  if (errno!=EINVAL)
+    {
+      sprintf(errorstring,FMT, cb.aio_fildes, r);
+      error(0,errno, errorstring);
+    }
+
+  close(cb.aio_fildes);
+
+  return 0;
+}

Regards,

Tom

Tom Gall - PPC64, PPC, Embedded  "Where's the ka-boom? There was
Linux Technology Center           supposed to be an earth
(w) tom_gall@vnet.ibm.com         shattering ka-boom!"
(w) 507-253-4558                 -- Marvin Martian
(h) tgall@rochcivictheatre.org 
http://www.ibm.com/linux/ltc


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]