snprintf.c 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. #include "../git-compat-util.h"
  2. /*
  3. * The size parameter specifies the available space, i.e. includes
  4. * the trailing NUL byte; but Windows's vsnprintf uses the entire
  5. * buffer and avoids the trailing NUL, should the buffer be exactly
  6. * big enough for the result. Defining SNPRINTF_SIZE_CORR to 1 will
  7. * therefore remove 1 byte from the reported buffer size, so we
  8. * always have room for a trailing NUL byte.
  9. */
  10. #ifndef SNPRINTF_SIZE_CORR
  11. #if defined(WIN32) && (!defined(__GNUC__) || __GNUC__ < 4) && (!defined(_MSC_VER) || _MSC_VER < 1900)
  12. #define SNPRINTF_SIZE_CORR 1
  13. #else
  14. #define SNPRINTF_SIZE_CORR 0
  15. #endif
  16. #endif
  17. #undef vsnprintf
  18. int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap)
  19. {
  20. va_list cp;
  21. char *s;
  22. int ret = -1;
  23. if (maxsize > 0) {
  24. va_copy(cp, ap);
  25. ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, cp);
  26. va_end(cp);
  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;
  35. if (maxsize < 128)
  36. maxsize = 128;
  37. while (ret == -1) {
  38. maxsize *= 4;
  39. str = realloc(s, maxsize);
  40. if (! str)
  41. break;
  42. s = str;
  43. va_copy(cp, ap);
  44. ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, cp);
  45. va_end(cp);
  46. if (ret == maxsize-1)
  47. ret = -1;
  48. }
  49. free(s);
  50. return ret;
  51. }
  52. int git_snprintf(char *str, size_t maxsize, const char *format, ...)
  53. {
  54. va_list ap;
  55. int ret;
  56. va_start(ap, format);
  57. ret = git_vsnprintf(str, maxsize, format, ap);
  58. va_end(ap);
  59. return ret;
  60. }