write_or_die.con commit sequencer: support cleaning up commit messages (0009426)
   1#include "cache.h"
   2#include "run-command.h"
   3
   4static void check_pipe(int err)
   5{
   6        if (err == EPIPE) {
   7                if (in_async())
   8                        async_exit(141);
   9
  10                signal(SIGPIPE, SIG_DFL);
  11                raise(SIGPIPE);
  12                /* Should never happen, but just in case... */
  13                exit(141);
  14        }
  15}
  16
  17/*
  18 * Some cases use stdio, but want to flush after the write
  19 * to get error handling (and to get better interactive
  20 * behaviour - not buffering excessively).
  21 *
  22 * Of course, if the flush happened within the write itself,
  23 * we've already lost the error code, and cannot report it any
  24 * more. So we just ignore that case instead (and hope we get
  25 * the right error code on the flush).
  26 *
  27 * If the file handle is stdout, and stdout is a file, then skip the
  28 * flush entirely since it's not needed.
  29 */
  30void maybe_flush_or_die(FILE *f, const char *desc)
  31{
  32        static int skip_stdout_flush = -1;
  33        struct stat st;
  34        char *cp;
  35
  36        if (f == stdout) {
  37                if (skip_stdout_flush < 0) {
  38                        cp = getenv("GIT_FLUSH");
  39                        if (cp)
  40                                skip_stdout_flush = (atoi(cp) == 0);
  41                        else if ((fstat(fileno(stdout), &st) == 0) &&
  42                                 S_ISREG(st.st_mode))
  43                                skip_stdout_flush = 1;
  44                        else
  45                                skip_stdout_flush = 0;
  46                }
  47                if (skip_stdout_flush && !ferror(f))
  48                        return;
  49        }
  50        if (fflush(f)) {
  51                check_pipe(errno);
  52                die_errno("write failure on '%s'", desc);
  53        }
  54}
  55
  56void fprintf_or_die(FILE *f, const char *fmt, ...)
  57{
  58        va_list ap;
  59        int ret;
  60
  61        va_start(ap, fmt);
  62        ret = vfprintf(f, fmt, ap);
  63        va_end(ap);
  64
  65        if (ret < 0) {
  66                check_pipe(errno);
  67                die_errno("write error");
  68        }
  69}
  70
  71void fsync_or_die(int fd, const char *msg)
  72{
  73        if (fsync(fd) < 0) {
  74                die_errno("fsync error on '%s'", msg);
  75        }
  76}
  77
  78void write_or_die(int fd, const void *buf, size_t count)
  79{
  80        if (write_in_full(fd, buf, count) < 0) {
  81                check_pipe(errno);
  82                die_errno("write error");
  83        }
  84}