{
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))
}
}
+static int handle_nonblock(int fd, short poll_events, int err)
+{
+ struct pollfd pfd;
+
+ if (err != EAGAIN && err != EWOULDBLOCK)
+ return 0;
+
+ pfd.fd = fd;
+ pfd.events = poll_events;
+
+ /*
+ * no need to check for errors, here;
+ * a subsequent read/write will detect unrecoverable errors
+ */
+ poll(&pfd, 1, -1);
+ return 1;
+}
+
/*
* xread() is the same a read(), but it automatically restarts read()
* operations with a recoverable error (EAGAIN and EINTR). xread()
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 (handle_nonblock(fd, POLLIN, errno))
+ continue;
+ }
return nr;
}
}
len = MAX_IO_SIZE;
while (1) {
nr = write(fd, buf, len);
- if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
- continue;
+ if (nr < 0) {
+ if (errno == EINTR)
+ continue;
+ if (handle_nonblock(fd, POLLOUT, errno))
+ continue;
+ }
+
return nr;
}
}
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;
return fd;
}
-/* git_mkstemp() - create tmp file honoring TMPDIR variable */
-int git_mkstemp(char *path, size_t len, const char *template)
-{
- const char *tmp;
- size_t n;
-
- tmp = getenv("TMPDIR");
- if (!tmp)
- tmp = "/tmp";
- n = snprintf(path, len, "%s/%s", tmp, template);
- if (len <= n) {
- errno = ENAMETOOLONG;
- return -1;
- }
- return mkstemp(path);
-}
-
-/* git_mkstemps() - create tmp file with suffix honoring TMPDIR variable. */
-int git_mkstemps(char *path, size_t len, const char *template, int suffix_len)
-{
- const char *tmp;
- size_t n;
-
- tmp = getenv("TMPDIR");
- if (!tmp)
- tmp = "/tmp";
- n = snprintf(path, len, "%s/%s", tmp, template);
- if (len <= n) {
- errno = ENAMETOOLONG;
- return -1;
- }
- return mkstemps(path, suffix_len);
-}
-
/* Adapted from libiberty's mkstemp.c. */
#undef TMP_MAX
return git_mkstemps_mode(pattern, 0, mode);
}
-#ifdef NO_MKSTEMPS
-int gitmkstemps(char *pattern, int suffix_len)
-{
- return git_mkstemps_mode(pattern, suffix_len, 0600);
-}
-#endif
-
int xmkstemp_mode(char *template, int mode)
{
int fd;
if (!rc || errno == ENOENT)
return 0;
err = errno;
- warning("unable to %s %s: %s", op, file, strerror(errno));
+ warning_errno("unable to %s %s", op, file);
errno = err;
return rc;
}
void warn_on_inaccessible(const char *path)
{
- warning(_("unable to access '%s': %s"), path, strerror(errno));
+ warning_errno(_("unable to access '%s'"), path);
}
static int access_error_is_ok(int err, unsigned flag)
return strbuf_detach(&sb, NULL);
}
-static int write_file_v(const char *path, int fatal,
- const char *fmt, va_list params)
+int xsnprintf(char *dst, size_t max, const char *fmt, ...)
{
- struct strbuf sb = STRBUF_INIT;
- int fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0666);
- if (fd < 0) {
- if (fatal)
- die_errno(_("could not open %s for writing"), path);
- return -1;
- }
- strbuf_vaddf(&sb, fmt, params);
- strbuf_complete_line(&sb);
- if (write_in_full(fd, sb.buf, sb.len) != sb.len) {
- int err = errno;
- close(fd);
- strbuf_release(&sb);
- errno = err;
- if (fatal)
- die_errno(_("could not write to %s"), path);
- return -1;
- }
- strbuf_release(&sb);
- if (close(fd)) {
- if (fatal)
- die_errno(_("could not close %s"), path);
- return -1;
- }
- return 0;
+ 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;
}
-int write_file(const char *path, const char *fmt, ...)
+void write_file_buf(const char *path, const char *buf, size_t len)
{
- int status;
- va_list params;
-
- va_start(params, fmt);
- status = write_file_v(path, 1, fmt, params);
- va_end(params);
- return status;
+ int fd = xopen(path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (write_in_full(fd, buf, len) != len)
+ die_errno(_("could not write to %s"), path);
+ if (close(fd))
+ die_errno(_("could not close %s"), path);
}
-int write_file_gently(const char *path, const char *fmt, ...)
+void write_file(const char *path, const char *fmt, ...)
{
- int status;
va_list params;
+ struct strbuf sb = STRBUF_INIT;
va_start(params, fmt);
- status = write_file_v(path, 0, fmt, params);
+ strbuf_vaddf(&sb, fmt, params);
va_end(params);
- return status;
+
+ strbuf_complete_line(&sb);
+
+ write_file_buf(path, sb.buf, sb.len);
+ strbuf_release(&sb);
}
void sleep_millisec(int millisec)
{
poll(NULL, 0, millisec);
}
+
+int xgethostname(char *buf, size_t len)
+{
+ /*
+ * If the full hostname doesn't fit in buf, POSIX does not
+ * specify whether the buffer will be null-terminated, so to
+ * be safe, do it ourselves.
+ */
+ int ret = gethostname(buf, len);
+ if (!ret)
+ buf[len - 1] = 0;
+ return ret;
+}