summaryrefslogtreecommitdiff
path: root/src/odb.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/odb.c')
-rw-r--r--src/odb.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/src/odb.c b/src/odb.c
index 43a75234e..ef3ced3d9 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -145,6 +145,48 @@ int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_otype type)
return GIT_SUCCESS;
}
+int git_odb__hashlink(git_oid *out, const char *path)
+{
+ struct stat st;
+ int error;
+ git_off_t size;
+
+ error = p_lstat(path, &st);
+ if (error < 0)
+ return git__throw(GIT_EOSERR, "Failed to stat blob. %s", strerror(errno));
+
+ size = st.st_size;
+
+ if (!git__is_sizet(size))
+ return git__throw(GIT_EOSERR, "File size overflow for 32-bit systems");
+
+ if (S_ISLNK(st.st_mode)) {
+ char *link_data;
+ ssize_t read_len;
+
+ link_data = git__malloc(size);
+ if (link_data == NULL)
+ return GIT_ENOMEM;
+
+ read_len = p_readlink(path, link_data, size + 1);
+ if (read_len != (ssize_t)size)
+ return git__throw(GIT_EOSERR, "Failed to read symlink data");
+
+ error = git_odb_hash(out, link_data, (size_t)size, GIT_OBJ_BLOB);
+ free(link_data);
+ } else {
+ int fd;
+
+ if ((fd = p_open(path, O_RDONLY)) < 0)
+ return git__throw(GIT_ENOTFOUND, "Could not open '%s'", path);
+
+ error = git_odb__hashfd(out, fd, (size_t)size, GIT_OBJ_BLOB);
+ p_close(fd);
+ }
+
+ return error;
+}
+
int git_odb_hashfile(git_oid *out, const char *path, git_otype type)
{
int fd, error;