diff options
Diffstat (limited to 'libbb/write_or_die.c')
-rw-r--r-- | libbb/write_or_die.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/libbb/write_or_die.c b/libbb/write_or_die.c new file mode 100644 index 000000000..4c29255df --- /dev/null +++ b/libbb/write_or_die.c | |||
@@ -0,0 +1,86 @@ | |||
1 | #include "cache.h" | ||
2 | |||
3 | /* | ||
4 | * Some cases use stdio, but want to flush after the write | ||
5 | * to get error handling (and to get better interactive | ||
6 | * behaviour - not buffering excessively). | ||
7 | * | ||
8 | * Of course, if the flush happened within the write itself, | ||
9 | * we've already lost the error code, and cannot report it any | ||
10 | * more. So we just ignore that case instead (and hope we get | ||
11 | * the right error code on the flush). | ||
12 | * | ||
13 | * If the file handle is stdout, and stdout is a file, then skip the | ||
14 | * flush entirely since it's not needed. | ||
15 | */ | ||
16 | void maybe_flush_or_die(FILE *f, const char *desc) | ||
17 | { | ||
18 | static int skip_stdout_flush = -1; | ||
19 | struct stat st; | ||
20 | char *cp; | ||
21 | |||
22 | if (f == stdout) { | ||
23 | if (skip_stdout_flush < 0) { | ||
24 | cp = getenv("GIT_FLUSH"); | ||
25 | if (cp) | ||
26 | skip_stdout_flush = (atoi(cp) == 0); | ||
27 | else if ((fstat(fileno(stdout), &st) == 0) && | ||
28 | S_ISREG(st.st_mode)) | ||
29 | skip_stdout_flush = 1; | ||
30 | else | ||
31 | skip_stdout_flush = 0; | ||
32 | } | ||
33 | if (skip_stdout_flush && !ferror(f)) | ||
34 | return; | ||
35 | } | ||
36 | if (fflush(f)) { | ||
37 | /* | ||
38 | * On Windows, EPIPE is returned only by the first write() | ||
39 | * after the reading end has closed its handle; subsequent | ||
40 | * write()s return EINVAL. | ||
41 | */ | ||
42 | if (errno == EPIPE || errno == EINVAL) | ||
43 | exit(0); | ||
44 | die("write failure on %s: %s", desc, strerror(errno)); | ||
45 | } | ||
46 | } | ||
47 | |||
48 | void fsync_or_die(int fd, const char *msg) | ||
49 | { | ||
50 | if (fsync(fd) < 0) { | ||
51 | die("%s: fsync error (%s)", msg, strerror(errno)); | ||
52 | } | ||
53 | } | ||
54 | |||
55 | void write_or_die(int fd, const void *buf, size_t count) | ||
56 | { | ||
57 | if (write_in_full(fd, buf, count) < 0) { | ||
58 | if (errno == EPIPE) | ||
59 | exit(0); | ||
60 | die("write error (%s)", strerror(errno)); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | int write_or_whine_pipe(int fd, const void *buf, size_t count, const char *msg) | ||
65 | { | ||
66 | if (write_in_full(fd, buf, count) < 0) { | ||
67 | if (errno == EPIPE) | ||
68 | exit(0); | ||
69 | fprintf(stderr, "%s: write error (%s)\n", | ||
70 | msg, strerror(errno)); | ||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | return 1; | ||
75 | } | ||
76 | |||
77 | int write_or_whine(int fd, const void *buf, size_t count, const char *msg) | ||
78 | { | ||
79 | if (write_in_full(fd, buf, count) < 0) { | ||
80 | fprintf(stderr, "%s: write error (%s)\n", | ||
81 | msg, strerror(errno)); | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | return 1; | ||
86 | } | ||