Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
git/write_or_die.c
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
107 lines (94 sloc)
2.18 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "cache.h" | |
#include "run-command.h" | |
static void check_pipe(int err) | |
{ | |
if (err == EPIPE) { | |
if (in_async()) | |
async_exit(141); | |
signal(SIGPIPE, SIG_DFL); | |
raise(SIGPIPE); | |
/* Should never happen, but just in case... */ | |
exit(141); | |
} | |
} | |
/* | |
* Some cases use stdio, but want to flush after the write | |
* to get error handling (and to get better interactive | |
* behaviour - not buffering excessively). | |
* | |
* Of course, if the flush happened within the write itself, | |
* we've already lost the error code, and cannot report it any | |
* more. So we just ignore that case instead (and hope we get | |
* the right error code on the flush). | |
* | |
* If the file handle is stdout, and stdout is a file, then skip the | |
* flush entirely since it's not needed. | |
*/ | |
void maybe_flush_or_die(FILE *f, const char *desc) | |
{ | |
static int skip_stdout_flush = -1; | |
struct stat st; | |
char *cp; | |
if (f == stdout) { | |
if (skip_stdout_flush < 0) { | |
cp = getenv("GIT_FLUSH"); | |
if (cp) | |
skip_stdout_flush = (atoi(cp) == 0); | |
else if ((fstat(fileno(stdout), &st) == 0) && | |
S_ISREG(st.st_mode)) | |
skip_stdout_flush = 1; | |
else | |
skip_stdout_flush = 0; | |
} | |
if (skip_stdout_flush && !ferror(f)) | |
return; | |
} | |
if (fflush(f)) { | |
check_pipe(errno); | |
die_errno("write failure on '%s'", desc); | |
} | |
} | |
void fprintf_or_die(FILE *f, const char *fmt, ...) | |
{ | |
va_list ap; | |
int ret; | |
va_start(ap, fmt); | |
ret = vfprintf(f, fmt, ap); | |
va_end(ap); | |
if (ret < 0) { | |
check_pipe(errno); | |
die_errno("write error"); | |
} | |
} | |
void fsync_or_die(int fd, const char *msg) | |
{ | |
if (fsync(fd) < 0) { | |
die_errno("fsync error on '%s'", msg); | |
} | |
} | |
void write_or_die(int fd, const void *buf, size_t count) | |
{ | |
if (write_in_full(fd, buf, count) < 0) { | |
check_pipe(errno); | |
die_errno("write error"); | |
} | |
} | |
int write_or_whine_pipe(int fd, const void *buf, size_t count, const char *msg) | |
{ | |
if (write_in_full(fd, buf, count) < 0) { | |
check_pipe(errno); | |
fprintf(stderr, "%s: write error (%s)\n", | |
msg, strerror(errno)); | |
return 0; | |
} | |
return 1; | |
} | |
int write_or_whine(int fd, const void *buf, size_t count, const char *msg) | |
{ | |
if (write_in_full(fd, buf, count) < 0) { | |
fprintf(stderr, "%s: write error (%s)\n", | |
msg, strerror(errno)); | |
return 0; | |
} | |
return 1; | |
} |