stuff
[oweals/gnunet.git] / src / util / disk.c
index 6512d9945f6e542b876635144a6051789d711e55..e3a58531bd9f6c552f316a90ac7ac360e0ddd58b 100644 (file)
@@ -266,7 +266,10 @@ GNUNET_DISK_file_get_identifiers (const char *filename,
 
 
 /**
- * Create an (empty) temporary file on disk.
+ * Create an (empty) temporary file on disk.  If the given name is not
+ * an absolute path, the current 'TMPDIR' will be prepended.  In any case,
+ * 6 random characters will be appended to the name to create a unique
+ * filename.
  * 
  * @param t component to use for the name;
  *        does NOT contain "XXXXXX" or "/tmp/".
@@ -281,10 +284,17 @@ GNUNET_DISK_mktemp (const char *t)
   char *tmpl;
   char *fn;
 
-  tmpdir = getenv ("TMPDIR");
-  tmpdir = tmpdir ? tmpdir : "/tmp";
-
-  GNUNET_asprintf (&tmpl, "%s/%s%s", tmpdir, t, "XXXXXX");
+  if ( (t[0] != '/') &&
+       (t[0] != '\\') )
+    {
+      tmpdir = getenv ("TMPDIR");
+      tmpdir = tmpdir ? tmpdir : "/tmp";
+      GNUNET_asprintf (&tmpl, "%s/%s%s", tmpdir, t, "XXXXXX");
+    }
+  else
+    {
+      GNUNET_asprintf (&tmpl, "%s%s", t, "XXXXXX");
+    }
 #ifdef MINGW
   fn = (char *) GNUNET_malloc (MAX_PATH + 1);
   if (ERROR_SUCCESS != plibc_conv_to_win_path (tmpl, fn))
@@ -1192,7 +1202,6 @@ GNUNET_DISK_file_open (const char *fn,
   expfn = GNUNET_STRINGS_filename_expand (fn);
   if (NULL == expfn)
     return NULL;
-
 #ifndef MINGW
   mode = 0;
   if (GNUNET_DISK_OPEN_READWRITE == (flags & GNUNET_DISK_OPEN_READWRITE))
@@ -1208,13 +1217,14 @@ GNUNET_DISK_file_open (const char *fn,
       return NULL;
     }
   if (flags & GNUNET_DISK_OPEN_FAILIFEXISTS)
-    oflags |= (O_CREAT & O_EXCL);
+    oflags |= (O_CREAT | O_EXCL);
   if (flags & GNUNET_DISK_OPEN_TRUNCATE)
     oflags |= O_TRUNC;
   if (flags & GNUNET_DISK_OPEN_APPEND)
     oflags |= O_APPEND;
   if (flags & GNUNET_DISK_OPEN_CREATE)
     {
+      (void) GNUNET_DISK_directory_create_for_file (expfn);
       oflags |= O_CREAT;
       if (perm & GNUNET_DISK_PERM_USER_READ)
         mode |= S_IRUSR;
@@ -1239,7 +1249,10 @@ GNUNET_DISK_file_open (const char *fn,
   fd = open (expfn, oflags | O_LARGEFILE, mode);
   if (fd == -1)
     {
-      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "open", expfn);
+      if (0 == (flags & GNUNET_DISK_OPEN_FAILIFEXISTS))
+       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "open", expfn);
+      else
+       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_DEBUG, "open", expfn);
       GNUNET_free (expfn);
       return NULL;
     }
@@ -1271,7 +1284,7 @@ GNUNET_DISK_file_open (const char *fn,
     }
   else
     {
-      disp = OPEN_ALWAYS;
+      disp = OPEN_EXISTING;
     }
 
   /* TODO: access priviledges? */
@@ -1671,6 +1684,65 @@ GNUNET_DISK_pipe (int blocking)
 }
 
 
+/**
+ * Closes an interprocess channel
+ *
+ * @param p pipe to close
+ * @param end which end of the pipe to close
+ * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
+ */
+int
+GNUNET_DISK_pipe_close_end (struct GNUNET_DISK_PipeHandle *p,
+                           enum GNUNET_DISK_PipeEnd end)
+{
+  int ret = GNUNET_OK;
+  int save;
+
+#ifdef MINGW
+  if (end == GNUNET_DISK_PIPE_END_READ)
+    {
+      if (!CloseHandle (p->fd[0]->h))
+        {
+          SetErrnoFromWinError (GetLastError ());
+          ret = GNUNET_SYSERR;
+        }
+      p->fd[0]->h = INVALID_HANDLE_VALUE;
+    }
+  else if (end == GNUNET_DISK_PIPE_END_WRITE)
+    {
+      if (!CloseHandle (p->fd[1]->h))
+        {
+          SetErrnoFromWinError (GetLastError ());
+          ret = GNUNET_SYSERR;
+        }
+      p->fd[1]->h = INVALID_HANDLE_VALUE;
+    }
+  save = errno;
+#else
+  save = 0;
+  if (end == GNUNET_DISK_PIPE_END_READ)
+    {
+      if (0 != close (p->fd[0]->fd))
+        {
+          ret = GNUNET_SYSERR;
+          save = errno;
+        }
+      p->fd[0]->fd = -1;
+    }
+  else if (end == GNUNET_DISK_PIPE_END_WRITE)
+    {
+      if (0 != close (p->fd[1]->fd))
+        {
+          ret = GNUNET_SYSERR;
+          save = errno;
+        }
+      p->fd[1]->fd = -1;
+    }
+#endif
+  errno = save;
+  return ret;
+}
+
 /**
  * Closes an interprocess channel
  *
@@ -1697,15 +1769,22 @@ GNUNET_DISK_pipe_close (struct GNUNET_DISK_PipeHandle *p)
   save = errno;
 #else
   save = 0;
-  if (0 != close (p->fd[0]->fd))
+  if (p->fd[0]->fd != -1)
     {
-      ret = GNUNET_SYSERR;
-      save = errno;
+      if (0 != close (p->fd[0]->fd))
+        {
+          ret = GNUNET_SYSERR;
+          save = errno;
+        }
     }
-  if (0 != close (p->fd[1]->fd))
+
+  if (p->fd[1]->fd != -1)
     {
-      ret = GNUNET_SYSERR;
-      save = errno;
+      if (0 != close (p->fd[1]->fd))
+        {
+          ret = GNUNET_SYSERR;
+          save = errno;
+        }
     }
 #endif
   GNUNET_free (p);
@@ -1716,8 +1795,10 @@ GNUNET_DISK_pipe_close (struct GNUNET_DISK_PipeHandle *p)
 
 /**
  * Get the handle to a particular pipe end
+ *
  * @param p pipe
  * @param n end to access
+ * @return handle for the respective end
  */
 const struct GNUNET_DISK_FileHandle *
 GNUNET_DISK_pipe_handle (const struct GNUNET_DISK_PipeHandle *p,