summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/indexer.c2
-rw-r--r--src/odb.c50
-rw-r--r--src/odb.h4
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