diff options
author | Jeff King <peff@peff.net> | 2024-09-06 05:48:41 +0200 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2024-09-06 17:02:26 +0200 |
commit | a71c47825d2650cfe53217d860107d9457cc375c (patch) | |
tree | efb257de871e79047155e87943210725e2c89fa3 | |
parent | sparse-checkout: check commit_lock_file when writing patterns (diff) | |
download | git-a71c47825d2650cfe53217d860107d9457cc375c.tar.xz git-a71c47825d2650cfe53217d860107d9457cc375c.zip |
sparse-checkout: use fdopen_lock_file() instead of xfdopen()
When updating sparse patterns, we open a lock_file to write out the new
data. The lock_file struct holds the file descriptor, but we call
fdopen() to get a stdio handle to do the actual write.
After we finish writing, we fflush() so that all of the data is on disk,
and then call commit_lock_file() which closes the descriptor. But we
never fclose() the stdio handle, leaking it.
The obvious solution seems like it would be to just call fclose(). But
when? If we do it before commit_lock_file(), then the lock_file code is
left thinking it owns the now-closed file descriptor, and will do an
extra close() on the descriptor. But if we do it before, we have the
opposite problem: the lock_file code will close the descriptor, and
fclose() will do the extra close().
We can handle this correctly by using fdopen_lock_file(). That leaves
ownership of the stdio handle with the lock_file, which knows not to
double-close it.
We do have to adjust the code a bit:
- we have to handle errors ourselves; we can just die(), since that's
what xfdopen() would have done (and we can even provide a more
specific error message).
- we no longer need to call fflush(); committing the lock-file
auto-closes it, which will now do the flush for us. As a bonus, this
will actually check that the flush was successful before renaming
the file into place.
- we can get rid of the local "fd" variable, since we never look at it
ourselves now
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r-- | builtin/sparse-checkout.c | 9 |
1 files changed, 4 insertions, 5 deletions
diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c index b5e220cc44..5ccf696862 100644 --- a/builtin/sparse-checkout.c +++ b/builtin/sparse-checkout.c @@ -327,7 +327,6 @@ static int write_patterns_and_update(struct pattern_list *pl) { char *sparse_filename; FILE *fp; - int fd; struct lock_file lk = LOCK_INIT; int result; @@ -336,8 +335,7 @@ static int write_patterns_and_update(struct pattern_list *pl) if (safe_create_leading_directories(sparse_filename)) die(_("failed to create directory for sparse-checkout file")); - fd = hold_lock_file_for_update(&lk, sparse_filename, - LOCK_DIE_ON_ERROR); + hold_lock_file_for_update(&lk, sparse_filename, LOCK_DIE_ON_ERROR); result = update_working_directory(pl); if (result) { @@ -346,14 +344,15 @@ static int write_patterns_and_update(struct pattern_list *pl) goto out; } - fp = xfdopen(fd, "w"); + fp = fdopen_lock_file(&lk, "w"); + if (!fp) + die_errno(_("unable to fdopen %s"), get_lock_file_path(&lk)); if (core_sparse_checkout_cone) write_cone_to_file(fp, pl); else write_patterns_to_file(fp, pl); - fflush(fp); if (commit_lock_file(&lk)) die_errno(_("unable to write %s"), sparse_filename); |