- fix 2699
[oweals/gnunet.git] / src / util / disk.c
index 01a3cc214928a12095ed5ad1da99ac381b40138d..f06311f88648561a4cb5e58b862c217e857a71c8 100644 (file)
@@ -1819,86 +1819,153 @@ GNUNET_DISK_file_open (const char *fn, enum GNUNET_DISK_OpenFlags flags,
 int
 GNUNET_DISK_file_close (struct GNUNET_DISK_FileHandle *h)
 {
+  int ret;
   if (h == NULL)
   {
     errno = EINVAL;
     return GNUNET_SYSERR;
   }
 
+  ret = GNUNET_OK;
+
 #if MINGW
   if (!CloseHandle (h->h))
   {
     SetErrnoFromWinError (GetLastError ());
     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "close");
+    ret = GNUNET_SYSERR;
+  }
+  if (h->oOverlapRead)
+  {
+    if (!CloseHandle (h->oOverlapRead->hEvent))
+    {
+      SetErrnoFromWinError (GetLastError ());
+      LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "close");
+      ret = GNUNET_SYSERR;
+    }
     GNUNET_free (h->oOverlapRead);
+  }
+  if (h->oOverlapWrite)
+  {
+    if (!CloseHandle (h->oOverlapWrite->hEvent))
+    {
+      SetErrnoFromWinError (GetLastError ());
+      LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "close");
+      ret = GNUNET_SYSERR;
+    }
     GNUNET_free (h->oOverlapWrite);
-    GNUNET_free (h);
-    return GNUNET_SYSERR;
   }
 #else
   if (close (h->fd) != 0)
   {
     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "close");
-    GNUNET_free (h);
-    return GNUNET_SYSERR;
+    ret = GNUNET_SYSERR;
   }
 #endif
   GNUNET_free (h);
-  return GNUNET_OK;
+  return ret;
 }
 
-
+#ifdef WINDOWS
 /**
- * Get a handle from a native FD.
+ * Get a GNUnet file handle from a W32 handle.
  *
- * @param fd native file descriptor
- * @return file handle corresponding to the descriptor
+ * @param handle native handle
+ * @return GNUnet file handle corresponding to the W32 handle
  */
 struct GNUNET_DISK_FileHandle *
-GNUNET_DISK_get_handle_from_native (FILE *fd)
+GNUNET_DISK_get_handle_from_w32_handle (HANDLE osfh)
 {
   struct GNUNET_DISK_FileHandle *fh;
-  int fno;
-#if MINGW
-  intptr_t osfh;
-#endif
 
-  fno = fileno (fd);
-  if (-1 == fno)
-    return NULL;
+  DWORD dwret;
+  enum GNUNET_FILE_Type ftype;
 
-#if MINGW
-  osfh = _get_osfhandle (fno);
-  if (INVALID_HANDLE_VALUE == (HANDLE) osfh)
+  dwret = GetFileType (osfh);
+  switch (dwret)
+  {
+  case FILE_TYPE_DISK:
+    ftype = GNUNET_DISK_HANLDE_TYPE_FILE;
+    break;
+  case FILE_TYPE_PIPE:
+    ftype = GNUNET_DISK_HANLDE_TYPE_PIPE;
+    break;
+  default:
     return NULL;
+  }
+
+  fh = GNUNET_malloc (sizeof (struct GNUNET_DISK_FileHandle));
+
+  fh->h = osfh;
+  fh->type = ftype;
+  if (ftype == GNUNET_DISK_HANLDE_TYPE_PIPE)
+  {
+    /**
+     * Note that we can't make it overlapped if it isn't already.
+     * (ReOpenFile() is only available in 2003/Vista).
+     * The process that opened this file in the first place (usually a parent
+     * process, if this is stdin/stdout/stderr) must make it overlapped,
+     * otherwise we're screwed, as selecting on non-overlapped handle
+     * will block.
+     */
+    fh->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED));
+    fh->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED));
+    fh->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
+    fh->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
+  }
+
+  return fh;
+}
 #endif
 
+/**
+ * Get a handle from a native integer FD.
+ *
+ * @param fd native integer file descriptor
+ * @return file handle corresponding to the descriptor
+ */
+struct GNUNET_DISK_FileHandle *
+GNUNET_DISK_get_handle_from_int_fd (int fno)
+{
+  struct GNUNET_DISK_FileHandle *fh;
+
+#ifndef WINDOWS
   fh = GNUNET_malloc (sizeof (struct GNUNET_DISK_FileHandle));
 
-#if MINGW
-  fh->h = (HANDLE) osfh;
-  /* Assume it to be a pipe. TODO: use some kind of detection
-   * function to figure out handle type.
-   * Note that we can't make it overlapped if it isn't already.
-   * (ReOpenFile() is only available in 2003/Vista).
-   * The process that opened this file in the first place (usually a parent
-   * process, if this is stdin/stdout/stderr) must make it overlapped,
-   * otherwise we're screwed, as selecting on non-overlapped handle
-   * will block.
-   */
-  fh->type = GNUNET_DISK_HANLDE_TYPE_PIPE;
-  fh->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED));
-  fh->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED));
-  fh->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
-  fh->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
-#else
   fh->fd = fno;
+#else
+  intptr_t osfh;
+
+  osfh = _get_osfhandle (fno);
+  if (INVALID_HANDLE_VALUE == (HANDLE) osfh)
+    return NULL;
+
+  fh = GNUNET_DISK_get_handle_from_w32_handle ((HANDLE) osfh);
 #endif
 
   return fh;
 }
 
 
+/**
+ * Get a handle from a native streaming FD.
+ *
+ * @param fd native streaming file descriptor
+ * @return file handle corresponding to the descriptor
+ */
+struct GNUNET_DISK_FileHandle *
+GNUNET_DISK_get_handle_from_native (FILE *fd)
+{
+  int fno;
+
+  fno = fileno (fd);
+  if (-1 == fno)
+    return NULL;
+
+  return GNUNET_DISK_get_handle_from_int_fd (fno);
+}
+
+
 /**
  * Construct full path to a file inside of the private
  * directory used by GNUnet.  Also creates the corresponding
@@ -2191,9 +2258,8 @@ create_selectable_pipe (PHANDLE read_pipe_ptr, PHANDLE write_pipe_ptr,
      * a waste, since only a single direction is actually used.
      * It's important to only allow a single instance, to ensure that
      * the pipe was not created earlier by some other process, even if
-     * the pid has been reused.  We avoid FILE_FLAG_FIRST_PIPE_INSTANCE
-     * because that is only available for Win2k SP2 and WinXP.  */
-    read_pipe = CreateNamedPipeA (pipename, PIPE_ACCESS_INBOUND | dwReadMode, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1,   /* max instances */
+     * the pid has been reused.  */
+    read_pipe = CreateNamedPipeA (pipename, PIPE_ACCESS_INBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE | dwReadMode, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1,   /* max instances */
                                   psize,        /* output buffer size */
                                   psize,        /* input buffer size */
                                   NMPWAIT_USE_DEFAULT_WAIT, sa_ptr);