From 18e5b8547d075afc53c2b20ba15ef7c09cb5efd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicent=20Mart=C3=AD?= Date: Fri, 10 Feb 2012 19:47:02 +0100 Subject: [PATCH] odb: Add internal `git_odb__hashfd` --- src/indexer.c | 2 +- src/odb.c | 50 ++++++++++++++++++++++++++++---------------------- src/odb.h | 4 +++- 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/indexer.c b/src/indexer.c index 1b2cd61e0..8912e8bf3 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -345,7 +345,7 @@ int git_indexer_run(git_indexer *idx, git_indexer_stats *stats) } /* FIXME: Parse the object instead of hashing it */ - error = git_odb__hash_obj(&oid, &obj); + error = git_odb__hashobj(&oid, &obj); if (error < GIT_SUCCESS) { error = git__rethrow(error, "Failed to hash object"); goto cleanup; diff --git a/src/odb.c b/src/odb.c index 8905c2237..43a75234e 100644 --- a/src/odb.c +++ b/src/odb.c @@ -33,13 +33,13 @@ static int format_object_header(char *hdr, size_t n, size_t obj_len, git_otype o const char *type_str = git_object_type2string(obj_type); int len = p_snprintf(hdr, n, "%s %"PRIuZ, type_str, obj_len); - if (len < 0 || ((size_t) len) >= n) + if (len < 0 || len >= (int)n) return git__throw(GIT_ERROR, "Cannot format object header. Length is out of bounds"); return len+1; } -int git_odb__hash_obj(git_oid *id, git_rawobj *obj) +int git_odb__hashobj(git_oid *id, git_rawobj *obj) { git_buf_vec vec[2]; char header[64]; @@ -113,22 +113,13 @@ void git_odb_object_free(git_odb_object *object) git_cached_obj_decref((git_cached_obj *)object, &free_odb_object); } -int git_odb_hashfile(git_oid *out, const char *path, git_otype type) +int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_otype type) { - int fd, hdr_len; + int hdr_len; char hdr[64], buffer[2048]; - git_off_t size; git_hash_ctx *ctx; - if ((fd = p_open(path, O_RDONLY)) < 0) - return git__throw(GIT_ENOTFOUND, "Could not open '%s'", path); - - if ((size = git_futils_filesize(fd)) < 0 || !git__is_sizet(size)) { - p_close(fd); - return git__throw(GIT_EOSERR, "'%s' appears to be corrupted", path); - } - - hdr_len = format_object_header(hdr, sizeof(hdr), (size_t)size, type); + hdr_len = format_object_header(hdr, sizeof(hdr), size, type); if (hdr_len < 0) return git__throw(GIT_ERROR, "Failed to format blob header. Length is out of bounds"); @@ -137,28 +128,43 @@ int git_odb_hashfile(git_oid *out, const char *path, git_otype type) git_hash_update(ctx, hdr, hdr_len); while (size > 0) { - ssize_t read_len; - - read_len = read(fd, buffer, sizeof(buffer)); + ssize_t read_len = read(fd, buffer, sizeof(buffer)); if (read_len < 0) { - p_close(fd); git_hash_free_ctx(ctx); - return git__throw(GIT_EOSERR, "Can't read full file '%s'", path); + return git__throw(GIT_EOSERR, "Error when reading file: %s", strerror(errno)); } git_hash_update(ctx, buffer, read_len); size -= read_len; } - p_close(fd); - git_hash_final(out, ctx); git_hash_free_ctx(ctx); return GIT_SUCCESS; } +int git_odb_hashfile(git_oid *out, const char *path, git_otype type) +{ + int fd, error; + git_off_t size; + + if ((fd = p_open(path, O_RDONLY)) < 0) + return git__throw(GIT_ENOTFOUND, "Could not open '%s'", path); + + if ((size = git_futils_filesize(fd)) < 0 || !git__is_sizet(size)) { + p_close(fd); + return git__throw(GIT_EOSERR, + "File size overflow. The object is too big to fit in 32-bit mode"); + } + + error = git_odb__hashfd(out, fd, (size_t)size, type); + + p_close(fd); + return error; +} + int git_odb_hash(git_oid *id, const void *data, size_t len, git_otype type) { git_rawobj raw; @@ -169,7 +175,7 @@ int git_odb_hash(git_oid *id, const void *data, size_t len, git_otype type) raw.len = len; raw.type = type; - return git_odb__hash_obj(id, &raw); + return git_odb__hashobj(id, &raw); } /** diff --git a/src/odb.h b/src/odb.h index b81533001..fd0787e84 100644 --- a/src/odb.h +++ b/src/odb.h @@ -13,6 +13,7 @@ #include "vector.h" #include "cache.h" +#include "posix.h" #define GIT_OBJECTS_DIR "objects/" #define GIT_OBJECT_DIR_MODE 0777 @@ -38,6 +39,7 @@ struct git_odb { git_cache cache; }; -int git_odb__hash_obj(git_oid *id, git_rawobj *obj); +int git_odb__hashobj(git_oid *id, git_rawobj *obj); +int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_otype type); #endif