Git 2.8-rc4
[gitweb.git] / wrapper.c
index dae5675a960b636337dc7890fcfbcc559aa98567..9afc1a021c224d4ff2230fffeb0e4f0882d4a99e 100644 (file)
--- a/wrapper.c
+++ b/wrapper.c
@@ -152,6 +152,9 @@ void *xcalloc(size_t nmemb, size_t size)
 {
        void *ret;
 
+       if (unsigned_mult_overflows(nmemb, size))
+               die("data too large to fit into virtual memory space");
+
        memory_limit_check(size * nmemb, 0);
        ret = calloc(nmemb, size);
        if (!ret && (!nmemb || !size))
@@ -236,8 +239,24 @@ ssize_t xread(int fd, void *buf, size_t len)
            len = MAX_IO_SIZE;
        while (1) {
                nr = read(fd, buf, len);
-               if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
-                       continue;
+               if (nr < 0) {
+                       if (errno == EINTR)
+                               continue;
+                       if (errno == EAGAIN || errno == EWOULDBLOCK) {
+                               struct pollfd pfd;
+                               pfd.events = POLLIN;
+                               pfd.fd = fd;
+                               /*
+                                * it is OK if this poll() failed; we
+                                * want to leave this infinite loop
+                                * only when read() returns with
+                                * success, or an expected failure,
+                                * which would be checked by the next
+                                * call to read(2).
+                                */
+                               poll(&pfd, 1, -1);
+                       }
+               }
                return nr;
        }
 }
@@ -375,6 +394,19 @@ FILE *xfdopen(int fd, const char *mode)
        return stream;
 }
 
+FILE *fopen_for_writing(const char *path)
+{
+       FILE *ret = fopen(path, "w");
+
+       if (!ret && errno == EPERM) {
+               if (!unlink(path))
+                       ret = fopen(path, "w");
+               else
+                       errno = EPERM;
+       }
+       return ret;
+}
+
 int xmkstemp(char *template)
 {
        int fd;
@@ -609,6 +641,22 @@ char *xgetcwd(void)
        return strbuf_detach(&sb, NULL);
 }
 
+int xsnprintf(char *dst, size_t max, const char *fmt, ...)
+{
+       va_list ap;
+       int len;
+
+       va_start(ap, fmt);
+       len = vsnprintf(dst, max, fmt, ap);
+       va_end(ap);
+
+       if (len < 0)
+               die("BUG: your snprintf is broken");
+       if (len >= max)
+               die("BUG: attempt to snprintf into too-small buffer");
+       return len;
+}
+
 static int write_file_v(const char *path, int fatal,
                        const char *fmt, va_list params)
 {