summaryrefslogtreecommitdiff
path: root/tempfile.c
diff options
context:
space:
mode:
authorRené Scharfe <l.s.r@web.de>2022-04-20 20:26:09 (GMT)
committerJunio C Hamano <gitster@pobox.com>2022-04-20 23:17:33 (GMT)
commit2c2db194bd9e2f2dda7f1a47d26a1f86b3dd635a (patch)
tree9502d330ff313ff1c774945203bb10c843deb615 /tempfile.c
parent6cd33dceed60949e2dbc32e3f0f5e67c4c882e1e (diff)
downloadgit-2c2db194bd9e2f2dda7f1a47d26a1f86b3dd635a.zip
git-2c2db194bd9e2f2dda7f1a47d26a1f86b3dd635a.tar.gz
git-2c2db194bd9e2f2dda7f1a47d26a1f86b3dd635a.tar.bz2
tempfile: add mks_tempfile_dt()
Add a function to create a temporary file with a certain name in a temporary directory created using mkdtemp(3). Its result is more sightly than the paths created by mks_tempfile_ts(), which include a random prefix. That's useful for files passed to a program that displays their name, e.g. an external diff tool. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'tempfile.c')
-rw-r--r--tempfile.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/tempfile.c b/tempfile.c
index 94aa18f..2024c82 100644
--- a/tempfile.c
+++ b/tempfile.c
@@ -56,6 +56,20 @@
static VOLATILE_LIST_HEAD(tempfile_list);
+static void remove_template_directory(struct tempfile *tempfile,
+ int in_signal_handler)
+{
+ if (tempfile->directorylen > 0 &&
+ tempfile->directorylen < tempfile->filename.len &&
+ tempfile->filename.buf[tempfile->directorylen] == '/') {
+ strbuf_setlen(&tempfile->filename, tempfile->directorylen);
+ if (in_signal_handler)
+ rmdir(tempfile->filename.buf);
+ else
+ rmdir_or_warn(tempfile->filename.buf);
+ }
+}
+
static void remove_tempfiles(int in_signal_handler)
{
pid_t me = getpid();
@@ -74,6 +88,7 @@ static void remove_tempfiles(int in_signal_handler)
unlink(p->filename.buf);
else
unlink_or_warn(p->filename.buf);
+ remove_template_directory(p, in_signal_handler);
p->active = 0;
}
@@ -100,6 +115,7 @@ static struct tempfile *new_tempfile(void)
tempfile->owner = 0;
INIT_LIST_HEAD(&tempfile->list);
strbuf_init(&tempfile->filename, 0);
+ tempfile->directorylen = 0;
return tempfile;
}
@@ -198,6 +214,52 @@ struct tempfile *mks_tempfile_tsm(const char *filename_template, int suffixlen,
return tempfile;
}
+struct tempfile *mks_tempfile_dt(const char *directory_template,
+ const char *filename)
+{
+ struct tempfile *tempfile;
+ const char *tmpdir;
+ struct strbuf sb = STRBUF_INIT;
+ int fd;
+ size_t directorylen;
+
+ if (!ends_with(directory_template, "XXXXXX")) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ tmpdir = getenv("TMPDIR");
+ if (!tmpdir)
+ tmpdir = "/tmp";
+
+ strbuf_addf(&sb, "%s/%s", tmpdir, directory_template);
+ directorylen = sb.len;
+ if (!mkdtemp(sb.buf)) {
+ int orig_errno = errno;
+ strbuf_release(&sb);
+ errno = orig_errno;
+ return NULL;
+ }
+
+ strbuf_addf(&sb, "/%s", filename);
+ fd = open(sb.buf, O_CREAT | O_EXCL | O_RDWR, 0600);
+ if (fd < 0) {
+ int orig_errno = errno;
+ strbuf_setlen(&sb, directorylen);
+ rmdir(sb.buf);
+ strbuf_release(&sb);
+ errno = orig_errno;
+ return NULL;
+ }
+
+ tempfile = new_tempfile();
+ strbuf_swap(&tempfile->filename, &sb);
+ tempfile->directorylen = directorylen;
+ tempfile->fd = fd;
+ activate_tempfile(tempfile);
+ return tempfile;
+}
+
struct tempfile *xmks_tempfile_m(const char *filename_template, int mode)
{
struct tempfile *tempfile;
@@ -316,6 +378,7 @@ void delete_tempfile(struct tempfile **tempfile_p)
close_tempfile_gently(tempfile);
unlink_or_warn(tempfile->filename.buf);
+ remove_template_directory(tempfile, 0);
deactivate_tempfile(tempfile);
*tempfile_p = NULL;
}