-GArik: fix typo
[oweals/gnunet.git] / src / util / disk.c
index a5190d587c773f031e2bf21852c55f6076108f8d..b2a70559359df312c03aadb30799eb5e4f598e70 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     (C) 2001, 2002, 2005, 2006, 2009 Christian Grothoff (and other contributing authors)
+     (C) 2001--2012 Christian Grothoff (and other contributing authors)
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -115,7 +115,7 @@ struct GetFileSizeData
 };
 
 
-int
+static int
 translate_unix_perms (enum GNUNET_DISK_AccessPermissions perm)
 {
   int mode;
@@ -420,6 +420,7 @@ GNUNET_DISK_mktemp (const char *t)
   fn = tmpl;
 #endif
   /* FIXME: why is this not MKSTEMP()? This function is implemented in plibc.
+   * CG: really? If I put MKSTEMP here, I get a compilation error...
    * It will assume that fn is UTF-8-encoded, if compiled with UTF-8 support.
    */
   fd = mkstemp (fn);
@@ -531,6 +532,7 @@ GNUNET_DISK_directory_test (const char *fil)
   return GNUNET_YES;
 }
 
+
 /**
  * Check that fil corresponds to a filename
  * (of a file that exists and that is not a directory).
@@ -746,6 +748,7 @@ GNUNET_DISK_file_read (const struct GNUNET_DISK_FileHandle * h, void *result,
 #endif
 }
 
+
 /**
  * Read the contents of a binary file into a buffer.
  * Guarantees not to block (returns GNUNET_SYSERR and sets errno to EAGAIN
@@ -809,8 +812,17 @@ GNUNET_DISK_file_read_non_blocking (const struct GNUNET_DISK_FileHandle * h,
   }
   return bytesRead;
 #else
-  /* FIXME: set to non-blocking (fcntl?), read, then set back? */
-  return read (h->fd, result, len);
+  int flags;
+  ssize_t ret;
+
+  /* set to non-blocking, read, then set back */
+  flags = fcntl (h->fd, F_GETFL);
+  if (0 == (flags & O_NONBLOCK))
+    fcntl (h->fd, F_SETFL, flags | O_NONBLOCK);
+  ret = read (h->fd, result, len);
+  if (0 == (flags & O_NONBLOCK))
+    fcntl (h->fd, F_SETFL, flags);
+  return ret;
 #endif
 }
 
@@ -938,6 +950,7 @@ GNUNET_DISK_file_write (const struct GNUNET_DISK_FileHandle * h,
 #endif
 }
 
+
 /**
  * Write a buffer to a file, blocking, if necessary.
  * @param h handle to open file
@@ -991,11 +1004,21 @@ GNUNET_DISK_file_write_blocking (const struct GNUNET_DISK_FileHandle * h,
 #endif
   return bytesWritten;
 #else
-  /* FIXME: switch to blocking mode (fcntl?), write, then switch back? */
-  return write (h->fd, buffer, n);
+  int flags;
+  ssize_t ret;
+
+  /* set to blocking, write, then set back */
+  flags = fcntl (h->fd, F_GETFL);
+  if (0 != (flags & O_NONBLOCK))
+    fcntl (h->fd, F_SETFL, flags - O_NONBLOCK);
+  ret = write (h->fd, buffer, n);
+  if (0 == (flags & O_NONBLOCK))
+    fcntl (h->fd, F_SETFL, flags);
+  return ret;
 #endif
 }
 
+
 /**
  * Write a buffer to a file.  If the file is longer than the
  * number of bytes that will be written, it will be truncated.
@@ -1229,7 +1252,7 @@ GNUNET_DISK_directory_iterator_next (struct GNUNET_DISK_DirectoryIterator *iter,
  * @param dirName the name of the directory
  * @param callback the method to call for each file
  * @param callback_cls closure for callback
- * @return GNUNET_YES if directory is not empty and @callback
+ * @return GNUNET_YES if directory is not empty and 'callback'
  *         will be called later, GNUNET_NO otherwise, GNUNET_SYSERR on error.
  */
 int
@@ -1949,6 +1972,7 @@ GNUNET_DISK_file_sync (const struct GNUNET_DISK_FileHandle *h)
 #endif
 }
 
+
 #if WINDOWS
 /* Copyright Bob Byrnes  <byrnes <at> curl.com>
    http://permalink.gmane.org/gmane.os.cygwin.patches/2121
@@ -2087,30 +2111,22 @@ create_selectable_pipe (PHANDLE read_pipe_ptr, PHANDLE write_pipe_ptr,
 }
 #endif
 
+
 /**
  * Creates an interprocess channel
  *
- * @param blocking creates an asynchronous pipe if set to GNUNET_NO
+ * @param blocking_read creates an asynchronous pipe for reading if set to GNUNET_NO
+ * @param blocking_write creates an asynchronous pipe for writing if set to GNUNET_NO
  * @param inherit_read inherit the parent processes stdin (only for windows)
  * @param inherit_write inherit the parent processes stdout (only for windows)
- *
  * @return handle to the new pipe, NULL on error
  */
 struct GNUNET_DISK_PipeHandle *
 GNUNET_DISK_pipe (int blocking_read, int blocking_write, int inherit_read, int inherit_write)
 {
-  struct GNUNET_DISK_PipeHandle *p;
-  struct GNUNET_DISK_FileHandle *fds;
-
-  p = GNUNET_malloc (sizeof (struct GNUNET_DISK_PipeHandle) +
-                     2 * sizeof (struct GNUNET_DISK_FileHandle));
-  fds = (struct GNUNET_DISK_FileHandle *) &p[1];
-  p->fd[0] = &fds[0];
-  p->fd[1] = &fds[1];
 #ifndef MINGW
   int fd[2];
   int ret;
-  int flags;
   int eno;
 
   ret = pipe (fd);
@@ -2118,50 +2134,32 @@ GNUNET_DISK_pipe (int blocking_read, int blocking_write, int inherit_read, int i
   {
     eno = errno;
     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "pipe");
-    GNUNET_free (p);
-    errno = eno;
-    return NULL;
-  }
-  p->fd[0]->fd = fd[0];
-  p->fd[1]->fd = fd[1];
-  ret = 0;
-  flags = fcntl (fd[0], F_GETFL);
-  if (!blocking_read)
-    flags |= O_NONBLOCK;
-  if (0 > fcntl (fd[0], F_SETFL, flags))
-    ret = -1;
-  flags = fcntl (fd[0], F_GETFD);
-  flags |= FD_CLOEXEC;
-  if (0 > fcntl (fd[0], F_SETFD, flags))
-    ret = -1;
-
-  flags = fcntl (fd[1], F_GETFL);
-  if (!blocking_write)
-    flags |= O_NONBLOCK;
-  if (0 > fcntl (fd[1], F_SETFL, flags))
-    ret = -1;
-  flags = fcntl (fd[1], F_GETFD);
-  flags |= FD_CLOEXEC;
-  if (0 > fcntl (fd[1], F_SETFD, flags))
-    ret = -1;
-  if (ret == -1)
-  {
-    eno = errno;
-    LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fcntl");
-    GNUNET_break (0 == close (p->fd[0]->fd));
-    GNUNET_break (0 == close (p->fd[1]->fd));
-    GNUNET_free (p);
     errno = eno;
     return NULL;
   }
+  return GNUNET_DISK_pipe_from_fd (blocking_read,
+                                  blocking_write,
+                                  fd);
 #else
+  struct GNUNET_DISK_PipeHandle *p;
+  struct GNUNET_DISK_FileHandle *fds;
   BOOL ret;
   HANDLE tmp_handle;
+  
+
+  p = GNUNET_malloc (sizeof (struct GNUNET_DISK_PipeHandle) +
+                     2 * sizeof (struct GNUNET_DISK_FileHandle));
+  fds = (struct GNUNET_DISK_FileHandle *) &p[1];
+  p->fd[0] = &fds[0];
+  p->fd[1] = &fds[1];
 
+  /* All pipes are overlapped. If you want them to block - just
+   * call WriteFile() and ReadFile() with NULL overlapped pointer.
+   */
   ret =
       create_selectable_pipe (&p->fd[0]->h, &p->fd[1]->h, NULL, 0,
-                              blocking_read ? 0 : FILE_FLAG_OVERLAPPED,
-                              blocking_write ? 0 : FILE_FLAG_OVERLAPPED);
+                              FILE_FLAG_OVERLAPPED,
+                              FILE_FLAG_OVERLAPPED);
   if (!ret)
   {
     GNUNET_free (p);
@@ -2208,15 +2206,17 @@ GNUNET_DISK_pipe (int blocking_read, int blocking_write, int inherit_read, int i
   p->fd[1]->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
   p->fd[1]->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
 
-#endif
   return p;
+#endif
 }
 
+
 /**
  * Creates a pipe object from a couple of file descriptors.
  * Useful for wrapping existing pipe FDs.
  *
- * @param blocking creates an asynchronous pipe if set to GNUNET_NO
+ * @param blocking_read creates an asynchronous pipe for reading if set to GNUNET_NO
+ * @param blocking_write creates an asynchronous pipe for writing if set to GNUNET_NO
  * @param fd an array of two fd values. One of them may be -1 for read-only or write-only pipes
  *
  * @return handle to the new pipe, NULL on error
@@ -2242,32 +2242,48 @@ GNUNET_DISK_pipe_from_fd (int blocking_read, int blocking_write, int fd[2])
   ret = 0;
   if (fd[0] >= 0)
   {
-    flags = fcntl (fd[0], F_GETFL);
     if (!blocking_read)
+    {
+      flags = fcntl (fd[0], F_GETFL);
       flags |= O_NONBLOCK;
-    if (0 > fcntl (fd[0], F_SETFL, flags))
-      ret = -1;
+      if (0 > fcntl (fd[0], F_SETFL, flags))
+      {
+       ret = -1;
+       eno = errno;
+      }
+    }
     flags = fcntl (fd[0], F_GETFD);
     flags |= FD_CLOEXEC;
     if (0 > fcntl (fd[0], F_SETFD, flags))
+    {
       ret = -1;
+      eno = errno;
+    }
   }
 
   if (fd[1] >= 0)
   {
-    flags = fcntl (fd[1], F_GETFL);
     if (!blocking_write)
+    {
+      flags = fcntl (fd[1], F_GETFL);
       flags |= O_NONBLOCK;
-    if (0 > fcntl (fd[1], F_SETFL, flags))
-      ret = -1;
+      if (0 > fcntl (fd[1], F_SETFL, flags))
+      {
+       ret = -1;
+       eno = errno;
+      }
+    }
     flags = fcntl (fd[1], F_GETFD);
     flags |= FD_CLOEXEC;
     if (0 > fcntl (fd[1], F_SETFD, flags))
+    {
       ret = -1;
+      eno = errno;
+    }
   }
   if (ret == -1)
   {
-    eno = errno;
+    errno = eno;
     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fcntl");
     if (p->fd[0]->fd >= 0)
       GNUNET_break (0 == close (p->fd[0]->fd));
@@ -2278,8 +2294,6 @@ GNUNET_DISK_pipe_from_fd (int blocking_read, int blocking_write, int fd[2])
     return NULL;
   }
 #else
-  BOOL ret;
-
   if (fd[0] >= 0)
     p->fd[0]->h = _get_osfhandle (fd[0]);
   else
@@ -2380,6 +2394,7 @@ GNUNET_DISK_pipe_close_end (struct GNUNET_DISK_PipeHandle *p,
   return ret;
 }
 
+
 /**
  * Closes an interprocess channel
  *
@@ -2622,6 +2637,7 @@ GNUNET_DISK_npipe_open (const char *fn, enum GNUNET_DISK_OpenFlags flags,
 #endif
 }
 
+
 /**
  * Closes a named pipe/FIFO
  * @param pipe named pipe