From 0aa0feda15b70ddcd717ee1421b2c39ba196e581 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Sat, 19 Jul 2008 23:53:27 +0200 Subject: [PATCH] Libucw: Be able to use public tmp directory. 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 | 3 ++- ucw/fb-temp.c | 72 ++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/ucw/fastbuf.h b/ucw/fastbuf.h index 89294f31..24a36847 100644 --- a/ucw/fastbuf.h +++ b/ucw/fastbuf.h @@ -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 */ diff --git a/ucw/fb-temp.c b/ucw/fb-temp.c index d6546e38..4d924d50 100644 --- a/ucw/fb-temp.c +++ b/ucw/fb-temp.c @@ -15,12 +15,17 @@ #include #include #include +#include +#include +#include -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) { -- 2.39.2