Commit e1de726c by Russell Belfer

Migrate ODB files to new error handling

This migrates odb.c, odb_loose.c, odb_pack.c and pack.c to
the new style of error handling.  Also got the unix and win32
versions of map.c.  There are some minor changes to other
files but no others were completely converted.

This also contains an update to filebuf so that a zeroed out
filebuf will not think that the fd (== 0) is actually open
(and inadvertently call close() on fd 0 if cleaned up).

Lastly, this was built and tested on win32 and contains a
bunch of fixes for the win32 build which was pretty broken.
parent dda708e7
......@@ -103,7 +103,7 @@ typedef enum {
GIT_EOBJCORRUPTED = -28,
/** The given short oid is ambiguous */
GIT_EAMBIGUOUSOIDPREFIX = -29,
GIT_EAMBIGUOUS = -29,
/** Skip and passthrough the given ODB backend */
GIT_EPASSTHROUGH = -30,
......@@ -128,6 +128,7 @@ typedef enum {
GITERR_REPOSITORY,
GITERR_CONFIG,
GITERR_REGEX,
GITERR_ODB
} git_error_class;
/**
......
......@@ -78,7 +78,7 @@ static int write_file_stream(git_oid *oid, git_odb *odb, const char *path, git_o
char buffer[4096];
git_odb_stream *stream = NULL;
if ((error = git_odb_open_wstream(&stream, odb, file_size, GIT_OBJ_BLOB)) < GIT_SUCCESS)
if ((error = git_odb_open_wstream(&stream, odb, (size_t)file_size, GIT_OBJ_BLOB)) < GIT_SUCCESS)
return error;
if ((fd = p_open(path, O_RDONLY)) < 0) {
......
......@@ -40,7 +40,7 @@ static struct {
{GIT_EEXISTS, "A reference with this name already exists"},
{GIT_EOVERFLOW, "The given integer literal is too large to be parsed"},
{GIT_ENOTNUM, "The given literal is not a valid number"},
{GIT_EAMBIGUOUSOIDPREFIX, "The given oid prefix is ambiguous"},
{GIT_EAMBIGUOUS, "The given oid prefix is ambiguous"},
};
const char *git_strerror(int num)
......@@ -129,9 +129,29 @@ void giterr_set(int error_class, const char *string, ...)
/* automatically suffix strerror(errno) for GITERR_OS errors */
if (error_class == GITERR_OS) {
strncat(error_str, ": ", sizeof(error_str));
strncat(error_str, strerror(errno), sizeof(error_str));
errno = 0;
if (errno != 0) {
strncat(error_str, ": ", sizeof(error_str));
strncat(error_str, strerror(errno), sizeof(error_str));
errno = 0;
}
#ifdef GIT_WIN32
else {
LPVOID lpMsgBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dw, 0, (LPTSTR) &lpMsgBuf, 0, NULL);
if (lpMsgBuf) {
strncat(error_str, ": ", sizeof(error_str));
strncat(error_str, (const char *)lpMsgBuf, sizeof(error_str));
LocalFree(lpMsgBuf);
}
}
#endif
}
giterr_set_str(error_class, error_str);
......
......@@ -67,6 +67,8 @@ static int lock_file(git_filebuf *file, int flags)
if (file->fd < 0)
return -1;
file->fd_is_open = true;
if ((flags & GIT_FILEBUF_APPEND) && git_path_exists(file->path_original) == true) {
git_file source;
char buffer[2048];
......@@ -94,10 +96,10 @@ static int lock_file(git_filebuf *file, int flags)
void git_filebuf_cleanup(git_filebuf *file)
{
if (file->fd >= 0)
if (file->fd_is_open && file->fd >= 0)
p_close(file->fd);
if (file->fd >= 0 && file->path_lock && git_path_exists(file->path_lock) == true)
if (file->fd_is_open && file->path_lock && git_path_exists(file->path_lock))
p_unlink(file->path_lock);
if (file->digest)
......@@ -239,6 +241,7 @@ int git_filebuf_open(git_filebuf *file, const char *path, int flags)
git_buf_free(&tmp_path);
goto cleanup;
}
file->fd_is_open = true;
/* No original path */
file->path_original = NULL;
......@@ -308,6 +311,7 @@ int git_filebuf_commit(git_filebuf *file, mode_t mode)
p_close(file->fd);
file->fd = -1;
file->fd_is_open = false;
if (p_chmod(file->path_lock, mode)) {
giterr_set(GITERR_OS, "Failed to set attributes for file at '%s'", file->path_lock);
......
......@@ -40,6 +40,7 @@ struct git_filebuf {
size_t buf_size, buf_pos;
git_file fd;
bool fd_is_open;
int last_error;
};
......
......@@ -117,7 +117,7 @@ int git_futils_readbuffer_updated(git_buf *buf, const char *path, time_t *mtime,
return fd;
if (p_fstat(fd, &st) < 0 || S_ISDIR(st.st_mode) || !git__is_sizet(st.st_size+1)) {
close(fd);
p_close(fd);
giterr_set(GITERR_OS, "Invalid regular file stat for '%s'", path);
return -1;
}
......@@ -127,7 +127,7 @@ int git_futils_readbuffer_updated(git_buf *buf, const char *path, time_t *mtime,
* has been modified.
*/
if (mtime != NULL && *mtime >= st.st_mtime) {
close(fd);
p_close(fd);
return 0;
}
......@@ -139,8 +139,8 @@ int git_futils_readbuffer_updated(git_buf *buf, const char *path, time_t *mtime,
git_buf_clear(buf);
if (git_buf_grow(buf, len + 1) < 0) {
close(fd);
return GIT_ENOMEM;
p_close(fd);
return -1;
}
buf->ptr[len] = '\0';
......@@ -149,7 +149,7 @@ int git_futils_readbuffer_updated(git_buf *buf, const char *path, time_t *mtime,
ssize_t read_size = p_read(fd, buf->ptr, len);
if (read_size < 0) {
close(fd);
p_close(fd);
giterr_set(GITERR_OS, "Failed to read descriptor for '%s'", path);
return -1;
}
......
......@@ -307,7 +307,7 @@ cleanup:
int git_indexer_run(git_indexer *idx, git_indexer_stats *stats)
{
git_mwindow_file *mwf;
off_t off = sizeof(struct git_pack_header);
git_off_t off = sizeof(struct git_pack_header);
int error;
struct entry *entry;
unsigned int left, processed;
......@@ -328,18 +328,18 @@ int git_indexer_run(git_indexer *idx, git_indexer_stats *stats)
struct git_pack_entry *pentry;
git_mwindow *w = NULL;
int i;
off_t entry_start = off;
git_off_t entry_start = off;
void *packed;
size_t entry_size;
entry = git__malloc(sizeof(struct entry));
memset(entry, 0x0, sizeof(struct entry));
entry = git__calloc(1, sizeof(*entry));
GITERR_CHECK_ALLOC(entry);
if (off > UINT31_MAX) {
entry->offset = UINT32_MAX;
entry->offset_long = off;
} else {
entry->offset = off;
entry->offset = (uint32_t)off;
}
error = git_packfile_unpack(&obj, idx->pack, &off);
......@@ -369,7 +369,7 @@ int git_indexer_run(git_indexer *idx, git_indexer_stats *stats)
git_oid_cpy(&entry->oid, &oid);
entry->crc = crc32(0L, Z_NULL, 0);
entry_size = off - entry_start;
entry_size = (size_t)(off - entry_start);
packed = git_mwindow_open(mwf, &w, entry_start, entry_size, &left);
if (packed == NULL) {
error = git__rethrow(error, "Failed to open window to read packed data");
......
......@@ -31,6 +31,8 @@ typedef struct { /* memory mapped buffer */
#endif
} git_map;
extern int validate_map_args(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset);
extern int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset);
extern int p_munmap(git_map *map);
......
......@@ -178,8 +178,10 @@ static git_mwindow *new_window(
* window.
*/
if (git_futils_mmap_ro(&w->window_map, fd, w->offset, (size_t)len) < GIT_SUCCESS)
goto cleanup;
if (git_futils_mmap_ro(&w->window_map, fd, w->offset, (size_t)len) < 0) {
git__free(w);
return NULL;
}
ctl->mmap_calls++;
ctl->open_windows++;
......@@ -191,10 +193,6 @@ static git_mwindow *new_window(
ctl->peak_open_windows = ctl->open_windows;
return w;
cleanup:
git__free(w);
return NULL;
}
/*
......@@ -253,11 +251,10 @@ unsigned char *git_mwindow_open(
int git_mwindow_file_register(git_mwindow_file *mwf)
{
git_mwindow_ctl *ctl = &GIT_GLOBAL->mem_ctl;
int error;
if (ctl->windowfiles.length == 0 &&
(error = git_vector_init(&ctl->windowfiles, 8, NULL)) < GIT_SUCCESS)
return error;
git_vector_init(&ctl->windowfiles, 8, NULL) < 0)
return -1;
return git_vector_insert(&ctl->windowfiles, mwf);
}
......
......@@ -92,7 +92,7 @@ int git_object_lookup_prefix(
assert(repo && object_out && id);
if (len < GIT_OID_MINPREFIXLEN)
return git__throw(GIT_EAMBIGUOUSOIDPREFIX,
return git__throw(GIT_EAMBIGUOUS,
"Failed to lookup object. Prefix length is lower than %d.", GIT_OID_MINPREFIXLEN);
error = git_repository_odb__weakptr(&odb, repo);
......
......@@ -188,7 +188,7 @@ int git_odb_hashfile(git_oid *out, const char *path, git_otype type)
git_off_t size;
int result, fd = git_futils_open_ro(path);
if (fd < 0)
return -1;
return fd;
if ((size = git_futils_filesize(fd)) < 0 || !git__is_sizet(size)) {
giterr_set(GITERR_OS, "File size overflow for 32-bit systems");
......@@ -507,23 +507,20 @@ int git_odb_read_header(size_t *len_p, git_otype *type_p, git_odb *db, const git
error = b->read_header(len_p, type_p, b, id);
}
if (error == GIT_EPASSTHROUGH)
if (!error || error == GIT_EPASSTHROUGH)
return 0;
/*
* no backend could read only the header.
* try reading the whole object and freeing the contents
*/
if (error < 0) {
if ((error = git_odb_read(&object, db, id)) < GIT_SUCCESS)
return error; /* error already set - pass through */
*len_p = object->raw.len;
*type_p = object->raw.type;
git_odb_object_free(object);
}
if ((error = git_odb_read(&object, db, id)) < 0)
return error; /* error already set - pass along */
return GIT_SUCCESS;
*len_p = object->raw.len;
*type_p = object->raw.type;
git_odb_object_free(object);
return 0;
}
int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
......@@ -536,7 +533,7 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
*out = git_cache_get(&db->cache, id);
if (*out != NULL)
return GIT_SUCCESS;
return 0;
for (i = 0; i < db->backends.length && error < 0; ++i) {
backend_internal *internal = git_vector_get(&db->backends, i);
......@@ -546,15 +543,15 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
error = b->read(&raw.data, &raw.len, &raw.type, b, id);
}
if (error == GIT_EPASSTHROUGH || error == GIT_SUCCESS) {
*out = git_cache_try_store(&db->cache, new_odb_object(id, &raw));
return GIT_SUCCESS;
}
if (error && error != GIT_EPASSTHROUGH)
return error;
return git__rethrow(error, "Failed to read object");
*out = git_cache_try_store(&db->cache, new_odb_object(id, &raw));
return 0;
}
int git_odb_read_prefix(git_odb_object **out, git_odb *db, const git_oid *short_id, unsigned int len)
int git_odb_read_prefix(
git_odb_object **out, git_odb *db, const git_oid *short_id, unsigned int len)
{
unsigned int i;
int error = GIT_ENOTFOUND;
......@@ -565,7 +562,7 @@ int git_odb_read_prefix(git_odb_object **out, git_odb *db, const git_oid *short_
assert(out && db);
if (len < GIT_OID_MINPREFIXLEN)
return git__throw(GIT_EAMBIGUOUSOIDPREFIX, "Failed to lookup object. Prefix length is lower than %d.", GIT_OID_MINPREFIXLEN);
return git_odb__error_ambiguous("prefix length too short");
if (len > GIT_OID_HEXSZ)
len = GIT_OID_HEXSZ;
......@@ -573,7 +570,7 @@ int git_odb_read_prefix(git_odb_object **out, git_odb *db, const git_oid *short_
if (len == GIT_OID_HEXSZ) {
*out = git_cache_get(&db->cache, short_id);
if (*out != NULL)
return GIT_SUCCESS;
return 0;
}
for (i = 0; i < db->backends.length && found < 2; ++i) {
......@@ -582,33 +579,24 @@ int git_odb_read_prefix(git_odb_object **out, git_odb *db, const git_oid *short_
if (b->read != NULL) {
error = b->read_prefix(&full_oid, &raw.data, &raw.len, &raw.type, b, short_id, len);
switch (error) {
case GIT_SUCCESS:
if (!error)
found++;
break;
case GIT_ENOTFOUND:
case GIT_EPASSTHROUGH:
break;
case GIT_EAMBIGUOUSOIDPREFIX:
return git__rethrow(error, "Failed to read object. Ambiguous sha1 prefix");
default:
return git__rethrow(error, "Failed to read object");
}
else if (error != GIT_ENOTFOUND && error != GIT_EPASSTHROUGH)
return error;
}
}
if (found == 1) {
*out = git_cache_try_store(&db->cache, new_odb_object(&full_oid, &raw));
} else if (found > 1) {
return git__throw(GIT_EAMBIGUOUSOIDPREFIX, "Failed to read object. Ambiguous sha1 prefix");
} else {
return git__throw(GIT_ENOTFOUND, "Failed to read object. Object not found");
}
if (found == 0)
return git_odb__error_notfound("no match for prefix");
if (found > 1)
return git_odb__error_ambiguous("multiple matches for prefix");
return GIT_SUCCESS;
*out = git_cache_try_store(&db->cache, new_odb_object(&full_oid, &raw));
return 0;
}
int git_odb_write(git_oid *oid, git_odb *db, const void *data, size_t len, git_otype type)
int git_odb_write(
git_oid *oid, git_odb *db, const void *data, size_t len, git_otype type)
{
unsigned int i;
int error = GIT_ERROR;
......@@ -628,24 +616,25 @@ int git_odb_write(git_oid *oid, git_odb *db, const void *data, size_t len, git_o
error = b->write(oid, b, data, len, type);
}
if (error == GIT_EPASSTHROUGH || error == GIT_SUCCESS)
return GIT_SUCCESS;
if (!error || error == GIT_EPASSTHROUGH)
return 0;
/* if no backends were able to write the object directly, we try a streaming
* write to the backends; just write the whole object into the stream in one
* push */
if ((error = git_odb_open_wstream(&stream, db, len, type)) == GIT_SUCCESS) {
stream->write(stream, data, len);
error = stream->finalize_write(oid, stream);
stream->free(stream);
return GIT_SUCCESS;
}
if ((error = git_odb_open_wstream(&stream, db, len, type)) != 0)
return error;
return git__rethrow(error, "Failed to write object");
stream->write(stream, data, len);
error = stream->finalize_write(oid, stream);
stream->free(stream);
return error;
}
int git_odb_open_wstream(git_odb_stream **stream, git_odb *db, size_t size, git_otype type)
int git_odb_open_wstream(
git_odb_stream **stream, git_odb *db, size_t size, git_otype type)
{
unsigned int i;
int error = GIT_ERROR;
......@@ -666,10 +655,10 @@ int git_odb_open_wstream(git_odb_stream **stream, git_odb *db, size_t size, git_
error = init_fake_wstream(stream, b, size, type);
}
if (error == GIT_EPASSTHROUGH || error == GIT_SUCCESS)
return GIT_SUCCESS;
if (error == GIT_EPASSTHROUGH)
error = 0;
return git__rethrow(error, "Failed to open write stream");
return error;
}
int git_odb_open_rstream(git_odb_stream **stream, git_odb *db, const git_oid *oid)
......@@ -687,9 +676,21 @@ int git_odb_open_rstream(git_odb_stream **stream, git_odb *db, const git_oid *oi
error = b->readstream(stream, b, oid);
}
if (error == GIT_EPASSTHROUGH || error == GIT_SUCCESS)
return GIT_SUCCESS;
if (error == GIT_EPASSTHROUGH)
error = 0;
return git__rethrow(error, "Failed to open read stream");
return error;
}
int git_odb__error_notfound(const char *message)
{
giterr_set(GITERR_ODB, "Object not found - %s", message);
return GIT_ENOTFOUND;
}
int git_odb__error_ambiguous(const char *message)
{
giterr_set(GITERR_ODB, "Ambiguous SHA1 prefix - %s", message);
return GIT_EAMBIGUOUS;
}
......@@ -67,4 +67,14 @@ int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_otype type);
*/
int git_odb__hashlink(git_oid *out, const char *path);
/*
* Generate a GIT_ENOTFOUND error for the ODB.
*/
int git_odb__error_notfound(const char *message);
/*
* Generate a GIT_EAMBIGUOUS error for the ODB.
*/
int git_odb__error_ambiguous(const char *message);
#endif
......@@ -137,19 +137,19 @@ static int packfile_load__cb(void *_data, git_buf *path);
static int packfile_refresh_all(struct pack_backend *backend);
static int pack_entry_find(struct git_pack_entry *e,
struct pack_backend *backend, const git_oid *oid);
struct pack_backend *backend, const git_oid *oid);
/* Can find the offset of an object given
* a prefix of an identifier.
* Throws GIT_EAMBIGUOUSOIDPREFIX if short oid
* is ambiguous.
* Sets GIT_EAMBIGUOUS if short oid is ambiguous.
* This method assumes that len is between
* GIT_OID_MINPREFIXLEN and GIT_OID_HEXSZ.
*/
static int pack_entry_find_prefix(struct git_pack_entry *e,
struct pack_backend *backend,
const git_oid *short_oid,
unsigned int len);
static int pack_entry_find_prefix(
struct git_pack_entry *e,
struct pack_backend *backend,
const git_oid *short_oid,
unsigned int len);
......@@ -215,27 +215,22 @@ static int packfile_load__cb(void *_data, git_buf *path)
size_t i;
if (git__suffixcmp(path->ptr, ".idx") != 0)
return GIT_SUCCESS; /* not an index */
return 0; /* not an index */
for (i = 0; i < backend->packs.length; ++i) {
struct git_pack_file *p = git_vector_get(&backend->packs, i);
if (memcmp(p->pack_name, path->ptr, path->size - strlen(".idx")) == 0)
return GIT_SUCCESS;
return 0;
}
error = git_packfile_check(&pack, path->ptr);
if (error == GIT_ENOTFOUND) {
if (error == GIT_ENOTFOUND)
/* ignore missing .pack file as git does */
return GIT_SUCCESS;
} else if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to load packfile");
if (git_vector_insert(&backend->packs, pack) < GIT_SUCCESS) {
git__free(pack);
return GIT_ENOMEM;
}
else if (error < 0)
return error;
return GIT_SUCCESS;
return git_vector_insert(&backend->packs, pack);
}
static int packfile_refresh_all(struct pack_backend *backend)
......@@ -244,10 +239,10 @@ static int packfile_refresh_all(struct pack_backend *backend)
struct stat st;
if (backend->pack_folder == NULL)
return GIT_SUCCESS;
return 0;
if (p_stat(backend->pack_folder, &st) < 0 || !S_ISDIR(st.st_mode))
return git__throw(GIT_ENOTFOUND, "Failed to refresh packfiles. Backend not found");
return git_odb__error_notfound("failed to refresh packfiles");
if (st.st_mtime != backend->pack_folder_mtime) {
git_buf path = GIT_BUF_INIT;
......@@ -257,14 +252,15 @@ static int packfile_refresh_all(struct pack_backend *backend)
error = git_path_direach(&path, packfile_load__cb, (void *)backend);
git_buf_free(&path);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to refresh packfiles");
if (error < 0)
return error;
git_vector_sort(&backend->packs);
backend->pack_folder_mtime = st.st_mtime;
}
return GIT_SUCCESS;
return 0;
}
static int pack_entry_find(struct git_pack_entry *e, struct pack_backend *backend, const git_oid *oid)
......@@ -272,12 +268,12 @@ static int pack_entry_find(struct git_pack_entry *e, struct pack_backend *backen
int error;
size_t i;
if ((error = packfile_refresh_all(backend)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to find pack entry");
if ((error = packfile_refresh_all(backend)) < 0)
return error;
if (backend->last_found &&
git_pack_entry_find(e, backend->last_found, oid, GIT_OID_HEXSZ) == GIT_SUCCESS)
return GIT_SUCCESS;
git_pack_entry_find(e, backend->last_found, oid, GIT_OID_HEXSZ) == 0)
return 0;
for (i = 0; i < backend->packs.length; ++i) {
struct git_pack_file *p;
......@@ -286,13 +282,13 @@ static int pack_entry_find(struct git_pack_entry *e, struct pack_backend *backen
if (p == backend->last_found)
continue;
if (git_pack_entry_find(e, p, oid, GIT_OID_HEXSZ) == GIT_SUCCESS) {
if (git_pack_entry_find(e, p, oid, GIT_OID_HEXSZ) == 0) {
backend->last_found = p;
return GIT_SUCCESS;
return 0;
}
}
return git__throw(GIT_ENOTFOUND, "Failed to find pack entry");
return git_odb__error_notfound("failed to find pack entry");
}
static int pack_entry_find_prefix(
......@@ -305,16 +301,15 @@ static int pack_entry_find_prefix(
size_t i;
unsigned found = 0;
if ((error = packfile_refresh_all(backend)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to find pack entry");
if ((error = packfile_refresh_all(backend)) < 0)
return error;
if (backend->last_found) {
error = git_pack_entry_find(e, backend->last_found, short_oid, len);
if (error == GIT_EAMBIGUOUSOIDPREFIX) {
return git__rethrow(error, "Failed to find pack entry. Ambiguous sha1 prefix");
} else if (error == GIT_SUCCESS) {
if (error == GIT_EAMBIGUOUS)
return error;
if (!error)
found = 1;
}
}
for (i = 0; i < backend->packs.length; ++i) {
......@@ -325,24 +320,21 @@ static int pack_entry_find_prefix(
continue;
error = git_pack_entry_find(e, p, short_oid, len);
if (error == GIT_EAMBIGUOUSOIDPREFIX) {
return git__rethrow(error, "Failed to find pack entry. Ambiguous sha1 prefix");
} else if (error == GIT_SUCCESS) {
found++;
if (found > 1)
if (error == GIT_EAMBIGUOUS)
return error;
if (!error) {
if (++found > 1)
break;
backend->last_found = p;
}
}
if (!found) {
return git__rethrow(GIT_ENOTFOUND, "Failed to find pack entry");
} else if (found > 1) {
return git__rethrow(GIT_EAMBIGUOUSOIDPREFIX, "Failed to find pack entry. Ambiguous sha1 prefix");
} else {
return GIT_SUCCESS;
}
if (!found)
return git_odb__error_notfound("failed to find pack entry");
else if (found > 1)
return git_odb__error_ambiguous("found multiple pack entries");
else
return 0;
}
......@@ -374,17 +366,15 @@ static int pack_backend__read(void **buffer_p, size_t *len_p, git_otype *type_p,
git_rawobj raw;
int error;
if ((error = pack_entry_find(&e, (struct pack_backend *)backend, oid)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to read pack backend");
if ((error = git_packfile_unpack(&raw, e.p, &e.offset)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to read pack backend");
if ((error = pack_entry_find(&e, (struct pack_backend *)backend, oid)) < 0 ||
(error = git_packfile_unpack(&raw, e.p, &e.offset)) < 0)
return error;
*buffer_p = raw.data;
*len_p = raw.len;
*type_p = raw.type;
return GIT_SUCCESS;
return 0;
}
static int pack_backend__read_prefix(
......@@ -396,40 +386,38 @@ static int pack_backend__read_prefix(
const git_oid *short_oid,
unsigned int len)
{
int error = 0;
if (len < GIT_OID_MINPREFIXLEN)
return git__throw(GIT_EAMBIGUOUSOIDPREFIX, "Failed to read pack backend. Prefix length is lower than %d.", GIT_OID_MINPREFIXLEN);
error = git_odb__error_ambiguous("prefix length too short");
if (len >= GIT_OID_HEXSZ) {
else if (len >= GIT_OID_HEXSZ) {
/* We can fall back to regular read method */
int error = pack_backend__read(buffer_p, len_p, type_p, backend, short_oid);
if (error == GIT_SUCCESS)
error = pack_backend__read(buffer_p, len_p, type_p, backend, short_oid);
if (!error)
git_oid_cpy(out_oid, short_oid);
return error;
} else {
struct git_pack_entry e;
git_rawobj raw;
int error;
if ((error = pack_entry_find_prefix(&e, (struct pack_backend *)backend, short_oid, len)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to read pack backend");
if ((error = git_packfile_unpack(&raw, e.p, &e.offset)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to read pack backend");
*buffer_p = raw.data;
*len_p = raw.len;
*type_p = raw.type;
git_oid_cpy(out_oid, &e.sha1);
if ((error = pack_entry_find_prefix(
&e, (struct pack_backend *)backend, short_oid, len)) == 0 &&
(error = git_packfile_unpack(&raw, e.p, &e.offset)) == 0)
{
*buffer_p = raw.data;
*len_p = raw.len;
*type_p = raw.type;
git_oid_cpy(out_oid, &e.sha1);
}
}
return GIT_SUCCESS;
return error;
}
static int pack_backend__exists(git_odb_backend *backend, const git_oid *oid)
{
struct git_pack_entry e;
return pack_entry_find(&e, (struct pack_backend *)backend, oid) == GIT_SUCCESS;
return pack_entry_find(&e, (struct pack_backend *)backend, oid) == 0;
}
static void pack_backend__free(git_odb_backend *_backend)
......@@ -455,19 +443,16 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
{
struct pack_backend *backend = NULL;
git_buf path = GIT_BUF_INIT;
int error = GIT_SUCCESS;
backend = git__calloc(1, sizeof(struct pack_backend));
if (backend == NULL)
return GIT_ENOMEM;
error = git_vector_init(&backend->packs, 8, packfile_sort__cb);
if (error < GIT_SUCCESS)
goto cleanup;
GITERR_CHECK_ALLOC(backend);
error = git_buf_joinpath(&path, objects_dir, "pack");
if (error < GIT_SUCCESS)
goto cleanup;
if (git_vector_init(&backend->packs, 8, packfile_sort__cb) < 0 ||
git_buf_joinpath(&path, objects_dir, "pack") < 0)
{
git__free(backend);
return -1;
}
if (git_path_isdir(git_buf_cstr(&path)) == true) {
backend->pack_folder = git_buf_detach(&path);
......@@ -482,10 +467,7 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
*backend_out = (git_odb_backend *)backend;
cleanup:
if (error < GIT_SUCCESS)
git__free(backend);
git_buf_free(&path);
return error;
return 0;
}
......@@ -70,7 +70,7 @@ struct git_pack_file {
};
struct git_pack_entry {
off_t offset;
git_off_t offset;
git_oid sha1;
struct git_pack_file *p;
};
......@@ -80,13 +80,13 @@ int git_packfile_unpack_header(
git_otype *type_p,
git_mwindow_file *mwf,
git_mwindow **w_curs,
off_t *curpos);
git_off_t *curpos);
int git_packfile_unpack(git_rawobj *obj, struct git_pack_file *p, off_t *obj_offset);
int git_packfile_unpack(git_rawobj *obj, struct git_pack_file *p, git_off_t *obj_offset);
off_t get_delta_base(struct git_pack_file *p, git_mwindow **w_curs,
off_t *curpos, git_otype type,
off_t delta_obj_offset);
git_off_t get_delta_base(struct git_pack_file *p, git_mwindow **w_curs,
git_off_t *curpos, git_otype type,
git_off_t delta_obj_offset);
void packfile_free(struct git_pack_file *p);
int git_packfile_check(struct git_pack_file **pack_out, const char *path);
......
......@@ -842,7 +842,7 @@ static int reference_path_available(
if (!data.available) {
giterr_set(GITERR_REFERENCE,
"The path to reference '%s' collides with an existing one");
"The path to reference '%s' collides with an existing one", ref);
return -1;
}
......@@ -902,7 +902,7 @@ static int reference_can_write(
* the rename; the existing one would be overwritten */
if (exists) {
giterr_set(GITERR_REFERENCE,
"A reference with that name (%s) already exists");
"A reference with that name (%s) already exists", refname);
return GIT_EEXISTS;
}
}
......
......@@ -17,12 +17,8 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs
int mprot = 0;
int mflag = 0;
assert((out != NULL) && (len > 0));
if ((out == NULL) || (len == 0)) {
errno = EINVAL;
return git__throw(GIT_ERROR, "Failed to mmap. No map or zero length");
}
if (validate_map_args(out, len, prot, flags, fd, offset) < 0)
return -1;
out->data = NULL;
out->len = 0;
......@@ -31,39 +27,28 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs
mprot = PROT_WRITE;
else if (prot & GIT_PROT_READ)
mprot = PROT_READ;
else {
errno = EINVAL;
return git__throw(GIT_ERROR, "Failed to mmap. Invalid protection parameters");
}
if ((flags & GIT_MAP_TYPE) == GIT_MAP_SHARED)
mflag = MAP_SHARED;
else if ((flags & GIT_MAP_TYPE) == GIT_MAP_PRIVATE)
mflag = MAP_PRIVATE;
if (flags & GIT_MAP_FIXED) {
errno = EINVAL;
return git__throw(GIT_ERROR, "Failed to mmap. FIXED not set");
out->data = mmap(NULL, len, mprot, mflag, fd, offset);
if (!out->data || out->data == MAP_FAILED) {
giterr_set(GITERR_OS, "Failed to mmap. Could not write data");
return -1;
}
out->data = mmap(NULL, len, mprot, mflag, fd, offset);
if (!out->data || out->data == MAP_FAILED)
return git__throw(GIT_EOSERR, "Failed to mmap. Could not write data");
out->len = len;
return GIT_SUCCESS;
return 0;
}
int p_munmap(git_map *map)
{
assert(map != NULL);
if (!map)
return git__throw(GIT_ERROR, "Failed to munmap. Map does not exist");
munmap(map->data, map->len);
return GIT_SUCCESS;
return 0;
}
#endif
......
......@@ -33,12 +33,8 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs
git_off_t page_start;
git_off_t page_offset;
assert((out != NULL) && (len > 0));
if ((out == NULL) || (len == 0)) {
errno = EINVAL;
return git__throw(GIT_ERROR, "Failed to mmap. No map or zero length");
}
if (validate_map_args(out, len, prot, flags, fd, offset) < 0)
return -1;
out->data = NULL;
out->len = 0;
......@@ -46,86 +42,75 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs
if (fh == INVALID_HANDLE_VALUE) {
errno = EBADF;
return git__throw(GIT_ERROR, "Failed to mmap. Invalid handle value");
giterr_set(GITERR_OS, "Failed to mmap. Invalid handle value");
return -1;
}
if (prot & GIT_PROT_WRITE)
fmap_prot |= PAGE_READWRITE;
else if (prot & GIT_PROT_READ)
fmap_prot |= PAGE_READONLY;
else {
errno = EINVAL;
return git__throw(GIT_ERROR, "Failed to mmap. Invalid protection parameters");
}
if (prot & GIT_PROT_WRITE)
view_prot |= FILE_MAP_WRITE;
if (prot & GIT_PROT_READ)
view_prot |= FILE_MAP_READ;
if (flags & GIT_MAP_FIXED) {
errno = EINVAL;
return git__throw(GIT_ERROR, "Failed to mmap. FIXED not set");
}
page_start = (offset / page_size) * page_size;
page_offset = offset - page_start;
if (page_offset != 0) { /* offset must be multiple of page size */
errno = EINVAL;
return git__throw(GIT_ERROR, "Failed to mmap. Offset must be multiple of page size");
giterr_set(GITERR_OS, "Failed to mmap. Offset must be multiple of page size");
return -1;
}
out->fmh = CreateFileMapping(fh, NULL, fmap_prot, 0, 0, NULL);
if (!out->fmh || out->fmh == INVALID_HANDLE_VALUE) {
/* errno = ? */
giterr_set(GITERR_OS, "Failed to mmap. Invalid handle value");
out->fmh = NULL;
return git__throw(GIT_ERROR, "Failed to mmap. Invalid handle value");
return -1;
}
assert(sizeof(git_off_t) == 8);
off_low = (DWORD)(page_start);
off_hi = (DWORD)(page_start >> 32);
out->data = MapViewOfFile(out->fmh, view_prot, off_hi, off_low, len);
if (!out->data) {
/* errno = ? */
giterr_set(GITERR_OS, "Failed to mmap. No data written");
CloseHandle(out->fmh);
out->fmh = NULL;
return git__throw(GIT_ERROR, "Failed to mmap. No data written");
return -1;
}
out->len = len;
return GIT_SUCCESS;
return 0;
}
int p_munmap(git_map *map)
{
assert(map != NULL);
int error = 0;
if (!map)
return git__throw(GIT_ERROR, "Failed to munmap. Map does not exist");
assert(map != NULL);
if (map->data) {
if (!UnmapViewOfFile(map->data)) {
/* errno = ? */
CloseHandle(map->fmh);
map->data = NULL;
map->fmh = NULL;
return git__throw(GIT_ERROR, "Failed to munmap. Could not unmap view of file");
giterr_set(GITERR_OS, "Failed to munmap. Could not unmap view of file");
error = -1;
}
map->data = NULL;
}
if (map->fmh) {
if (!CloseHandle(map->fmh)) {
/* errno = ? */
map->fmh = NULL;
return git__throw(GIT_ERROR, "Failed to munmap. Could not close handle");
giterr_set(GITERR_OS, "Failed to munmap. Could not close handle");
error = -1;
}
map->fmh = NULL;
}
return GIT_SUCCESS;
return error;
}
/ < 0)
/*
* Copyright (C) 2009-2012 the libgit2 contributors
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
......@@ -339,7 +339,7 @@ int p_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr)
int len;
if (count == 0 || (len = _vsnprintf(buffer, count, format, argptr)) < 0)
return p_vscprintf(format, argptr);
return _vscprintf(format, argptr);
return len;
#else /* MinGW */
......
......@@ -15,7 +15,7 @@ struct attr_expected {
const char *expected_str;
};
static inline void attr_check_expected(
GIT_INLINE(void) attr_check_expected(
enum attr_expect_t expected,
const char *expected_str,
const char *value)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment