Commit dda708e7 by Vicent Martí

error-handling: On-disk config file backend

Includes:

	- Proper error reporting when encountering syntax errors in a
	config file (file, line number, column).

	- Rewritten `config_write`, now with 99% less goto-spaghetti

	- Error state in `git_filebuf`: filebuf write functions no longer
	need to be checked for error returns. If any of the writes performed
	on a buffer fail, the last call to `git_filebuf_commit` or
	`git_filebuf_hash` will fail accordingly and set the appropiate error
	message. Baller!
parent 6af24ce3
...@@ -127,14 +127,9 @@ typedef enum { ...@@ -127,14 +127,9 @@ typedef enum {
GITERR_ZLIB, GITERR_ZLIB,
GITERR_REPOSITORY, GITERR_REPOSITORY,
GITERR_CONFIG, GITERR_CONFIG,
GITERR_REGEX,
} git_error_class; } git_error_class;
#define GITERR_CHECK_ALLOC(ptr) if (ptr == NULL) { return -1; }
GIT_EXTERN(void) giterr_set_oom(void);
GIT_EXTERN(void) giterr_set(int error_class, const char *string, ...);
GIT_EXTERN(void) giterr_clear(void);
/** /**
* Return a detailed error string with the latest error * Return a detailed error string with the latest error
* that occurred in the library. * that occurred in the library.
......
...@@ -46,6 +46,8 @@ ...@@ -46,6 +46,8 @@
#include "thread-utils.h" #include "thread-utils.h"
#include "bswap.h" #include "bswap.h"
#include <regex.h>
extern void git___throw(const char *, ...) GIT_FORMAT_PRINTF(1, 2); extern void git___throw(const char *, ...) GIT_FORMAT_PRINTF(1, 2);
#define git__throw(error, ...) \ #define git__throw(error, ...) \
(git___throw(__VA_ARGS__), error) (git___throw(__VA_ARGS__), error)
...@@ -54,6 +56,16 @@ extern void git___rethrow(const char *, ...) GIT_FORMAT_PRINTF(1, 2); ...@@ -54,6 +56,16 @@ extern void git___rethrow(const char *, ...) GIT_FORMAT_PRINTF(1, 2);
#define git__rethrow(error, ...) \ #define git__rethrow(error, ...) \
(git___rethrow(__VA_ARGS__), error) (git___rethrow(__VA_ARGS__), error)
#define GITERR_CHECK_ALLOC(ptr) if (ptr == NULL) { return -1; }
void giterr_set_oom(void);
void giterr_set(int error_class, const char *string, ...);
void giterr_clear(void);
void giterr_set_str(int error_class, const char *string);
void giterr_set_regex(const regex_t *regex, int error_code);
#include "util.h" #include "util.h"
......
...@@ -401,13 +401,15 @@ int git_config_get_string(git_config *cfg, const char *name, const char **out) ...@@ -401,13 +401,15 @@ int git_config_get_string(git_config *cfg, const char *name, const char **out)
if (ret == 0) if (ret == 0)
return 0; return 0;
/* File backend doesn't set error message on variable
* not found */
if (ret == GIT_ENOTFOUND) if (ret == GIT_ENOTFOUND)
continue; continue;
return ret; return ret;
} }
giterr_set(GITERR_CONFIG, "Config value '%s' not found", name); giterr_set(GITERR_CONFIG, "Config variable '%s' not found", name);
return GIT_ENOTFOUND; return GIT_ENOTFOUND;
} }
......
...@@ -122,25 +122,28 @@ void giterr_set(int error_class, const char *string, ...) ...@@ -122,25 +122,28 @@ void giterr_set(int error_class, const char *string, ...)
{ {
char error_str[1024]; char error_str[1024];
va_list arglist; va_list arglist;
git_error *error;
const char *oserr =
(error_class == GITERR_OS && errno != 0) ? strerror(errno) : NULL;
error = &GIT_GLOBAL->error_t;
free(error->message);
va_start(arglist, string); va_start(arglist, string);
p_vsnprintf(error_str, sizeof(error_str), string, arglist); p_vsnprintf(error_str, sizeof(error_str), string, arglist);
va_end(arglist); va_end(arglist);
/* automatically suffix strerror(errno) for GITERR_OS errors */ /* automatically suffix strerror(errno) for GITERR_OS errors */
if (oserr != NULL) { if (error_class == GITERR_OS) {
strncat(error_str, ": ", sizeof(error_str)); strncat(error_str, ": ", sizeof(error_str));
strncat(error_str, oserr, sizeof(error_str)); strncat(error_str, strerror(errno), sizeof(error_str));
errno = 0; errno = 0;
} }
error->message = git__strdup(error_str); giterr_set_str(error_class, error_str);
}
void giterr_set_str(int error_class, const char *string)
{
git_error *error = &GIT_GLOBAL->error_t;
free(error->message);
error->message = git__strdup(string);
error->klass = error_class; error->klass = error_class;
if (error->message == NULL) { if (error->message == NULL) {
...@@ -151,6 +154,13 @@ void giterr_set(int error_class, const char *string, ...) ...@@ -151,6 +154,13 @@ void giterr_set(int error_class, const char *string, ...)
GIT_GLOBAL->last_error = error; GIT_GLOBAL->last_error = error;
} }
void giterr_set_regex(const regex_t *regex, int error_code)
{
char error_buf[1024];
regerror(error_code, regex, error_buf, sizeof(error_buf));
giterr_set_str(GITERR_REGEX, error_buf);
}
void giterr_clear(void) void giterr_clear(void)
{ {
GIT_GLOBAL->last_error = NULL; GIT_GLOBAL->last_error = NULL;
......
...@@ -14,6 +14,36 @@ ...@@ -14,6 +14,36 @@
static const size_t WRITE_BUFFER_SIZE = (4096 * 2); static const size_t WRITE_BUFFER_SIZE = (4096 * 2);
enum buferr_t {
BUFERR_OK = 0,
BUFERR_WRITE,
BUFERR_ZLIB,
BUFERR_MEM
};
#define ENSURE_BUF_OK(buf) if ((buf)->last_error != BUFERR_OK) { return -1; }
static int verify_last_error(git_filebuf *file)
{
switch (file->last_error) {
case BUFERR_WRITE:
giterr_set(GITERR_OS, "Failed to write out file");
return -1;
case BUFERR_MEM:
giterr_set_oom();
return -1;
case BUFERR_ZLIB:
giterr_set(GITERR_ZLIB,
"Buffer error when writing out ZLib data");
return -1;
default:
return 0;
}
}
static int lock_file(git_filebuf *file, int flags) static int lock_file(git_filebuf *file, int flags)
{ {
if (git_path_exists(file->path_lock) == true) { if (git_path_exists(file->path_lock) == true) {
...@@ -100,20 +130,21 @@ GIT_INLINE(int) flush_buffer(git_filebuf *file) ...@@ -100,20 +130,21 @@ GIT_INLINE(int) flush_buffer(git_filebuf *file)
static int write_normal(git_filebuf *file, void *source, size_t len) static int write_normal(git_filebuf *file, void *source, size_t len)
{ {
int result = 0;
if (len > 0) { if (len > 0) {
result = p_write(file->fd, (void *)source, len); if (p_write(file->fd, (void *)source, len) < 0) {
file->last_error = BUFERR_WRITE;
return -1;
}
if (file->digest) if (file->digest)
git_hash_update(file->digest, source, len); git_hash_update(file->digest, source, len);
} }
return result; return 0;
} }
static int write_deflate(git_filebuf *file, void *source, size_t len) static int write_deflate(git_filebuf *file, void *source, size_t len)
{ {
int result = Z_OK;
z_stream *zs = &file->zs; z_stream *zs = &file->zs;
if (len > 0 || file->flush_mode == Z_FINISH) { if (len > 0 || file->flush_mode == Z_FINISH) {
...@@ -126,14 +157,17 @@ static int write_deflate(git_filebuf *file, void *source, size_t len) ...@@ -126,14 +157,17 @@ static int write_deflate(git_filebuf *file, void *source, size_t len)
zs->next_out = file->z_buf; zs->next_out = file->z_buf;
zs->avail_out = (uInt)file->buf_size; zs->avail_out = (uInt)file->buf_size;
result = deflate(zs, file->flush_mode); if (deflate(zs, file->flush_mode) == Z_STREAM_ERROR) {
if (result == Z_STREAM_ERROR) file->last_error = BUFERR_ZLIB;
return git__throw(GIT_ERROR, "Failed to deflate input"); return -1;
}
have = file->buf_size - (size_t)zs->avail_out; have = file->buf_size - (size_t)zs->avail_out;
if (p_write(file->fd, file->z_buf, have) < GIT_SUCCESS) if (p_write(file->fd, file->z_buf, have) < 0) {
return git__throw(GIT_EOSERR, "Failed to write to file"); file->last_error = BUFERR_WRITE;
return -1;
}
} while (zs->avail_out == 0); } while (zs->avail_out == 0);
...@@ -143,7 +177,7 @@ static int write_deflate(git_filebuf *file, void *source, size_t len) ...@@ -143,7 +177,7 @@ static int write_deflate(git_filebuf *file, void *source, size_t len)
git_hash_update(file->digest, source, len); git_hash_update(file->digest, source, len);
} }
return GIT_SUCCESS; return 0;
} }
int git_filebuf_open(git_filebuf *file, const char *path, int flags) int git_filebuf_open(git_filebuf *file, const char *path, int flags)
...@@ -161,6 +195,7 @@ int git_filebuf_open(git_filebuf *file, const char *path, int flags) ...@@ -161,6 +195,7 @@ int git_filebuf_open(git_filebuf *file, const char *path, int flags)
file->buf_size = WRITE_BUFFER_SIZE; file->buf_size = WRITE_BUFFER_SIZE;
file->buf_pos = 0; file->buf_pos = 0;
file->fd = -1; file->fd = -1;
file->last_error = BUFERR_OK;
/* Allocate the main cache buffer */ /* Allocate the main cache buffer */
file->buffer = git__malloc(file->buf_size); file->buffer = git__malloc(file->buf_size);
...@@ -237,58 +272,61 @@ cleanup: ...@@ -237,58 +272,61 @@ cleanup:
int git_filebuf_hash(git_oid *oid, git_filebuf *file) int git_filebuf_hash(git_oid *oid, git_filebuf *file)
{ {
int error;
assert(oid && file && file->digest); assert(oid && file && file->digest);
if ((error = flush_buffer(file)) < GIT_SUCCESS) flush_buffer(file);
return git__rethrow(error, "Failed to get hash for file");
if (verify_last_error(file) < 0)
return -1;
git_hash_final(oid, file->digest); git_hash_final(oid, file->digest);
git_hash_free_ctx(file->digest); git_hash_free_ctx(file->digest);
file->digest = NULL; file->digest = NULL;
return GIT_SUCCESS; return 0;
} }
int git_filebuf_commit_at(git_filebuf *file, const char *path, mode_t mode) int git_filebuf_commit_at(git_filebuf *file, const char *path, mode_t mode)
{ {
git__free(file->path_original); git__free(file->path_original);
file->path_original = git__strdup(path); file->path_original = git__strdup(path);
if (file->path_original == NULL) GITERR_CHECK_ALLOC(file->path_original);
return GIT_ENOMEM;
return git_filebuf_commit(file, mode); return git_filebuf_commit(file, mode);
} }
int git_filebuf_commit(git_filebuf *file, mode_t mode) int git_filebuf_commit(git_filebuf *file, mode_t mode)
{ {
int error;
/* temporary files cannot be committed */ /* temporary files cannot be committed */
assert(file && file->path_original); assert(file && file->path_original);
file->flush_mode = Z_FINISH; file->flush_mode = Z_FINISH;
if ((error = flush_buffer(file)) < GIT_SUCCESS) flush_buffer(file);
goto cleanup;
if (verify_last_error(file) < 0)
goto on_error;
p_close(file->fd); p_close(file->fd);
file->fd = -1; file->fd = -1;
if (p_chmod(file->path_lock, mode)) { if (p_chmod(file->path_lock, mode)) {
error = git__throw(GIT_EOSERR, "Failed to chmod locked file before committing"); giterr_set(GITERR_OS, "Failed to set attributes for file at '%s'", file->path_lock);
goto cleanup; goto on_error;
} }
p_unlink(file->path_original); p_unlink(file->path_original);
error = p_rename(file->path_lock, file->path_original); if (p_rename(file->path_lock, file->path_original) < 0) {
giterr_set(GITERR_OS, "Failed to rename lockfile to '%s'", file->path_original);
goto on_error;
}
cleanup:
git_filebuf_cleanup(file); git_filebuf_cleanup(file);
if (error < GIT_SUCCESS) return 0;
return git__rethrow(error, "Failed to commit locked file from buffer");
return GIT_SUCCESS; on_error:
git_filebuf_cleanup(file);
return -1;
} }
GIT_INLINE(void) add_to_cache(git_filebuf *file, const void *buf, size_t len) GIT_INLINE(void) add_to_cache(git_filebuf *file, const void *buf, size_t len)
...@@ -299,22 +337,22 @@ GIT_INLINE(void) add_to_cache(git_filebuf *file, const void *buf, size_t len) ...@@ -299,22 +337,22 @@ GIT_INLINE(void) add_to_cache(git_filebuf *file, const void *buf, size_t len)
int git_filebuf_write(git_filebuf *file, const void *buff, size_t len) int git_filebuf_write(git_filebuf *file, const void *buff, size_t len)
{ {
int error;
const unsigned char *buf = buff; const unsigned char *buf = buff;
ENSURE_BUF_OK(file);
for (;;) { for (;;) {
size_t space_left = file->buf_size - file->buf_pos; size_t space_left = file->buf_size - file->buf_pos;
/* cache if it's small */ /* cache if it's small */
if (space_left > len) { if (space_left > len) {
add_to_cache(file, buf, len); add_to_cache(file, buf, len);
return GIT_SUCCESS; return 0;
} }
add_to_cache(file, buf, space_left); add_to_cache(file, buf, space_left);
if (flush_buffer(file) < 0)
if ((error = flush_buffer(file)) < GIT_SUCCESS) return -1;
return git__rethrow(error, "Failed to write to buffer");
len -= space_left; len -= space_left;
buf += space_left; buf += space_left;
...@@ -323,32 +361,37 @@ int git_filebuf_write(git_filebuf *file, const void *buff, size_t len) ...@@ -323,32 +361,37 @@ int git_filebuf_write(git_filebuf *file, const void *buff, size_t len)
int git_filebuf_reserve(git_filebuf *file, void **buffer, size_t len) int git_filebuf_reserve(git_filebuf *file, void **buffer, size_t len)
{ {
int error;
size_t space_left = file->buf_size - file->buf_pos; size_t space_left = file->buf_size - file->buf_pos;
*buffer = NULL; *buffer = NULL;
if (len > file->buf_size) ENSURE_BUF_OK(file);
return GIT_ENOMEM;
if (len > file->buf_size) {
file->last_error = BUFERR_MEM;
return -1;
}
if (space_left <= len) { if (space_left <= len) {
if ((error = flush_buffer(file)) < GIT_SUCCESS) if (flush_buffer(file) < 0)
return git__rethrow(error, "Failed to reserve buffer"); return -1;
} }
*buffer = (file->buffer + file->buf_pos); *buffer = (file->buffer + file->buf_pos);
file->buf_pos += len; file->buf_pos += len;
return GIT_SUCCESS; return 0;
} }
int git_filebuf_printf(git_filebuf *file, const char *format, ...) int git_filebuf_printf(git_filebuf *file, const char *format, ...)
{ {
va_list arglist; va_list arglist;
size_t space_left; size_t space_left;
int len, error; int len, res;
char *tmp_buffer; char *tmp_buffer;
ENSURE_BUF_OK(file);
space_left = file->buf_size - file->buf_pos; space_left = file->buf_size - file->buf_pos;
do { do {
...@@ -356,24 +399,28 @@ int git_filebuf_printf(git_filebuf *file, const char *format, ...) ...@@ -356,24 +399,28 @@ int git_filebuf_printf(git_filebuf *file, const char *format, ...)
len = p_vsnprintf((char *)file->buffer + file->buf_pos, space_left, format, arglist); len = p_vsnprintf((char *)file->buffer + file->buf_pos, space_left, format, arglist);
va_end(arglist); va_end(arglist);
if (len < 0) if (len < 0) {
return git__throw(GIT_EOSERR, "Failed to format string"); file->last_error = BUFERR_MEM;
return -1;
}
if ((size_t)len + 1 <= space_left) { if ((size_t)len + 1 <= space_left) {
file->buf_pos += len; file->buf_pos += len;
return GIT_SUCCESS; return 0;
} }
if ((error = flush_buffer(file)) < GIT_SUCCESS) if (flush_buffer(file) < 0)
return git__rethrow(error, "Failed to output to buffer"); return -1;
space_left = file->buf_size - file->buf_pos; space_left = file->buf_size - file->buf_pos;
} while ((size_t)len + 1 <= space_left); } while ((size_t)len + 1 <= space_left);
tmp_buffer = git__malloc(len + 1); tmp_buffer = git__malloc(len + 1);
if (!tmp_buffer) if (!tmp_buffer) {
return GIT_ENOMEM; file->last_error = BUFERR_MEM;
return -1;
}
va_start(arglist, format); va_start(arglist, format);
len = p_vsnprintf(tmp_buffer, len + 1, format, arglist); len = p_vsnprintf(tmp_buffer, len + 1, format, arglist);
...@@ -381,12 +428,13 @@ int git_filebuf_printf(git_filebuf *file, const char *format, ...) ...@@ -381,12 +428,13 @@ int git_filebuf_printf(git_filebuf *file, const char *format, ...)
if (len < 0) { if (len < 0) {
git__free(tmp_buffer); git__free(tmp_buffer);
return git__throw(GIT_EOSERR, "Failed to format string"); file->last_error = BUFERR_MEM;
return -1;
} }
error = git_filebuf_write(file, tmp_buffer, len); res = git_filebuf_write(file, tmp_buffer, len);
git__free(tmp_buffer); git__free(tmp_buffer);
return error; return res;
} }
...@@ -40,25 +40,35 @@ struct git_filebuf { ...@@ -40,25 +40,35 @@ struct git_filebuf {
size_t buf_size, buf_pos; size_t buf_size, buf_pos;
git_file fd; git_file fd;
int last_error;
}; };
typedef struct git_filebuf git_filebuf; typedef struct git_filebuf git_filebuf;
#define GIT_FILEBUF_INIT {0} #define GIT_FILEBUF_INIT {0}
/* The git_filebuf object lifecycle is: /*
* The git_filebuf object lifecycle is:
* - Allocate git_filebuf, preferably using GIT_FILEBUF_INIT. * - Allocate git_filebuf, preferably using GIT_FILEBUF_INIT.
*
* - Call git_filebuf_open() to initialize the filebuf for use. * - Call git_filebuf_open() to initialize the filebuf for use.
*
* - Make as many calls to git_filebuf_write(), git_filebuf_printf(), * - Make as many calls to git_filebuf_write(), git_filebuf_printf(),
* git_filebuf_reserve() as you like. * git_filebuf_reserve() as you like. The error codes for these
* functions don't need to be checked. They are stored internally
* by the file buffer.
*
* - While you are writing, you may call git_filebuf_hash() to get * - While you are writing, you may call git_filebuf_hash() to get
* the hash of all you have written so far. * the hash of all you have written so far. This function will
* fail if any of the previous writes to the buffer failed.
*
* - To close the git_filebuf, you may call git_filebuf_commit() or * - To close the git_filebuf, you may call git_filebuf_commit() or
* git_filebuf_commit_at() to save the file, or * git_filebuf_commit_at() to save the file, or
* git_filebuf_cleanup() to abandon the file. All of these will * git_filebuf_cleanup() to abandon the file. All of these will
* clear the git_filebuf object. * free the git_filebuf object. Likewise, all of these will fail
* if any of the previous writes to the buffer failed, and set
* an error code accordingly.
*/ */
int git_filebuf_write(git_filebuf *lock, const void *buff, size_t len); int git_filebuf_write(git_filebuf *lock, const void *buff, size_t len);
int git_filebuf_reserve(git_filebuf *file, void **buff, size_t len); int git_filebuf_reserve(git_filebuf *file, void **buff, size_t len);
int git_filebuf_printf(git_filebuf *file, const char *format, ...) GIT_FORMAT_PRINTF(2, 3); int git_filebuf_printf(git_filebuf *file, const char *format, ...) GIT_FORMAT_PRINTF(2, 3);
......
...@@ -227,11 +227,11 @@ int git_hashtable_remove2(git_hashtable *self, const void *key, void **old_value ...@@ -227,11 +227,11 @@ int git_hashtable_remove2(git_hashtable *self, const void *key, void **old_value
node->key = NULL; node->key = NULL;
node->value = NULL; node->value = NULL;
self->key_count--; self->key_count--;
return GIT_SUCCESS; return 0;
} }
} }
return git__throw(GIT_ENOTFOUND, "Entry not found in hash table"); return GIT_ENOTFOUND;
} }
int git_hashtable_merge(git_hashtable *self, git_hashtable *other) int git_hashtable_merge(git_hashtable *self, git_hashtable *other)
......
...@@ -31,10 +31,9 @@ int p_getcwd(char *buffer_out, size_t size) ...@@ -31,10 +31,9 @@ int p_getcwd(char *buffer_out, size_t size)
cwd_buffer = getcwd(buffer_out, size); cwd_buffer = getcwd(buffer_out, size);
if (cwd_buffer == NULL) if (cwd_buffer == NULL)
return git__throw(GIT_EOSERR, "Failed to retrieve current working directory"); return -1;
git_path_mkposix(buffer_out); git_path_mkposix(buffer_out);
git_path_string_to_dir(buffer_out, size); //Ensure the path ends with a trailing slash git_path_string_to_dir(buffer_out, size); //Ensure the path ends with a trailing slash
return GIT_SUCCESS; return GIT_SUCCESS;
...@@ -44,14 +43,13 @@ int p_rename(const char *from, const char *to) ...@@ -44,14 +43,13 @@ int p_rename(const char *from, const char *to)
{ {
if (!link(from, to)) { if (!link(from, to)) {
p_unlink(from); p_unlink(from);
return GIT_SUCCESS; return 0;
} }
if (!rename(from, to)) if (!rename(from, to))
return GIT_SUCCESS; return 0;
return GIT_ERROR;
return -1;
} }
#endif #endif
...@@ -64,7 +62,7 @@ int p_read(git_file fd, void *buf, size_t cnt) ...@@ -64,7 +62,7 @@ int p_read(git_file fd, void *buf, size_t cnt)
if (r < 0) { if (r < 0) {
if (errno == EINTR || errno == EAGAIN) if (errno == EINTR || errno == EAGAIN)
continue; continue;
return GIT_EOSERR; return -1;
} }
if (!r) if (!r)
break; break;
...@@ -82,14 +80,14 @@ int p_write(git_file fd, const void *buf, size_t cnt) ...@@ -82,14 +80,14 @@ int p_write(git_file fd, const void *buf, size_t cnt)
if (r < 0) { if (r < 0) {
if (errno == EINTR || errno == EAGAIN) if (errno == EINTR || errno == EAGAIN)
continue; continue;
return GIT_EOSERR; return -1;
} }
if (!r) { if (!r) {
errno = EPIPE; errno = EPIPE;
return GIT_EOSERR; return -1;
} }
cnt -= r; cnt -= r;
b += r; b += r;
} }
return GIT_SUCCESS; return 0;
} }
...@@ -7,8 +7,6 @@ ...@@ -7,8 +7,6 @@
#ifndef INCLUDE_util_h__ #ifndef INCLUDE_util_h__
#define INCLUDE_util_h__ #define INCLUDE_util_h__
#include "git2/errors.h"
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
#define bitsizeof(x) (CHAR_BIT * sizeof(x)) #define bitsizeof(x) (CHAR_BIT * sizeof(x))
#define MSB(x, bits) ((x) & (~0ULL << (bitsizeof(x) - (bits)))) #define MSB(x, bits) ((x) & (~0ULL << (bitsizeof(x) - (bits))))
...@@ -24,24 +22,21 @@ ...@@ -24,24 +22,21 @@
GIT_INLINE(void *) git__malloc(size_t len) GIT_INLINE(void *) git__malloc(size_t len)
{ {
void *ptr = malloc(len); void *ptr = malloc(len);
if (!ptr) if (!ptr) giterr_set_oom();
giterr_set(GITERR_NOMEMORY, "Out of memory. Failed to allocate %d bytes.", (int)len);
return ptr; return ptr;
} }
GIT_INLINE(void *) git__calloc(size_t nelem, size_t elsize) GIT_INLINE(void *) git__calloc(size_t nelem, size_t elsize)
{ {
void *ptr = calloc(nelem, elsize); void *ptr = calloc(nelem, elsize);
if (!ptr) if (!ptr) giterr_set_oom();
giterr_set(GITERR_NOMEMORY, "Out of memory. Failed to allocate %d bytes.", (int)nelem*elsize);
return ptr; return ptr;
} }
GIT_INLINE(char *) git__strdup(const char *str) GIT_INLINE(char *) git__strdup(const char *str)
{ {
char *ptr = strdup(str); char *ptr = strdup(str);
if (!ptr) if (!ptr) giterr_set_oom();
giterr_set(GITERR_NOMEMORY, "Out of memory. Failed to duplicate string");
return ptr; return ptr;
} }
...@@ -56,7 +51,7 @@ GIT_INLINE(char *) git__strndup(const char *str, size_t n) ...@@ -56,7 +51,7 @@ GIT_INLINE(char *) git__strndup(const char *str, size_t n)
ptr = (char*)malloc(length + 1); ptr = (char*)malloc(length + 1);
if (!ptr) { if (!ptr) {
giterr_set(GITERR_NOMEMORY, "Out of memory. Failed to duplicate string"); giterr_set_oom();
return NULL; return NULL;
} }
...@@ -69,8 +64,7 @@ GIT_INLINE(char *) git__strndup(const char *str, size_t n) ...@@ -69,8 +64,7 @@ GIT_INLINE(char *) git__strndup(const char *str, size_t n)
GIT_INLINE(void *) git__realloc(void *ptr, size_t size) GIT_INLINE(void *) git__realloc(void *ptr, size_t size)
{ {
void *new_ptr = realloc(ptr, size); void *new_ptr = realloc(ptr, size);
if (!new_ptr) if (!new_ptr) giterr_set_oom();
giterr_set(GITERR_NOMEMORY, "Out of memory. Failed to allocate %d bytes.", (int)size);
return new_ptr; return new_ptr;
} }
......
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