mirror of
https://github.com/git/git.git
synced 2024-11-23 01:46:13 +08:00
Merge branch 'tb/weak-sha1-for-tail-sum'
The checksum at the tail of files are now computed without collision detection protection. This is safe as the consumer of the information to protect itself from replay attacks checks for hash collisions independently. * tb/weak-sha1-for-tail-sum: csum-file.c: use unsafe SHA-1 implementation when available Makefile: allow specifying a SHA-1 for non-cryptographic uses hash.h: scaffolding for _unsafe hashing variants sha1: do not redefine `platform_SHA_CTX` and friends pack-objects: use finalize_object_file() to rename pack/idx/etc finalize_object_file(): implement collision check finalize_object_file(): refactor unlink_or_warn() placement finalize_object_file(): check for name collision before renaming
This commit is contained in:
commit
ead0a050e2
25
Makefile
25
Makefile
@ -521,6 +521,10 @@ include shared.mak
|
||||
# Define APPLE_COMMON_CRYPTO_SHA1 to use Apple's CommonCrypto for
|
||||
# SHA-1.
|
||||
#
|
||||
# Define the same Makefile knobs as above, but suffixed with _UNSAFE to
|
||||
# use the corresponding implementations for unsafe SHA-1 hashing for
|
||||
# non-cryptographic purposes.
|
||||
#
|
||||
# If don't enable any of the *_SHA1 settings in this section, Git will
|
||||
# default to its built-in sha1collisiondetection library, which is a
|
||||
# collision-detecting sha1 This is slower, but may detect attempted
|
||||
@ -1997,6 +2001,27 @@ endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef OPENSSL_SHA1_UNSAFE
|
||||
ifndef OPENSSL_SHA1
|
||||
EXTLIBS += $(LIB_4_CRYPTO)
|
||||
BASIC_CFLAGS += -DSHA1_OPENSSL_UNSAFE
|
||||
endif
|
||||
else
|
||||
ifdef BLK_SHA1_UNSAFE
|
||||
ifndef BLK_SHA1
|
||||
LIB_OBJS += block-sha1/sha1.o
|
||||
BASIC_CFLAGS += -DSHA1_BLK_UNSAFE
|
||||
endif
|
||||
else
|
||||
ifdef APPLE_COMMON_CRYPTO_SHA1_UNSAFE
|
||||
ifndef APPLE_COMMON_CRYPTO_SHA1
|
||||
COMPAT_CFLAGS += -DCOMMON_DIGEST_FOR_OPENSSL
|
||||
BASIC_CFLAGS += -DSHA1_APPLE_UNSAFE
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef OPENSSL_SHA256
|
||||
EXTLIBS += $(LIB_4_CRYPTO)
|
||||
BASIC_CFLAGS += -DSHA256_OPENSSL
|
||||
|
@ -16,7 +16,9 @@ void blk_SHA1_Init(blk_SHA_CTX *ctx);
|
||||
void blk_SHA1_Update(blk_SHA_CTX *ctx, const void *dataIn, size_t len);
|
||||
void blk_SHA1_Final(unsigned char hashout[20], blk_SHA_CTX *ctx);
|
||||
|
||||
#ifndef platform_SHA_CTX
|
||||
#define platform_SHA_CTX blk_SHA_CTX
|
||||
#define platform_SHA1_Init blk_SHA1_Init
|
||||
#define platform_SHA1_Update blk_SHA1_Update
|
||||
#define platform_SHA1_Final blk_SHA1_Final
|
||||
#endif
|
||||
|
18
csum-file.c
18
csum-file.c
@ -50,7 +50,7 @@ void hashflush(struct hashfile *f)
|
||||
|
||||
if (offset) {
|
||||
if (!f->skip_hash)
|
||||
the_hash_algo->update_fn(&f->ctx, f->buffer, offset);
|
||||
the_hash_algo->unsafe_update_fn(&f->ctx, f->buffer, offset);
|
||||
flush(f, f->buffer, offset);
|
||||
f->offset = 0;
|
||||
}
|
||||
@ -73,7 +73,7 @@ int finalize_hashfile(struct hashfile *f, unsigned char *result,
|
||||
if (f->skip_hash)
|
||||
hashclr(f->buffer, the_repository->hash_algo);
|
||||
else
|
||||
the_hash_algo->final_fn(f->buffer, &f->ctx);
|
||||
the_hash_algo->unsafe_final_fn(f->buffer, &f->ctx);
|
||||
|
||||
if (result)
|
||||
hashcpy(result, f->buffer, the_repository->hash_algo);
|
||||
@ -128,7 +128,7 @@ void hashwrite(struct hashfile *f, const void *buf, unsigned int count)
|
||||
* f->offset is necessarily zero.
|
||||
*/
|
||||
if (!f->skip_hash)
|
||||
the_hash_algo->update_fn(&f->ctx, buf, nr);
|
||||
the_hash_algo->unsafe_update_fn(&f->ctx, buf, nr);
|
||||
flush(f, buf, nr);
|
||||
} else {
|
||||
/*
|
||||
@ -174,7 +174,7 @@ static struct hashfile *hashfd_internal(int fd, const char *name,
|
||||
f->name = name;
|
||||
f->do_crc = 0;
|
||||
f->skip_hash = 0;
|
||||
the_hash_algo->init_fn(&f->ctx);
|
||||
the_hash_algo->unsafe_init_fn(&f->ctx);
|
||||
|
||||
f->buffer_len = buffer_len;
|
||||
f->buffer = xmalloc(buffer_len);
|
||||
@ -208,7 +208,7 @@ void hashfile_checkpoint(struct hashfile *f, struct hashfile_checkpoint *checkpo
|
||||
{
|
||||
hashflush(f);
|
||||
checkpoint->offset = f->total;
|
||||
the_hash_algo->clone_fn(&checkpoint->ctx, &f->ctx);
|
||||
the_hash_algo->unsafe_clone_fn(&checkpoint->ctx, &f->ctx);
|
||||
}
|
||||
|
||||
int hashfile_truncate(struct hashfile *f, struct hashfile_checkpoint *checkpoint)
|
||||
@ -219,7 +219,7 @@ int hashfile_truncate(struct hashfile *f, struct hashfile_checkpoint *checkpoint
|
||||
lseek(f->fd, offset, SEEK_SET) != offset)
|
||||
return -1;
|
||||
f->total = offset;
|
||||
the_hash_algo->clone_fn(&f->ctx, &checkpoint->ctx);
|
||||
the_hash_algo->unsafe_clone_fn(&f->ctx, &checkpoint->ctx);
|
||||
f->offset = 0; /* hashflush() was called in checkpoint */
|
||||
return 0;
|
||||
}
|
||||
@ -245,9 +245,9 @@ int hashfile_checksum_valid(const unsigned char *data, size_t total_len)
|
||||
if (total_len < the_hash_algo->rawsz)
|
||||
return 0; /* say "too short"? */
|
||||
|
||||
the_hash_algo->init_fn(&ctx);
|
||||
the_hash_algo->update_fn(&ctx, data, data_len);
|
||||
the_hash_algo->final_fn(got, &ctx);
|
||||
the_hash_algo->unsafe_init_fn(&ctx);
|
||||
the_hash_algo->unsafe_update_fn(&ctx, data, data_len);
|
||||
the_hash_algo->unsafe_final_fn(got, &ctx);
|
||||
|
||||
return hasheq(got, data + data_len, the_repository->hash_algo);
|
||||
}
|
||||
|
72
hash.h
72
hash.h
@ -15,6 +15,36 @@
|
||||
#include "block-sha1/sha1.h"
|
||||
#endif
|
||||
|
||||
#if defined(SHA1_APPLE_UNSAFE)
|
||||
# include <CommonCrypto/CommonDigest.h>
|
||||
# define platform_SHA_CTX_unsafe CC_SHA1_CTX
|
||||
# define platform_SHA1_Init_unsafe CC_SHA1_Init
|
||||
# define platform_SHA1_Update_unsafe CC_SHA1_Update
|
||||
# define platform_SHA1_Final_unsafe CC_SHA1_Final
|
||||
#elif defined(SHA1_OPENSSL_UNSAFE)
|
||||
# include <openssl/sha.h>
|
||||
# if defined(OPENSSL_API_LEVEL) && OPENSSL_API_LEVEL >= 3
|
||||
# define SHA1_NEEDS_CLONE_HELPER_UNSAFE
|
||||
# include "sha1/openssl.h"
|
||||
# define platform_SHA_CTX_unsafe openssl_SHA1_CTX
|
||||
# define platform_SHA1_Init_unsafe openssl_SHA1_Init
|
||||
# define platform_SHA1_Clone_unsafe openssl_SHA1_Clone
|
||||
# define platform_SHA1_Update_unsafe openssl_SHA1_Update
|
||||
# define platform_SHA1_Final_unsafe openssl_SHA1_Final
|
||||
# else
|
||||
# define platform_SHA_CTX_unsafe SHA_CTX
|
||||
# define platform_SHA1_Init_unsafe SHA1_Init
|
||||
# define platform_SHA1_Update_unsafe SHA1_Update
|
||||
# define platform_SHA1_Final_unsafe SHA1_Final
|
||||
# endif
|
||||
#elif defined(SHA1_BLK_UNSAFE)
|
||||
# include "block-sha1/sha1.h"
|
||||
# define platform_SHA_CTX_unsafe blk_SHA_CTX
|
||||
# define platform_SHA1_Init_unsafe blk_SHA1_Init
|
||||
# define platform_SHA1_Update_unsafe blk_SHA1_Update
|
||||
# define platform_SHA1_Final_unsafe blk_SHA1_Final
|
||||
#endif
|
||||
|
||||
#if defined(SHA256_NETTLE)
|
||||
#include "sha256/nettle.h"
|
||||
#elif defined(SHA256_GCRYPT)
|
||||
@ -44,14 +74,32 @@
|
||||
#define platform_SHA1_Final SHA1_Final
|
||||
#endif
|
||||
|
||||
#ifndef platform_SHA_CTX_unsafe
|
||||
# define platform_SHA_CTX_unsafe platform_SHA_CTX
|
||||
# define platform_SHA1_Init_unsafe platform_SHA1_Init
|
||||
# define platform_SHA1_Update_unsafe platform_SHA1_Update
|
||||
# define platform_SHA1_Final_unsafe platform_SHA1_Final
|
||||
# ifdef platform_SHA1_Clone
|
||||
# define platform_SHA1_Clone_unsafe platform_SHA1_Clone
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define git_SHA_CTX platform_SHA_CTX
|
||||
#define git_SHA1_Init platform_SHA1_Init
|
||||
#define git_SHA1_Update platform_SHA1_Update
|
||||
#define git_SHA1_Final platform_SHA1_Final
|
||||
|
||||
#define git_SHA_CTX_unsafe platform_SHA_CTX_unsafe
|
||||
#define git_SHA1_Init_unsafe platform_SHA1_Init_unsafe
|
||||
#define git_SHA1_Update_unsafe platform_SHA1_Update_unsafe
|
||||
#define git_SHA1_Final_unsafe platform_SHA1_Final_unsafe
|
||||
|
||||
#ifdef platform_SHA1_Clone
|
||||
#define git_SHA1_Clone platform_SHA1_Clone
|
||||
#endif
|
||||
#ifdef platform_SHA1_Clone_unsafe
|
||||
# define git_SHA1_Clone_unsafe platform_SHA1_Clone_unsafe
|
||||
#endif
|
||||
|
||||
#ifndef platform_SHA256_CTX
|
||||
#define platform_SHA256_CTX SHA256_CTX
|
||||
@ -81,6 +129,13 @@ static inline void git_SHA1_Clone(git_SHA_CTX *dst, const git_SHA_CTX *src)
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
}
|
||||
#endif
|
||||
#ifndef SHA1_NEEDS_CLONE_HELPER_UNSAFE
|
||||
static inline void git_SHA1_Clone_unsafe(git_SHA_CTX_unsafe *dst,
|
||||
const git_SHA_CTX_unsafe *src)
|
||||
{
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SHA256_NEEDS_CLONE_HELPER
|
||||
static inline void git_SHA256_Clone(git_SHA256_CTX *dst, const git_SHA256_CTX *src)
|
||||
@ -178,6 +233,8 @@ enum get_oid_result {
|
||||
/* A suitably aligned type for stack allocations of hash contexts. */
|
||||
union git_hash_ctx {
|
||||
git_SHA_CTX sha1;
|
||||
git_SHA_CTX_unsafe sha1_unsafe;
|
||||
|
||||
git_SHA256_CTX sha256;
|
||||
};
|
||||
typedef union git_hash_ctx git_hash_ctx;
|
||||
@ -222,6 +279,21 @@ struct git_hash_algo {
|
||||
/* The hash finalization function for object IDs. */
|
||||
git_hash_final_oid_fn final_oid_fn;
|
||||
|
||||
/* The non-cryptographic hash initialization function. */
|
||||
git_hash_init_fn unsafe_init_fn;
|
||||
|
||||
/* The non-cryptographic hash context cloning function. */
|
||||
git_hash_clone_fn unsafe_clone_fn;
|
||||
|
||||
/* The non-cryptographic hash update function. */
|
||||
git_hash_update_fn unsafe_update_fn;
|
||||
|
||||
/* The non-cryptographic hash finalization function. */
|
||||
git_hash_final_fn unsafe_final_fn;
|
||||
|
||||
/* The non-cryptographic hash finalization function. */
|
||||
git_hash_final_oid_fn unsafe_final_oid_fn;
|
||||
|
||||
/* The OID of the empty tree. */
|
||||
const struct object_id *empty_tree;
|
||||
|
||||
|
124
object-file.c
124
object-file.c
@ -115,6 +115,33 @@ static void git_hash_sha1_final_oid(struct object_id *oid, git_hash_ctx *ctx)
|
||||
oid->algo = GIT_HASH_SHA1;
|
||||
}
|
||||
|
||||
static void git_hash_sha1_init_unsafe(git_hash_ctx *ctx)
|
||||
{
|
||||
git_SHA1_Init_unsafe(&ctx->sha1_unsafe);
|
||||
}
|
||||
|
||||
static void git_hash_sha1_clone_unsafe(git_hash_ctx *dst, const git_hash_ctx *src)
|
||||
{
|
||||
git_SHA1_Clone_unsafe(&dst->sha1_unsafe, &src->sha1_unsafe);
|
||||
}
|
||||
|
||||
static void git_hash_sha1_update_unsafe(git_hash_ctx *ctx, const void *data,
|
||||
size_t len)
|
||||
{
|
||||
git_SHA1_Update_unsafe(&ctx->sha1_unsafe, data, len);
|
||||
}
|
||||
|
||||
static void git_hash_sha1_final_unsafe(unsigned char *hash, git_hash_ctx *ctx)
|
||||
{
|
||||
git_SHA1_Final_unsafe(hash, &ctx->sha1_unsafe);
|
||||
}
|
||||
|
||||
static void git_hash_sha1_final_oid_unsafe(struct object_id *oid, git_hash_ctx *ctx)
|
||||
{
|
||||
git_SHA1_Final_unsafe(oid->hash, &ctx->sha1_unsafe);
|
||||
memset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ);
|
||||
oid->algo = GIT_HASH_SHA1;
|
||||
}
|
||||
|
||||
static void git_hash_sha256_init(git_hash_ctx *ctx)
|
||||
{
|
||||
@ -189,6 +216,11 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {
|
||||
.update_fn = git_hash_unknown_update,
|
||||
.final_fn = git_hash_unknown_final,
|
||||
.final_oid_fn = git_hash_unknown_final_oid,
|
||||
.unsafe_init_fn = git_hash_unknown_init,
|
||||
.unsafe_clone_fn = git_hash_unknown_clone,
|
||||
.unsafe_update_fn = git_hash_unknown_update,
|
||||
.unsafe_final_fn = git_hash_unknown_final,
|
||||
.unsafe_final_oid_fn = git_hash_unknown_final_oid,
|
||||
.empty_tree = NULL,
|
||||
.empty_blob = NULL,
|
||||
.null_oid = NULL,
|
||||
@ -204,6 +236,11 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {
|
||||
.update_fn = git_hash_sha1_update,
|
||||
.final_fn = git_hash_sha1_final,
|
||||
.final_oid_fn = git_hash_sha1_final_oid,
|
||||
.unsafe_init_fn = git_hash_sha1_init_unsafe,
|
||||
.unsafe_clone_fn = git_hash_sha1_clone_unsafe,
|
||||
.unsafe_update_fn = git_hash_sha1_update_unsafe,
|
||||
.unsafe_final_fn = git_hash_sha1_final_unsafe,
|
||||
.unsafe_final_oid_fn = git_hash_sha1_final_oid_unsafe,
|
||||
.empty_tree = &empty_tree_oid,
|
||||
.empty_blob = &empty_blob_oid,
|
||||
.null_oid = &null_oid_sha1,
|
||||
@ -219,6 +256,11 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {
|
||||
.update_fn = git_hash_sha256_update,
|
||||
.final_fn = git_hash_sha256_final,
|
||||
.final_oid_fn = git_hash_sha256_final_oid,
|
||||
.unsafe_init_fn = git_hash_sha256_init,
|
||||
.unsafe_clone_fn = git_hash_sha256_clone,
|
||||
.unsafe_update_fn = git_hash_sha256_update,
|
||||
.unsafe_final_fn = git_hash_sha256_final,
|
||||
.unsafe_final_oid_fn = git_hash_sha256_final_oid,
|
||||
.empty_tree = &empty_tree_oid_sha256,
|
||||
.empty_blob = &empty_blob_oid_sha256,
|
||||
.null_oid = &null_oid_sha256,
|
||||
@ -1932,17 +1974,77 @@ static void write_object_file_prepare_literally(const struct git_hash_algo *algo
|
||||
hash_object_body(algo, &c, buf, len, oid, hdr, hdrlen);
|
||||
}
|
||||
|
||||
static int check_collision(const char *filename_a, const char *filename_b)
|
||||
{
|
||||
char buf_a[4096], buf_b[4096];
|
||||
int fd_a = -1, fd_b = -1;
|
||||
int ret = 0;
|
||||
|
||||
fd_a = open(filename_a, O_RDONLY);
|
||||
if (fd_a < 0) {
|
||||
ret = error_errno(_("unable to open %s"), filename_a);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fd_b = open(filename_b, O_RDONLY);
|
||||
if (fd_b < 0) {
|
||||
ret = error_errno(_("unable to open %s"), filename_b);
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
ssize_t sz_a, sz_b;
|
||||
|
||||
sz_a = read_in_full(fd_a, buf_a, sizeof(buf_a));
|
||||
if (sz_a < 0) {
|
||||
ret = error_errno(_("unable to read %s"), filename_a);
|
||||
goto out;
|
||||
}
|
||||
|
||||
sz_b = read_in_full(fd_b, buf_b, sizeof(buf_b));
|
||||
if (sz_b < 0) {
|
||||
ret = error_errno(_("unable to read %s"), filename_b);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (sz_a != sz_b || memcmp(buf_a, buf_b, sz_a)) {
|
||||
ret = error(_("files '%s' and '%s' differ in contents"),
|
||||
filename_a, filename_b);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (sz_a < sizeof(buf_a))
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
if (fd_a > -1)
|
||||
close(fd_a);
|
||||
if (fd_b > -1)
|
||||
close(fd_b);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the just written object into its final resting place.
|
||||
*/
|
||||
int finalize_object_file(const char *tmpfile, const char *filename)
|
||||
{
|
||||
return finalize_object_file_flags(tmpfile, filename, 0);
|
||||
}
|
||||
|
||||
int finalize_object_file_flags(const char *tmpfile, const char *filename,
|
||||
enum finalize_object_file_flags flags)
|
||||
{
|
||||
struct stat st;
|
||||
int ret = 0;
|
||||
|
||||
if (object_creation_mode == OBJECT_CREATION_USES_RENAMES)
|
||||
goto try_rename;
|
||||
else if (link(tmpfile, filename))
|
||||
ret = errno;
|
||||
else
|
||||
unlink_or_warn(tmpfile);
|
||||
|
||||
/*
|
||||
* Coda hack - coda doesn't like cross-directory links,
|
||||
@ -1957,16 +2059,24 @@ int finalize_object_file(const char *tmpfile, const char *filename)
|
||||
*/
|
||||
if (ret && ret != EEXIST) {
|
||||
try_rename:
|
||||
if (!rename(tmpfile, filename))
|
||||
if (!stat(filename, &st))
|
||||
ret = EEXIST;
|
||||
else if (!rename(tmpfile, filename))
|
||||
goto out;
|
||||
ret = errno;
|
||||
else
|
||||
ret = errno;
|
||||
}
|
||||
unlink_or_warn(tmpfile);
|
||||
if (ret) {
|
||||
if (ret != EEXIST) {
|
||||
int saved_errno = errno;
|
||||
unlink_or_warn(tmpfile);
|
||||
errno = saved_errno;
|
||||
return error_errno(_("unable to write file %s"), filename);
|
||||
}
|
||||
/* FIXME!!! Collision check here ? */
|
||||
if (!(flags & FOF_SKIP_COLLISION_CHECK) &&
|
||||
check_collision(tmpfile, filename))
|
||||
return -1;
|
||||
unlink_or_warn(tmpfile);
|
||||
}
|
||||
|
||||
out:
|
||||
@ -2219,7 +2329,8 @@ static int write_loose_object(const struct object_id *oid, char *hdr,
|
||||
warning_errno(_("failed utime() on %s"), tmp_file.buf);
|
||||
}
|
||||
|
||||
return finalize_object_file(tmp_file.buf, filename.buf);
|
||||
return finalize_object_file_flags(tmp_file.buf, filename.buf,
|
||||
FOF_SKIP_COLLISION_CHECK);
|
||||
}
|
||||
|
||||
static int freshen_loose_object(const struct object_id *oid)
|
||||
@ -2341,7 +2452,8 @@ int stream_loose_object(struct input_stream *in_stream, size_t len,
|
||||
strbuf_release(&dir);
|
||||
}
|
||||
|
||||
err = finalize_object_file(tmp_file.buf, filename.buf);
|
||||
err = finalize_object_file_flags(tmp_file.buf, filename.buf,
|
||||
FOF_SKIP_COLLISION_CHECK);
|
||||
if (!err && compat)
|
||||
err = repo_add_loose_object_map(the_repository, oid, &compat_oid);
|
||||
cleanup:
|
||||
|
@ -117,7 +117,13 @@ int check_object_signature(struct repository *r, const struct object_id *oid,
|
||||
*/
|
||||
int stream_object_signature(struct repository *r, const struct object_id *oid);
|
||||
|
||||
enum finalize_object_file_flags {
|
||||
FOF_SKIP_COLLISION_CHECK = 1,
|
||||
};
|
||||
|
||||
int finalize_object_file(const char *tmpfile, const char *filename);
|
||||
int finalize_object_file_flags(const char *tmpfile, const char *filename,
|
||||
enum finalize_object_file_flags flags);
|
||||
|
||||
/* Helper to check and "touch" a file */
|
||||
int check_and_freshen_file(const char *fn, int freshen);
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "csum-file.h"
|
||||
#include "remote.h"
|
||||
#include "chunk-format.h"
|
||||
#include "object-file.h"
|
||||
#include "pack-mtimes.h"
|
||||
#include "pack-objects.h"
|
||||
#include "pack-revindex.h"
|
||||
@ -528,9 +529,9 @@ static void rename_tmp_packfile(struct strbuf *name_prefix, const char *source,
|
||||
size_t name_prefix_len = name_prefix->len;
|
||||
|
||||
strbuf_addstr(name_prefix, ext);
|
||||
if (rename(source, name_prefix->buf))
|
||||
die_errno("unable to rename temporary file to '%s'",
|
||||
name_prefix->buf);
|
||||
if (finalize_object_file(source, name_prefix->buf))
|
||||
die("unable to rename temporary file to '%s'",
|
||||
name_prefix->buf);
|
||||
strbuf_setlen(name_prefix, name_prefix_len);
|
||||
}
|
||||
|
||||
|
@ -40,10 +40,12 @@ static inline void openssl_SHA1_Clone(struct openssl_SHA1_CTX *dst,
|
||||
EVP_MD_CTX_copy_ex(dst->ectx, src->ectx);
|
||||
}
|
||||
|
||||
#ifndef platform_SHA_CTX
|
||||
#define platform_SHA_CTX openssl_SHA1_CTX
|
||||
#define platform_SHA1_Init openssl_SHA1_Init
|
||||
#define platform_SHA1_Clone openssl_SHA1_Clone
|
||||
#define platform_SHA1_Update openssl_SHA1_Update
|
||||
#define platform_SHA1_Final openssl_SHA1_Final
|
||||
#endif
|
||||
|
||||
#endif /* SHA1_OPENSSL_H */
|
||||
|
@ -18,7 +18,10 @@ void git_SHA1DCFinal(unsigned char [20], SHA1_CTX *);
|
||||
void git_SHA1DCUpdate(SHA1_CTX *ctx, const void *data, unsigned long len);
|
||||
|
||||
#define platform_SHA_IS_SHA1DC /* used by "test-tool sha1-is-sha1dc" */
|
||||
|
||||
#ifndef platform_SHA_CTX
|
||||
#define platform_SHA_CTX SHA1_CTX
|
||||
#define platform_SHA1_Init git_SHA1DCInit
|
||||
#define platform_SHA1_Update git_SHA1DCUpdate
|
||||
#define platform_SHA1_Final git_SHA1DCFinal
|
||||
#endif
|
||||
|
@ -44,9 +44,14 @@ create_new_pack() {
|
||||
}
|
||||
|
||||
do_repack() {
|
||||
for f in $pack.*
|
||||
do
|
||||
mv $f "$(echo $f | sed -e 's/pack-/pack-corrupt-/')" || return 1
|
||||
done &&
|
||||
pack=$(printf "$blob_1\n$blob_2\n$blob_3\n" |
|
||||
git pack-objects $@ .git/objects/pack/pack) &&
|
||||
pack=".git/objects/pack/pack-${pack}"
|
||||
pack=".git/objects/pack/pack-${pack}" &&
|
||||
rm -f .git/objects/pack/pack-corrupt-*
|
||||
}
|
||||
|
||||
do_corrupt_object() {
|
||||
|
26
tmp-objdir.c
26
tmp-objdir.c
@ -206,9 +206,11 @@ static int read_dir_paths(struct string_list *out, const char *path)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int migrate_paths(struct strbuf *src, struct strbuf *dst);
|
||||
static int migrate_paths(struct strbuf *src, struct strbuf *dst,
|
||||
enum finalize_object_file_flags flags);
|
||||
|
||||
static int migrate_one(struct strbuf *src, struct strbuf *dst)
|
||||
static int migrate_one(struct strbuf *src, struct strbuf *dst,
|
||||
enum finalize_object_file_flags flags)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
@ -220,12 +222,18 @@ static int migrate_one(struct strbuf *src, struct strbuf *dst)
|
||||
return -1;
|
||||
} else if (errno != EEXIST)
|
||||
return -1;
|
||||
return migrate_paths(src, dst);
|
||||
return migrate_paths(src, dst, flags);
|
||||
}
|
||||
return finalize_object_file(src->buf, dst->buf);
|
||||
return finalize_object_file_flags(src->buf, dst->buf, flags);
|
||||
}
|
||||
|
||||
static int migrate_paths(struct strbuf *src, struct strbuf *dst)
|
||||
static int is_loose_object_shard(const char *name)
|
||||
{
|
||||
return strlen(name) == 2 && isxdigit(name[0]) && isxdigit(name[1]);
|
||||
}
|
||||
|
||||
static int migrate_paths(struct strbuf *src, struct strbuf *dst,
|
||||
enum finalize_object_file_flags flags)
|
||||
{
|
||||
size_t src_len = src->len, dst_len = dst->len;
|
||||
struct string_list paths = STRING_LIST_INIT_DUP;
|
||||
@ -239,11 +247,15 @@ static int migrate_paths(struct strbuf *src, struct strbuf *dst)
|
||||
|
||||
for (i = 0; i < paths.nr; i++) {
|
||||
const char *name = paths.items[i].string;
|
||||
enum finalize_object_file_flags flags_copy = flags;
|
||||
|
||||
strbuf_addf(src, "/%s", name);
|
||||
strbuf_addf(dst, "/%s", name);
|
||||
|
||||
ret |= migrate_one(src, dst);
|
||||
if (is_loose_object_shard(name))
|
||||
flags_copy |= FOF_SKIP_COLLISION_CHECK;
|
||||
|
||||
ret |= migrate_one(src, dst, flags_copy);
|
||||
|
||||
strbuf_setlen(src, src_len);
|
||||
strbuf_setlen(dst, dst_len);
|
||||
@ -271,7 +283,7 @@ int tmp_objdir_migrate(struct tmp_objdir *t)
|
||||
strbuf_addbuf(&src, &t->path);
|
||||
strbuf_addstr(&dst, repo_get_object_directory(the_repository));
|
||||
|
||||
ret = migrate_paths(&src, &dst);
|
||||
ret = migrate_paths(&src, &dst, 0);
|
||||
|
||||
strbuf_release(&src);
|
||||
strbuf_release(&dst);
|
||||
|
Loading…
Reference in New Issue
Block a user