Skip to content

Commit 01e4994

Browse files
pks-tgitster
authored andcommitted
reftable/system: provide thin wrapper for tempfile subsystem
We use the tempfile subsystem to write temporary tables, but given that we're in the process of converting the reftable library to become standalone we cannot use this subsystem directly anymore. While we could in theory convert the code to use mkstemp(3p) instead, we'd lose access to our infrastructure that automatically prunes tempfiles via atexit(3p) or signal handlers. Provide a thin wrapper for the tempfile subsystem instead. Like this, the compatibility shim is fully self-contained in "reftable/system.c". Downstream users of the reftable library would have to implement their own tempfile shims by replacing "system.c" with a custom version. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 86b770b commit 01e4994

File tree

4 files changed

+114
-35
lines changed

4 files changed

+114
-35
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2722,6 +2722,7 @@ REFTABLE_OBJS += reftable/pq.o
27222722
REFTABLE_OBJS += reftable/reader.o
27232723
REFTABLE_OBJS += reftable/record.o
27242724
REFTABLE_OBJS += reftable/stack.o
2725+
REFTABLE_OBJS += reftable/system.o
27252726
REFTABLE_OBJS += reftable/tree.o
27262727
REFTABLE_OBJS += reftable/writer.o
27272728

reftable/stack.c

Lines changed: 23 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ license that can be found in the LICENSE file or at
1616
#include "reftable-record.h"
1717
#include "reftable-merged.h"
1818
#include "writer.h"
19-
#include "tempfile.h"
2019

2120
static int stack_try_add(struct reftable_stack *st,
2221
int (*write_table)(struct reftable_writer *wr,
@@ -867,7 +866,7 @@ int reftable_addition_add(struct reftable_addition *add,
867866
struct reftable_buf tab_file_name = REFTABLE_BUF_INIT;
868867
struct reftable_buf next_name = REFTABLE_BUF_INIT;
869868
struct reftable_writer *wr = NULL;
870-
struct tempfile *tab_file = NULL;
869+
struct reftable_tmpfile tab_file = REFTABLE_TMPFILE_INIT;
871870
struct fd_writer writer = {
872871
.opts = &add->stack->opts,
873872
};
@@ -887,20 +886,18 @@ int reftable_addition_add(struct reftable_addition *add,
887886
if (err < 0)
888887
goto done;
889888

890-
tab_file = mks_tempfile(temp_tab_file_name.buf);
891-
if (!tab_file) {
892-
err = REFTABLE_IO_ERROR;
889+
err = tmpfile_from_pattern(&tab_file, temp_tab_file_name.buf);
890+
if (err < 0)
893891
goto done;
894-
}
895892
if (add->stack->opts.default_permissions) {
896-
if (chmod(get_tempfile_path(tab_file),
893+
if (chmod(tab_file.path,
897894
add->stack->opts.default_permissions)) {
898895
err = REFTABLE_IO_ERROR;
899896
goto done;
900897
}
901898
}
902899

903-
writer.fd = get_tempfile_fd(tab_file);
900+
writer.fd = tab_file.fd;
904901
err = reftable_writer_new(&wr, fd_writer_write, fd_writer_flush,
905902
&writer, &add->stack->opts);
906903
if (err < 0)
@@ -918,11 +915,9 @@ int reftable_addition_add(struct reftable_addition *add,
918915
if (err < 0)
919916
goto done;
920917

921-
err = close_tempfile_gently(tab_file);
922-
if (err < 0) {
923-
err = REFTABLE_IO_ERROR;
918+
err = tmpfile_close(&tab_file);
919+
if (err < 0)
924920
goto done;
925-
}
926921

927922
if (wr->min_update_index < add->next_update_index) {
928923
err = REFTABLE_API_ERROR;
@@ -945,11 +940,9 @@ int reftable_addition_add(struct reftable_addition *add,
945940
On windows, this relies on rand() picking a unique destination name.
946941
Maybe we should do retry loop as well?
947942
*/
948-
err = rename_tempfile(&tab_file, tab_file_name.buf);
949-
if (err < 0) {
950-
err = REFTABLE_IO_ERROR;
943+
err = tmpfile_rename(&tab_file, tab_file_name.buf);
944+
if (err < 0)
951945
goto done;
952-
}
953946

954947
REFTABLE_ALLOC_GROW(add->new_tables, add->new_tables_len + 1,
955948
add->new_tables_cap);
@@ -960,7 +953,7 @@ int reftable_addition_add(struct reftable_addition *add,
960953
add->new_tables[add->new_tables_len++] = reftable_buf_detach(&next_name);
961954

962955
done:
963-
delete_tempfile(&tab_file);
956+
tmpfile_delete(&tab_file);
964957
reftable_buf_release(&temp_tab_file_name);
965958
reftable_buf_release(&tab_file_name);
966959
reftable_buf_release(&next_name);
@@ -980,15 +973,15 @@ uint64_t reftable_stack_next_update_index(struct reftable_stack *st)
980973
static int stack_compact_locked(struct reftable_stack *st,
981974
size_t first, size_t last,
982975
struct reftable_log_expiry_config *config,
983-
struct tempfile **tab_file_out)
976+
struct reftable_tmpfile *tab_file_out)
984977
{
985978
struct reftable_buf next_name = REFTABLE_BUF_INIT;
986979
struct reftable_buf tab_file_path = REFTABLE_BUF_INIT;
987980
struct reftable_writer *wr = NULL;
988981
struct fd_writer writer= {
989982
.opts = &st->opts,
990983
};
991-
struct tempfile *tab_file;
984+
struct reftable_tmpfile tab_file = REFTABLE_TMPFILE_INIT;
992985
int err = 0;
993986

994987
err = format_name(&next_name, reftable_reader_min_update_index(st->readers[first]),
@@ -1004,19 +997,17 @@ static int stack_compact_locked(struct reftable_stack *st,
1004997
if (err < 0)
1005998
goto done;
1006999

1007-
tab_file = mks_tempfile(tab_file_path.buf);
1008-
if (!tab_file) {
1009-
err = REFTABLE_IO_ERROR;
1000+
err = tmpfile_from_pattern(&tab_file, tab_file_path.buf);
1001+
if (err < 0)
10101002
goto done;
1011-
}
10121003

10131004
if (st->opts.default_permissions &&
1014-
chmod(get_tempfile_path(tab_file), st->opts.default_permissions) < 0) {
1005+
chmod(tab_file.path, st->opts.default_permissions) < 0) {
10151006
err = REFTABLE_IO_ERROR;
10161007
goto done;
10171008
}
10181009

1019-
writer.fd = get_tempfile_fd(tab_file);
1010+
writer.fd = tab_file.fd;
10201011
err = reftable_writer_new(&wr, fd_writer_write, fd_writer_flush,
10211012
&writer, &st->opts);
10221013
if (err < 0)
@@ -1030,15 +1021,15 @@ static int stack_compact_locked(struct reftable_stack *st,
10301021
if (err < 0)
10311022
goto done;
10321023

1033-
err = close_tempfile_gently(tab_file);
1024+
err = tmpfile_close(&tab_file);
10341025
if (err < 0)
10351026
goto done;
10361027

10371028
*tab_file_out = tab_file;
1038-
tab_file = NULL;
1029+
tab_file = REFTABLE_TMPFILE_INIT;
10391030

10401031
done:
1041-
delete_tempfile(&tab_file);
1032+
tmpfile_delete(&tab_file);
10421033
reftable_writer_free(wr);
10431034
reftable_buf_release(&next_name);
10441035
reftable_buf_release(&tab_file_path);
@@ -1171,7 +1162,7 @@ static int stack_compact_range(struct reftable_stack *st,
11711162
struct reftable_buf table_name = REFTABLE_BUF_INIT;
11721163
struct lock_file tables_list_lock = LOCK_INIT;
11731164
struct lock_file *table_locks = NULL;
1174-
struct tempfile *new_table = NULL;
1165+
struct reftable_tmpfile new_table = REFTABLE_TMPFILE_INIT;
11751166
int is_empty_table = 0, err = 0;
11761167
size_t first_to_replace, last_to_replace;
11771168
size_t i, nlocks = 0;
@@ -1439,11 +1430,9 @@ static int stack_compact_range(struct reftable_stack *st,
14391430
if (err < 0)
14401431
goto done;
14411432

1442-
err = rename_tempfile(&new_table, new_table_path.buf);
1443-
if (err < 0) {
1444-
err = REFTABLE_IO_ERROR;
1433+
err = tmpfile_rename(&new_table, new_table_path.buf);
1434+
if (err < 0)
14451435
goto done;
1446-
}
14471436
}
14481437

14491438
/*
@@ -1515,7 +1504,7 @@ static int stack_compact_range(struct reftable_stack *st,
15151504
rollback_lock_file(&table_locks[i]);
15161505
reftable_free(table_locks);
15171506

1518-
delete_tempfile(&new_table);
1507+
tmpfile_delete(&new_table);
15191508
reftable_buf_release(&new_table_name);
15201509
reftable_buf_release(&new_table_path);
15211510
reftable_buf_release(&tables_list_buf);

reftable/system.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#include "system.h"
2+
#include "basics.h"
3+
#include "reftable-error.h"
4+
#include "../tempfile.h"
5+
6+
int tmpfile_from_pattern(struct reftable_tmpfile *out, const char *pattern)
7+
{
8+
struct tempfile *tempfile;
9+
10+
tempfile = mks_tempfile(pattern);
11+
if (!tempfile)
12+
return REFTABLE_IO_ERROR;
13+
14+
out->path = tempfile->filename.buf;
15+
out->fd = tempfile->fd;
16+
out->priv = tempfile;
17+
18+
return 0;
19+
}
20+
21+
int tmpfile_close(struct reftable_tmpfile *t)
22+
{
23+
struct tempfile *tempfile = t->priv;
24+
int ret = close_tempfile_gently(tempfile);
25+
t->fd = -1;
26+
if (ret < 0)
27+
return REFTABLE_IO_ERROR;
28+
return 0;
29+
}
30+
31+
int tmpfile_delete(struct reftable_tmpfile *t)
32+
{
33+
struct tempfile *tempfile = t->priv;
34+
int ret = delete_tempfile(&tempfile);
35+
*t = REFTABLE_TMPFILE_INIT;
36+
if (ret < 0)
37+
return REFTABLE_IO_ERROR;
38+
return 0;
39+
}
40+
41+
int tmpfile_rename(struct reftable_tmpfile *t, const char *path)
42+
{
43+
struct tempfile *tempfile = t->priv;
44+
int ret = rename_tempfile(&tempfile, path);
45+
*t = REFTABLE_TMPFILE_INIT;
46+
if (ret < 0)
47+
return REFTABLE_IO_ERROR;
48+
return 0;
49+
}

reftable/system.h

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,46 @@ license that can be found in the LICENSE file or at
1313

1414
#include "git-compat-util.h"
1515
#include "lockfile.h"
16-
#include "tempfile.h"
16+
17+
/*
18+
* An implementation-specific temporary file. By making this specific to the
19+
* implementation it becomes possible to tie temporary files into any kind of
20+
* signal or atexit handlers for cleanup on abnormal situations.
21+
*/
22+
struct reftable_tmpfile {
23+
const char *path;
24+
int fd;
25+
void *priv;
26+
};
27+
#define REFTABLE_TMPFILE_INIT ((struct reftable_tmpfile) { .fd = -1, })
28+
29+
/*
30+
* Create a temporary file from a pattern similar to how mkstemp(3p) would.
31+
* The `pattern` shall not be modified. On success, the structure at `out` has
32+
* been initialized such that it is ready for use. Returns 0 on success, a
33+
* reftable error code on error.
34+
*/
35+
int tmpfile_from_pattern(struct reftable_tmpfile *out, const char *pattern);
36+
37+
/*
38+
* Close the temporary file's file descriptor without removing the file itself.
39+
* This is a no-op in case the file has already been closed beforehand. Returns
40+
* 0 on success, a reftable error code on error.
41+
*/
42+
int tmpfile_close(struct reftable_tmpfile *t);
43+
44+
/*
45+
* Close the temporary file and delete it. This is a no-op in case the file has
46+
* already been deleted or renamed beforehand. Returns 0 on success, a reftable
47+
* error code on error.
48+
*/
49+
int tmpfile_delete(struct reftable_tmpfile *t);
50+
51+
/*
52+
* Rename the temporary file to the provided path. The temporary file must be
53+
* active. Return 0 on success, a reftable error code on error. Deactivates the
54+
* temporary file.
55+
*/
56+
int tmpfile_rename(struct reftable_tmpfile *t, const char *path);
1757

1858
#endif

0 commit comments

Comments
 (0)