1#include "../git-compat-util.h"
   2/*
   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#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        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        s = NULL;
  36        if (maxsize < 128)
  37                maxsize = 128;
  38        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}
  52int git_snprintf(char *str, size_t maxsize, const char *format, ...)
  54{
  55        va_list ap;
  56        int ret;
  57        va_start(ap, format);
  59        ret = git_vsnprintf(str, maxsize, format, ap);
  60        va_end(ap);
  61        return ret;
  63}
  64