odb: Add internal `git_odb__hashfd`
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
diff --git a/src/indexer.c b/src/indexer.c
index 1b2cd61..8912e8b 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 8905c22..43a7523 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 b815330..fd0787e 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