compat / snprintf.con commit stash: Don't overwrite files that have gone from the index (7aa5d43)
   1#include "../git-compat-util.h"
   2
   3/*
   4 * The size parameter specifies the available space, i.e. includes
   5 * the trailing NUL byte; but Windows's vsnprintf uses the entire
   6 * buffer and avoids the trailing NUL, should the buffer be exactly
   7 * big enough for the result. Defining SNPRINTF_SIZE_CORR to 1 will
   8 * therefore remove 1 byte from the reported buffer size, so we
   9 * always have room for a trailing NUL byte.
  10 */
  11#ifndef SNPRINTF_SIZE_CORR
  12#if defined(WIN32) && (!defined(__GNUC__) || __GNUC__ < 4)
  13#define SNPRINTF_SIZE_CORR 1
  14#else
  15#define SNPRINTF_SIZE_CORR 0
  16#endif
  17#endif
  18
  19#undef vsnprintf
  20int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap)
  21{
  22        char *s;
  23        int ret = -1;
  24
  25        if (maxsize > 0) {
  26                ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);
  27                if (ret == maxsize-1)
  28                        ret = -1;
  29                /* Windows does not NUL-terminate if result fills buffer */
  30                str[maxsize-1] = 0;
  31        }
  32        if (ret != -1)
  33                return ret;
  34
  35        s = NULL;
  36        if (maxsize < 128)
  37                maxsize = 128;
  38
  39        while (ret == -1) {
  40                maxsize *= 4;
  41                str = realloc(s, maxsize);
  42                if (! str)
  43                        break;
  44                s = str;
  45                ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);
  46                if (ret == maxsize-1)
  47                        ret = -1;
  48        }
  49        free(s);
  50        return ret;
  51}
  52
  53int git_snprintf(char *str, size_t maxsize, const char *format, ...)
  54{
  55        va_list ap;
  56        int ret;
  57
  58        va_start(ap, format);
  59        ret = git_vsnprintf(str, maxsize, format, ap);
  60        va_end(ap);
  61
  62        return ret;
  63}
  64