push: introduce new push.default mode "simple"
[gitweb.git] / wrapper.c
index b3efefb5393f419b5cbf6303761f16c2a8367ecf..6ccd0595f43d0ef62bd60a5863804f9a842a4235 100644 (file)
--- a/wrapper.c
+++ b/wrapper.c
@@ -3,16 +3,29 @@
  */
 #include "cache.h"
 
-static void try_to_free_builtin(size_t size)
+static void do_nothing(size_t size)
 {
-       release_pack_memory(size, -1);
 }
 
-static void (*try_to_free_routine)(size_t size) = try_to_free_builtin;
+static void (*try_to_free_routine)(size_t size) = do_nothing;
+
+static void memory_limit_check(size_t size)
+{
+       static int limit = -1;
+       if (limit == -1) {
+               const char *env = getenv("GIT_ALLOC_LIMIT");
+               limit = env ? atoi(env) * 1024 : 0;
+       }
+       if (limit && size > limit)
+               die("attempting to allocate %"PRIuMAX" over limit %d",
+                   (intmax_t)size, limit);
+}
 
 try_to_free_t set_try_to_free_routine(try_to_free_t routine)
 {
        try_to_free_t old = try_to_free_routine;
+       if (!routine)
+               routine = do_nothing;
        try_to_free_routine = routine;
        return old;
 }
@@ -31,7 +44,10 @@ char *xstrdup(const char *str)
 
 void *xmalloc(size_t size)
 {
-       void *ret = malloc(size);
+       void *ret;
+
+       memory_limit_check(size);
+       ret = malloc(size);
        if (!ret && !size)
                ret = malloc(1);
        if (!ret) {
@@ -52,7 +68,7 @@ void *xmalloc(size_t size)
 void *xmallocz(size_t size)
 {
        void *ret;
-       if (size + 1 < size)
+       if (unsigned_add_overflows(size, 1))
                die("Data too large to fit into virtual memory space.");
        ret = xmalloc(size + 1);
        ((char*)ret)[size] = 0;
@@ -78,7 +94,10 @@ char *xstrndup(const char *str, size_t len)
 
 void *xrealloc(void *ptr, size_t size)
 {
-       void *ret = realloc(ptr, size);
+       void *ret;
+
+       memory_limit_check(size);
+       ret = realloc(ptr, size);
        if (!ret && !size)
                ret = realloc(ptr, 1);
        if (!ret) {
@@ -94,7 +113,10 @@ void *xrealloc(void *ptr, size_t size)
 
 void *xcalloc(size_t nmemb, size_t size)
 {
-       void *ret = calloc(nmemb, size);
+       void *ret;
+
+       memory_limit_check(size * nmemb);
+       ret = calloc(nmemb, size);
        if (!ret && (!nmemb || !size))
                ret = calloc(1, 1);
        if (!ret) {
@@ -147,8 +169,10 @@ ssize_t read_in_full(int fd, void *buf, size_t count)
 
        while (count > 0) {
                ssize_t loaded = xread(fd, p, count);
-               if (loaded <= 0)
-                       return total ? total : loaded;
+               if (loaded < 0)
+                       return -1;
+               if (loaded == 0)
+                       return total;
                count -= loaded;
                p += loaded;
                total += loaded;
@@ -197,10 +221,22 @@ FILE *xfdopen(int fd, const char *mode)
 int xmkstemp(char *template)
 {
        int fd;
+       char origtemplate[PATH_MAX];
+       strlcpy(origtemplate, template, sizeof(origtemplate));
 
        fd = mkstemp(template);
-       if (fd < 0)
-               die_errno("Unable to create temporary file");
+       if (fd < 0) {
+               int saved_errno = errno;
+               const char *nonrelative_template;
+
+               if (!template[0])
+                       template = origtemplate;
+
+               nonrelative_template = absolute_path(template);
+               errno = saved_errno;
+               die_errno("Unable to create temporary file '%s'",
+                       nonrelative_template);
+       }
        return fd;
 }
 
@@ -320,71 +356,23 @@ int gitmkstemps(char *pattern, int suffix_len)
 int xmkstemp_mode(char *template, int mode)
 {
        int fd;
+       char origtemplate[PATH_MAX];
+       strlcpy(origtemplate, template, sizeof(origtemplate));
 
        fd = git_mkstemp_mode(template, mode);
-       if (fd < 0)
-               die_errno("Unable to create temporary file");
-       return fd;
-}
+       if (fd < 0) {
+               int saved_errno = errno;
+               const char *nonrelative_template;
 
-/*
- * zlib wrappers to make sure we don't silently miss errors
- * at init time.
- */
-void git_inflate_init(z_streamp strm)
-{
-       const char *err;
-
-       switch (inflateInit(strm)) {
-       case Z_OK:
-               return;
-
-       case Z_MEM_ERROR:
-               err = "out of memory";
-               break;
-       case Z_VERSION_ERROR:
-               err = "wrong version";
-               break;
-       default:
-               err = "error";
-       }
-       die("inflateInit: %s (%s)", err, strm->msg ? strm->msg : "no message");
-}
+               if (!template[0])
+                       template = origtemplate;
 
-void git_inflate_end(z_streamp strm)
-{
-       if (inflateEnd(strm) != Z_OK)
-               error("inflateEnd: %s", strm->msg ? strm->msg : "failed");
-}
-
-int git_inflate(z_streamp strm, int flush)
-{
-       int ret = inflate(strm, flush);
-       const char *err;
-
-       switch (ret) {
-       /* Out of memory is fatal. */
-       case Z_MEM_ERROR:
-               die("inflate: out of memory");
-
-       /* Data corruption errors: we may want to recover from them (fsck) */
-       case Z_NEED_DICT:
-               err = "needs dictionary"; break;
-       case Z_DATA_ERROR:
-               err = "data stream error"; break;
-       case Z_STREAM_ERROR:
-               err = "stream consistency error"; break;
-       default:
-               err = "unknown error"; break;
-
-       /* Z_BUF_ERROR: normal, needs more space in the output buffer */
-       case Z_BUF_ERROR:
-       case Z_OK:
-       case Z_STREAM_END:
-               return ret;
+               nonrelative_template = absolute_path(template);
+               errno = saved_errno;
+               die_errno("Unable to create temporary file '%s'",
+                       nonrelative_template);
        }
-       error("inflate: %s (%s)", err, strm->msg ? strm->msg : "no message");
-       return ret;
+       return fd;
 }
 
 static int warn_if_unremovable(const char *op, const char *file, int rc)