mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-06 23:03:35 +00:00

This converts virtually all of the places that allocate GIT_PATH_MAX buffers on the stack for manipulating paths to use git_buf objects instead. The patch is pretty careful not to touch the public API for libgit2, so there are a few places that still use GIT_PATH_MAX. This extends and changes some details of the git_buf implementation to add a couple of extra functions and to make error handling easier. This includes serious alterations to all the path.c functions, and several of the fileops.c ones, too. Also, there are a number of new functions that parallel existing ones except that use a git_buf instead of a stack-based buffer (such as git_config_find_global_r that exists alongsize git_config_find_global). This also modifies the win32 version of p_realpath to allocate whatever buffer size is needed to accommodate the realpath instead of hardcoding a GIT_PATH_MAX limit, but that change needs to be tested still.
143 lines
3.2 KiB
C
143 lines
3.2 KiB
C
/*
|
|
* Copyright (C) 2009-2011 the libgit2 contributors
|
|
*
|
|
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
|
* a Linking Exception. For full terms see the included COPYING file.
|
|
*/
|
|
|
|
#include "git2/common.h"
|
|
#include "git2/object.h"
|
|
#include "git2/repository.h"
|
|
|
|
#include "common.h"
|
|
#include "blob.h"
|
|
|
|
const void *git_blob_rawcontent(git_blob *blob)
|
|
{
|
|
assert(blob);
|
|
return blob->odb_object->raw.data;
|
|
}
|
|
|
|
size_t git_blob_rawsize(git_blob *blob)
|
|
{
|
|
assert(blob);
|
|
return blob->odb_object->raw.len;
|
|
}
|
|
|
|
void git_blob__free(git_blob *blob)
|
|
{
|
|
git_odb_object_free(blob->odb_object);
|
|
git__free(blob);
|
|
}
|
|
|
|
int git_blob__parse(git_blob *blob, git_odb_object *odb_obj)
|
|
{
|
|
assert(blob);
|
|
git_cached_obj_incref((git_cached_obj *)odb_obj);
|
|
blob->odb_object = odb_obj;
|
|
return GIT_SUCCESS;
|
|
}
|
|
|
|
int git_blob_create_frombuffer(git_oid *oid, git_repository *repo, const void *buffer, size_t len)
|
|
{
|
|
int error;
|
|
git_odb *odb;
|
|
git_odb_stream *stream;
|
|
|
|
error = git_repository_odb__weakptr(&odb, repo);
|
|
if (error < GIT_SUCCESS)
|
|
return error;
|
|
|
|
if ((error = git_odb_open_wstream(&stream, odb, len, GIT_OBJ_BLOB)) < GIT_SUCCESS)
|
|
return git__rethrow(error, "Failed to create blob");
|
|
|
|
if ((error = stream->write(stream, buffer, len)) < GIT_SUCCESS) {
|
|
stream->free(stream);
|
|
return error;
|
|
}
|
|
|
|
error = stream->finalize_write(oid, stream);
|
|
stream->free(stream);
|
|
|
|
if (error < GIT_SUCCESS)
|
|
return git__rethrow(error, "Failed to create blob");
|
|
|
|
return GIT_SUCCESS;
|
|
}
|
|
|
|
int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *path)
|
|
{
|
|
int error = GIT_SUCCESS;
|
|
int islnk = 0;
|
|
int fd = 0;
|
|
git_buf full_path = GIT_BUF_INIT;
|
|
char buffer[2048];
|
|
git_off_t size;
|
|
git_odb_stream *stream = NULL;
|
|
struct stat st;
|
|
const char *workdir;
|
|
git_odb *odb;
|
|
|
|
workdir = git_repository_workdir(repo);
|
|
if (workdir == NULL)
|
|
return git__throw(GIT_ENOTFOUND, "Failed to create blob. (No working directory found)");
|
|
|
|
error = git_buf_joinpath(&full_path, workdir, path);
|
|
if (error < GIT_SUCCESS)
|
|
return error;
|
|
|
|
error = p_lstat(full_path.ptr, &st);
|
|
if (error < 0) {
|
|
error = git__throw(GIT_EOSERR, "Failed to stat blob. %s", strerror(errno));
|
|
goto cleanup;
|
|
}
|
|
|
|
islnk = S_ISLNK(st.st_mode);
|
|
size = st.st_size;
|
|
|
|
error = git_repository_odb__weakptr(&odb, repo);
|
|
if (error < GIT_SUCCESS)
|
|
goto cleanup;
|
|
|
|
if (!islnk) {
|
|
if ((fd = p_open(full_path.ptr, O_RDONLY)) < 0) {
|
|
error = git__throw(GIT_ENOTFOUND, "Failed to create blob. Could not open '%s'", full_path.ptr
|
|
);
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
if ((error = git_odb_open_wstream(&stream, odb, (size_t)size, GIT_OBJ_BLOB)) < GIT_SUCCESS)
|
|
goto cleanup;
|
|
|
|
while (size > 0) {
|
|
ssize_t read_len;
|
|
|
|
if (!islnk)
|
|
read_len = p_read(fd, buffer, sizeof(buffer));
|
|
else
|
|
read_len = p_readlink(full_path.ptr, buffer, sizeof(buffer));
|
|
|
|
if (read_len < 0) {
|
|
error = git__throw(GIT_EOSERR, "Failed to create blob. Can't read full file");
|
|
goto cleanup;
|
|
}
|
|
|
|
stream->write(stream, buffer, read_len);
|
|
size -= read_len;
|
|
}
|
|
|
|
error = stream->finalize_write(oid, stream);
|
|
|
|
cleanup:
|
|
if (stream)
|
|
stream->free(stream);
|
|
if (!islnk && fd)
|
|
p_close(fd);
|
|
git_buf_free(&full_path);
|
|
|
|
return error == GIT_SUCCESS ? GIT_SUCCESS :
|
|
git__rethrow(error, "Failed to create blob");
|
|
}
|
|
|