]> mj.ucw.cz Git - libucw.git/commitdiff
Libucw: Be able to use public tmp directory.
authorMartin Mares <mj@ucw.cz>
Sat, 19 Jul 2008 21:53:27 +0000 (23:53 +0200)
committerMartin Mares <mj@ucw.cz>
Sat, 19 Jul 2008 21:53:27 +0000 (23:53 +0200)
If Tempfiles.Prefix is not set, temp_file_name() now uses the public tmp directory
pointed to by $TMPDIR. The new Tempfiles.PublicDir switch controls the naming

Added open_tmp() which creates a temporary file in a race-free way.

The changes were picked from Michal's dev-vorner branch, mine are only renames
of function parameters and coding-style cleanups, and also the doc.

ucw/fastbuf.h
ucw/fb-temp.c

index 89294f31f02aa009fcc160337a0c7153134baee7..24a368475bbe1ad58216cc57852ecae5ca119ff2 100644 (file)
@@ -115,8 +115,9 @@ void bfilesync(struct fastbuf *b);
 /* Temporary files */
 
 #define TEMP_FILE_NAME_LEN 256
-void temp_file_name(char *name);
+void temp_file_name(char *name_buf, int *open_flags);
 void bfix_tmp_file(struct fastbuf *fb, const char *name);
+int open_tmp(char *name_buf, int open_flags, int mode);
 
 /* Internal functions of some file back-ends */
 
index d6546e38e3879150b39c94fa43da30b2ea9e2070..4d924d504928fc10b0a9c3d83947f8c3349dca6d 100644 (file)
 #include <stdio.h>
 #include <unistd.h>
 #include <sys/fcntl.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <errno.h>
 
-static char *temp_prefix = "/tmp/temp";
+static char *temp_prefix;
+static int public_dir = 1;
 
 static struct cf_section temp_config = {
   CF_ITEMS {
     CF_STRING("Prefix", &temp_prefix),
+    CF_INT("PublicDir", &public_dir),
     CF_END
   }
 };
@@ -31,27 +36,74 @@ static void CONSTRUCTOR temp_global_init(void)
 }
 
 void
-temp_file_name(char *buf)
+temp_file_name(char *name_buf, int *open_flags)
 {
-  struct ucwlib_context *ctx = ucwlib_thread_context();
-  int cnt = ++ctx->temp_counter;
-  int pid = getpid();
-  if (ctx->thread_id == pid)
-    sprintf(buf, "%s%d-%d", temp_prefix, pid, cnt);
+  char *prefix;
+  int free_prefix = 0;
+  if (temp_prefix)
+    prefix = temp_prefix;
   else
-    sprintf(buf, "%s%d-%d-%d", temp_prefix, pid, ctx->thread_id, cnt);
+    {
+      char *env = getenv("TMPDIR");
+      if (env)
+        {
+          prefix = xmalloc(strlen(env) + 6);
+          sprintf(prefix, "%s/temp", env);
+          free_prefix = 1;
+        }
+      else
+        prefix = "/tmp/temp";
+    }
+  if (public_dir)
+    {
+      struct timeval tv;
+      if (gettimeofday(&tv, NULL))
+        die("Could not generate temp file name: %m");
+      sprintf(name_buf, "%s-%u", prefix, (uns) tv.tv_usec);
+      if (open_flags)
+        *open_flags = O_EXCL;
+    }
+  else
+    {
+      struct ucwlib_context *ctx = ucwlib_thread_context();
+      int cnt = ++ctx->temp_counter;
+      int pid = getpid();
+      if (ctx->thread_id == pid)
+        sprintf(name_buf, "%s%d-%d", temp_prefix, pid, cnt);
+      else
+        sprintf(name_buf, "%s%d-%d-%d", temp_prefix, pid, ctx->thread_id, cnt);
+      if (open_flags)
+        *open_flags = 0;
+    }
+  if (free_prefix)
+    xfree(prefix);
 }
 
 struct fastbuf *
 bopen_tmp_file(struct fb_params *params)
 {
   char name[TEMP_FILE_NAME_LEN];
-  temp_file_name(name);
-  struct fastbuf *fb = bopen_file(name, O_RDWR | O_CREAT | O_TRUNC, params);
+  int fd = open_tmp(name, O_RDWR | O_CREAT | O_TRUNC, 0600);
+  struct fastbuf *fb = bopen_fd_name(fd, params, name);
   bconfig(fb, BCONFIG_IS_TEMP_FILE, 1);
   return fb;
 }
 
+int
+open_tmp(char *name_buf, int open_flags, int mode)
+{
+  int create_flags, fd, retry = 10;
+  do
+    {
+      temp_file_name(name_buf, &create_flags);
+      fd = open(name_buf, open_flags | create_flags, mode);
+    }
+  while (fd < 0 && errno == EEXIST && retry --);
+  if (fd < 0)
+    die("Unable to create temp file %s: %m", name_buf);
+  return fd;
+}
+
 struct fastbuf *
 bopen_tmp(uns buflen)
 {