compat / snprintf.con commit Merge branch 'tb/clone-case-smashing-warning-test' (590e5b8)
   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) && (!defined(_MSC_VER) || _MSC_VER < 1900)
  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        va_list cp;
  23        char *s;
  24        int ret = -1;
  25
  26        if (maxsize > 0) {
  27                va_copy(cp, ap);
  28                ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, cp);
  29                va_end(cp);
  30                if (ret == maxsize-1)
  31                        ret = -1;
  32                /* Windows does not NUL-terminate if result fills buffer */
  33                str[maxsize-1] = 0;
  34        }
  35        if (ret != -1)
  36                return ret;
  37
  38        s = NULL;
  39        if (maxsize < 128)
  40                maxsize = 128;
  41
  42        while (ret == -1) {
  43                maxsize *= 4;
  44                str = realloc(s, maxsize);
  45                if (! str)
  46                        break;
  47                s = str;
  48                va_copy(cp, ap);
  49                ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, cp);
  50                va_end(cp);
  51                if (ret == maxsize-1)
  52                        ret = -1;
  53        }
  54        free(s);
  55        return ret;
  56}
  57
  58int git_snprintf(char *str, size_t maxsize, const char *format, ...)
  59{
  60        va_list ap;
  61        int ret;
  62
  63        va_start(ap, format);
  64        ret = git_vsnprintf(str, maxsize, format, ap);
  65        va_end(ap);
  66
  67        return ret;
  68}
  69