|
|
#define _GNU_SOURCE |
|
|
#include <stdarg.h> |
|
|
#include <stdio.h> |
|
|
#include <stdlib.h> |
|
|
#include <limits.h> |
|
|
#include <string.h> |
|
|
|
|
|
#include "xmlrpc_config.h" |
|
|
#include "bool.h" |
|
|
#include "casprintf.h" |
|
|
|
|
|
|
|
|
|
|
|
static __inline__ void |
|
|
newVsnprintf(char * const buffer, |
|
|
size_t const bufferSize, |
|
|
const char * const fmt, |
|
|
va_list varargs, |
|
|
size_t * const formattedSizeP) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (bufferSize > INT_MAX/2) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*formattedSizeP = 0; |
|
|
} else { |
|
|
int rc; |
|
|
|
|
|
rc = XMLRPC_VSNPRINTF(buffer, bufferSize, fmt, varargs); |
|
|
|
|
|
if (rc < 0) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*formattedSizeP = bufferSize * 2; |
|
|
} else { |
|
|
|
|
|
|
|
|
|
|
|
*formattedSizeP = rc; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static __inline__ int |
|
|
simpleVasprintf(char ** const resultP, |
|
|
const char * const fmt, |
|
|
va_list varargs) { |
|
|
|
|
|
|
|
|
|
|
|
int retval; |
|
|
char * buffer; |
|
|
size_t bufferSize; |
|
|
bool outOfMemory; |
|
|
|
|
|
for (buffer = NULL, bufferSize = 4096, outOfMemory = false; |
|
|
!buffer && !outOfMemory; |
|
|
) { |
|
|
|
|
|
buffer = malloc(bufferSize); |
|
|
if (!buffer) |
|
|
outOfMemory = true; |
|
|
else { |
|
|
size_t bytesNeeded; |
|
|
newVsnprintf(buffer, bufferSize, fmt, varargs, &bytesNeeded); |
|
|
if (bytesNeeded > bufferSize) { |
|
|
free(buffer); |
|
|
buffer = NULL; |
|
|
bufferSize = bytesNeeded; |
|
|
} |
|
|
} |
|
|
} |
|
|
if (outOfMemory) |
|
|
retval = -1; |
|
|
else { |
|
|
retval = strlen(buffer); |
|
|
*resultP = buffer; |
|
|
} |
|
|
return retval; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const char * const strsol = "[Insufficient memory to build string]"; |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
cvasprintf(const char ** const retvalP, |
|
|
const char * const fmt, |
|
|
va_list varargs) { |
|
|
|
|
|
char * string; |
|
|
int rc; |
|
|
|
|
|
#if HAVE_ASPRINTF |
|
|
rc = vasprintf(&string, fmt, varargs); |
|
|
#else |
|
|
rc = simpleVasprintf(&string, fmt, varargs); |
|
|
#endif |
|
|
|
|
|
if (rc < 0) |
|
|
*retvalP = strsol; |
|
|
else |
|
|
*retvalP = string; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void GNU_PRINTF_ATTR(2,3) |
|
|
casprintf(const char ** const retvalP, const char * const fmt, ...) { |
|
|
|
|
|
va_list varargs; |
|
|
|
|
|
va_start(varargs, fmt); |
|
|
|
|
|
cvasprintf(retvalP, fmt, varargs); |
|
|
|
|
|
va_end(varargs); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
strfree(const char * const string) { |
|
|
|
|
|
if (string != strsol) |
|
|
free((void *)string); |
|
|
} |
|
|
|