git/csum-file.h
Junio C Hamano c3d034df16 csum-file: introduce discard_hashfile()
The hashfile API is used to write out a "hashfile", which has a
final checksum (typically SHA-1) at the end.  An in-core hashfile
structure has up to two file descriptors and a few buffers that can
only be freed by calling a helper function that is private to the
csum-file implementation.

The usual flow of a user of the API is to first open a file
descriptor for writing, obtain a hashfile associated with that write
file descriptor by calling either hashfd() or hashfd_check(), call
hashwrite() number of times to write data to the file, and then call
finalize_hashfile(), which appends th checksum to the end of the
file, closes file descriptors and releases associated buffers.

But what if a caller finds some error after calling hashfd() to
start the process and/or hashwrite() to send some data to the file,
and wants to abort the operation?  The underlying file descriptor is
often managed by the tempfile API, so aborting will clean the file
out of the filesystem, but the resources associated with the in-core
hashfile structure is lost.

Introduce discard_hashfile() API function to allow them to release
the resources held by a hashfile structure the callers want to
dispose of, and use that in read-cache.c:do_write_index(), which is
a central place that writes the index file.

Mark t2107 as leak-free, as this leak in "update-index --cacheinfo"
test that deliberately makes it fail is now plugged.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-07-26 09:04:02 -07:00

87 lines
2.1 KiB
C

#ifndef CSUM_FILE_H
#define CSUM_FILE_H
#include "hash.h"
#include "write-or-die.h"
struct progress;
/* A SHA1-protected file */
struct hashfile {
int fd;
int check_fd;
unsigned int offset;
git_hash_ctx ctx;
off_t total;
struct progress *tp;
const char *name;
int do_crc;
uint32_t crc32;
size_t buffer_len;
unsigned char *buffer;
unsigned char *check_buffer;
/**
* If non-zero, skip_hash indicates that we should
* not actually compute the hash for this hashfile and
* instead only use it as a buffered write.
*/
int skip_hash;
};
/* Checkpoint */
struct hashfile_checkpoint {
off_t offset;
git_hash_ctx ctx;
};
void hashfile_checkpoint(struct hashfile *, struct hashfile_checkpoint *);
int hashfile_truncate(struct hashfile *, struct hashfile_checkpoint *);
/* finalize_hashfile flags */
#define CSUM_CLOSE 1
#define CSUM_FSYNC 2
#define CSUM_HASH_IN_STREAM 4
struct hashfile *hashfd(int fd, const char *name);
struct hashfile *hashfd_check(const char *name);
struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp);
int finalize_hashfile(struct hashfile *, unsigned char *, enum fsync_component, unsigned int);
void discard_hashfile(struct hashfile *);
void hashwrite(struct hashfile *, const void *, unsigned int);
void hashflush(struct hashfile *f);
void crc32_begin(struct hashfile *);
uint32_t crc32_end(struct hashfile *);
/* Verify checksum validity while reading. Returns non-zero on success. */
int hashfile_checksum_valid(const unsigned char *data, size_t len);
/*
* Returns the total number of bytes fed to the hashfile so far (including ones
* that have not been written out to the descriptor yet).
*/
static inline off_t hashfile_total(struct hashfile *f)
{
return f->total + f->offset;
}
static inline void hashwrite_u8(struct hashfile *f, uint8_t data)
{
hashwrite(f, &data, sizeof(data));
}
static inline void hashwrite_be32(struct hashfile *f, uint32_t data)
{
data = htonl(data);
hashwrite(f, &data, sizeof(data));
}
static inline size_t hashwrite_be64(struct hashfile *f, uint64_t data)
{
data = htonll(data);
hashwrite(f, &data, sizeof(data));
return sizeof(data);
}
#endif