|
|
@@ -169,65 +169,115 @@ rspamd_sprintf_num (gchar *buf, gchar *last, guint64 ui64, gchar zero, |
|
|
|
return ((gchar *)memcpy (buf, p, len)) + len; |
|
|
|
} |
|
|
|
|
|
|
|
gint |
|
|
|
struct rspamd_printf_char_buf { |
|
|
|
char *begin; |
|
|
|
char *pos; |
|
|
|
glong remain; |
|
|
|
}; |
|
|
|
|
|
|
|
static glong |
|
|
|
rspamd_printf_append_char (const gchar *buf, glong buflen, gpointer ud) |
|
|
|
{ |
|
|
|
struct rspamd_printf_char_buf *dst = (struct rspamd_printf_char_buf *)ud; |
|
|
|
glong wr; |
|
|
|
|
|
|
|
if (dst->remain <= 0) { |
|
|
|
return dst->remain; |
|
|
|
} |
|
|
|
|
|
|
|
wr = MIN (dst->remain, buflen); |
|
|
|
memcpy (dst->pos, buf, wr); |
|
|
|
dst->remain -= wr; |
|
|
|
dst->pos += wr; |
|
|
|
|
|
|
|
return wr; |
|
|
|
} |
|
|
|
|
|
|
|
static glong |
|
|
|
rspamd_printf_append_file (const gchar *buf, glong buflen, gpointer ud) |
|
|
|
{ |
|
|
|
FILE *dst = (FILE *)ud; |
|
|
|
|
|
|
|
return fwrite (buf, 1, buflen, dst); |
|
|
|
} |
|
|
|
|
|
|
|
static glong |
|
|
|
rspamd_printf_append_gstring (const gchar *buf, glong buflen, gpointer ud) |
|
|
|
{ |
|
|
|
GString *dst = (GString *)ud; |
|
|
|
|
|
|
|
g_string_append_len (dst, buf, buflen); |
|
|
|
|
|
|
|
return buflen; |
|
|
|
} |
|
|
|
|
|
|
|
glong |
|
|
|
rspamd_fprintf (FILE *f, const gchar *fmt, ...) |
|
|
|
{ |
|
|
|
va_list args; |
|
|
|
gchar buf[BUFSIZ]; |
|
|
|
gint r; |
|
|
|
glong r; |
|
|
|
|
|
|
|
va_start (args, fmt); |
|
|
|
rspamd_vsnprintf (buf, sizeof (buf), fmt, args); |
|
|
|
r = rspamd_vprintf_common (rspamd_printf_append_file, f, fmt, args); |
|
|
|
va_end (args); |
|
|
|
|
|
|
|
r = fprintf (f, "%s", buf); |
|
|
|
|
|
|
|
return r; |
|
|
|
return r; |
|
|
|
} |
|
|
|
|
|
|
|
gint |
|
|
|
glong |
|
|
|
rspamd_log_fprintf (FILE *f, const gchar *fmt, ...) |
|
|
|
{ |
|
|
|
va_list args; |
|
|
|
gchar buf[BUFSIZ]; |
|
|
|
gint r; |
|
|
|
glong r; |
|
|
|
|
|
|
|
va_start (args, fmt); |
|
|
|
rspamd_vsnprintf (buf, sizeof (buf), fmt, args); |
|
|
|
r = rspamd_vprintf_common (rspamd_printf_append_file, f, fmt, args); |
|
|
|
va_end (args); |
|
|
|
|
|
|
|
r = fprintf (f, "%s\n", buf); |
|
|
|
fflush (f); |
|
|
|
fflush (f); |
|
|
|
|
|
|
|
return r; |
|
|
|
return r; |
|
|
|
} |
|
|
|
|
|
|
|
gint |
|
|
|
rspamd_sprintf (gchar *buf, const gchar *fmt, ...) |
|
|
|
|
|
|
|
glong |
|
|
|
rspamd_snprintf (gchar *buf, glong max, const gchar *fmt, ...) |
|
|
|
{ |
|
|
|
gchar *p; |
|
|
|
va_list args; |
|
|
|
gchar *r; |
|
|
|
va_list args; |
|
|
|
|
|
|
|
va_start (args, fmt); |
|
|
|
p = rspamd_vsnprintf (buf, /* STUB */ 65536, fmt, args); |
|
|
|
r = rspamd_vsnprintf (buf, max, fmt, args); |
|
|
|
va_end (args); |
|
|
|
|
|
|
|
return p - buf; |
|
|
|
return (r - buf); |
|
|
|
} |
|
|
|
|
|
|
|
gchar * |
|
|
|
rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args) |
|
|
|
{ |
|
|
|
struct rspamd_printf_char_buf dst; |
|
|
|
|
|
|
|
dst.begin = buf; |
|
|
|
dst.pos = dst.begin; |
|
|
|
dst.remain = max - 1; |
|
|
|
(void)rspamd_vprintf_common (rspamd_printf_append_char, &dst, fmt, args); |
|
|
|
*dst.pos = '\0'; |
|
|
|
|
|
|
|
gint |
|
|
|
rspamd_snprintf (gchar *buf, glong max, const gchar *fmt, ...) |
|
|
|
return dst.pos; |
|
|
|
} |
|
|
|
|
|
|
|
glong |
|
|
|
rspamd_printf_gstring (GString *s, const gchar *fmt, ...) |
|
|
|
{ |
|
|
|
gchar *p; |
|
|
|
va_list args; |
|
|
|
va_list args; |
|
|
|
glong r; |
|
|
|
|
|
|
|
va_start (args, fmt); |
|
|
|
p = rspamd_vsnprintf (buf, max - 1, fmt, args); |
|
|
|
r = rspamd_vprintf_common (rspamd_printf_append_gstring, s, fmt, args); |
|
|
|
va_end (args); |
|
|
|
*p = '\0'; |
|
|
|
|
|
|
|
return p - buf; |
|
|
|
return r; |
|
|
|
} |
|
|
|
|
|
|
|
gchar * |
|
|
@@ -284,13 +334,25 @@ rspamd_escape_string (gchar *dst, const gchar *src, glong len) |
|
|
|
return buf; |
|
|
|
} |
|
|
|
|
|
|
|
gchar * |
|
|
|
rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args) |
|
|
|
#define RSPAMD_PRINTF_APPEND(buf, len) \ |
|
|
|
do { \ |
|
|
|
wr = func ((buf), (len), apd); \ |
|
|
|
if (wr <= 0) { \ |
|
|
|
goto oob; \ |
|
|
|
} \ |
|
|
|
written += wr; \ |
|
|
|
fmt ++; \ |
|
|
|
buf_start = fmt; \ |
|
|
|
} while(0) |
|
|
|
|
|
|
|
glong |
|
|
|
rspamd_vprintf_common (rspamd_printf_append_func func, gpointer apd, const gchar *fmt, va_list args) |
|
|
|
{ |
|
|
|
gchar *p, zero, *last; |
|
|
|
gchar zero, numbuf[G_ASCII_DTOSTR_BUF_SIZE], *p, *last, c; |
|
|
|
const gchar *buf_start = fmt; |
|
|
|
gint d; |
|
|
|
long double f, scale; |
|
|
|
size_t len, slen; |
|
|
|
glong written = 0, wr, slen; |
|
|
|
gint64 i64; |
|
|
|
guint64 ui64; |
|
|
|
guint width, sign, hex, humanize, bytes, frac_width, i; |
|
|
@@ -298,13 +360,7 @@ rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args) |
|
|
|
GString *gs; |
|
|
|
gboolean bv; |
|
|
|
|
|
|
|
if (max <= 0) { |
|
|
|
return buf; |
|
|
|
} |
|
|
|
|
|
|
|
last = buf + max; |
|
|
|
|
|
|
|
while (*fmt && buf < last) { |
|
|
|
while (*fmt) { |
|
|
|
|
|
|
|
/* |
|
|
|
* "buf < last" means that we could copy at least one character: |
|
|
@@ -313,6 +369,15 @@ rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args) |
|
|
|
|
|
|
|
if (*fmt == '%') { |
|
|
|
|
|
|
|
/* Append what we have in buf */ |
|
|
|
if (fmt > buf_start) { |
|
|
|
wr = func (buf_start, fmt - buf_start, apd); |
|
|
|
if (wr <= 0) { |
|
|
|
goto oob; |
|
|
|
} |
|
|
|
written += wr; |
|
|
|
} |
|
|
|
|
|
|
|
i64 = 0; |
|
|
|
ui64 = 0; |
|
|
|
|
|
|
@@ -323,7 +388,7 @@ rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args) |
|
|
|
bytes = 0; |
|
|
|
humanize = 0; |
|
|
|
frac_width = 0; |
|
|
|
slen = (size_t) -1; |
|
|
|
slen = -1; |
|
|
|
|
|
|
|
while (*fmt >= '0' && *fmt <= '9') { |
|
|
|
width = width * 10 + *fmt++ - '0'; |
|
|
@@ -376,10 +441,10 @@ rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args) |
|
|
|
case '*': |
|
|
|
d = (gint)va_arg (args, gint); |
|
|
|
if (G_UNLIKELY (d < 0)) { |
|
|
|
msg_err ("crititcal error: size is less than 0"); |
|
|
|
g_assert (0); |
|
|
|
msg_err ("critical error: size is less than 0"); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
slen = (size_t)d; |
|
|
|
slen = (glong)d; |
|
|
|
fmt++; |
|
|
|
continue; |
|
|
|
|
|
|
@@ -395,61 +460,28 @@ rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args) |
|
|
|
|
|
|
|
case 'V': |
|
|
|
v = va_arg (args, f_str_t *); |
|
|
|
|
|
|
|
len = v->len; |
|
|
|
len = (buf + len < last) ? len : (size_t) (last - buf); |
|
|
|
|
|
|
|
buf = ((gchar *)memcpy (buf, v->begin, len)) + len; |
|
|
|
fmt++; |
|
|
|
RSPAMD_PRINTF_APPEND (v->begin, v->len); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
case 'v': |
|
|
|
gs = va_arg (args, GString *); |
|
|
|
len = gs->len; |
|
|
|
len = (buf + len < last) ? len : (size_t) (last - buf); |
|
|
|
|
|
|
|
buf = ((gchar *)memcpy (buf, gs->str, len)) + len; |
|
|
|
fmt++; |
|
|
|
break; |
|
|
|
|
|
|
|
case 's': |
|
|
|
p = va_arg(args, gchar *); |
|
|
|
if (p == NULL) { |
|
|
|
p = "(NULL)"; |
|
|
|
} |
|
|
|
|
|
|
|
if (slen == (size_t) -1) { |
|
|
|
while (*p && buf < last) { |
|
|
|
*buf++ = *p++; |
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
len = (buf + slen < last) ? slen : (size_t) (last - buf); |
|
|
|
|
|
|
|
buf = ((gchar *)memcpy (buf, p, len)) + len; |
|
|
|
} |
|
|
|
|
|
|
|
fmt++; |
|
|
|
RSPAMD_PRINTF_APPEND (gs->str, gs->len); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
case 'S': |
|
|
|
p = va_arg(args, gchar *); |
|
|
|
case 's': |
|
|
|
p = va_arg (args, gchar *); |
|
|
|
if (p == NULL) { |
|
|
|
p = "(NULL)"; |
|
|
|
} |
|
|
|
|
|
|
|
if (slen == (size_t) -1) { |
|
|
|
buf = rspamd_escape_string (buf, p, last - buf); |
|
|
|
|
|
|
|
} else { |
|
|
|
len = (buf + slen < last) ? slen : (size_t) (last - buf); |
|
|
|
|
|
|
|
buf = rspamd_escape_string (buf, p, len); |
|
|
|
if (slen == -1) { |
|
|
|
/* NULL terminated string */ |
|
|
|
slen = strlen (p); |
|
|
|
} |
|
|
|
|
|
|
|
fmt++; |
|
|
|
RSPAMD_PRINTF_APPEND (p, slen); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
@@ -510,57 +542,28 @@ rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args) |
|
|
|
|
|
|
|
|
|
|
|
case 'f': |
|
|
|
f = (double) va_arg (args, double); |
|
|
|
if (f < 0) { |
|
|
|
*buf++ = '-'; |
|
|
|
f = -f; |
|
|
|
case 'F': |
|
|
|
if (*fmt == 'f') { |
|
|
|
f = (long double) va_arg (args, double); |
|
|
|
} |
|
|
|
|
|
|
|
ui64 = (gint64) f; |
|
|
|
|
|
|
|
buf = rspamd_sprintf_num (buf, last, ui64, zero, 0, width); |
|
|
|
|
|
|
|
if (frac_width) { |
|
|
|
|
|
|
|
if (buf < last) { |
|
|
|
*buf++ = '.'; |
|
|
|
} |
|
|
|
|
|
|
|
scale = 1.0; |
|
|
|
|
|
|
|
for (i = 0; i < frac_width; i++) { |
|
|
|
scale *= 10.0; |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
* (gint64) cast is required for msvc6: |
|
|
|
* it can not convert guint64 to double |
|
|
|
*/ |
|
|
|
ui64 = (guint64) ((f - (gint64) ui64) * scale); |
|
|
|
|
|
|
|
buf = rspamd_sprintf_num (buf, last, ui64, '0', 0, frac_width); |
|
|
|
else { |
|
|
|
f = (long double) va_arg (args, long double); |
|
|
|
} |
|
|
|
|
|
|
|
fmt++; |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
case 'F': |
|
|
|
f = (long double) va_arg (args, long double); |
|
|
|
|
|
|
|
p = numbuf; |
|
|
|
last = p + sizeof (numbuf); |
|
|
|
if (f < 0) { |
|
|
|
*buf++ = '-'; |
|
|
|
*p++ = '-'; |
|
|
|
f = -f; |
|
|
|
} |
|
|
|
|
|
|
|
ui64 = (gint64) f; |
|
|
|
|
|
|
|
buf = rspamd_sprintf_num (buf, last, ui64, zero, 0, width); |
|
|
|
p = rspamd_sprintf_num (p, last, ui64, zero, 0, width); |
|
|
|
|
|
|
|
if (frac_width) { |
|
|
|
|
|
|
|
if (buf < last) { |
|
|
|
*buf++ = '.'; |
|
|
|
if (p < last) { |
|
|
|
*p++ = '.'; |
|
|
|
} |
|
|
|
|
|
|
|
scale = 1.0; |
|
|
@@ -575,50 +578,32 @@ rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args) |
|
|
|
*/ |
|
|
|
ui64 = (guint64) ((f - (gint64) ui64) * scale); |
|
|
|
|
|
|
|
buf = rspamd_sprintf_num (buf, last, ui64, '0', 0, frac_width); |
|
|
|
p = rspamd_sprintf_num (p, last, ui64, '0', 0, frac_width); |
|
|
|
} |
|
|
|
|
|
|
|
fmt++; |
|
|
|
slen = p - numbuf; |
|
|
|
RSPAMD_PRINTF_APPEND (numbuf, slen); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
case 'g': |
|
|
|
f = (long double) va_arg (args, double); |
|
|
|
|
|
|
|
if (f < 0) { |
|
|
|
*buf++ = '-'; |
|
|
|
f = -f; |
|
|
|
} |
|
|
|
g_ascii_formatd (buf, last - buf, "%g", (double)f); |
|
|
|
buf += strlen (buf); |
|
|
|
fmt++; |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
case 'b': |
|
|
|
bv = (gboolean) va_arg (args, double); |
|
|
|
if (bv) { |
|
|
|
len = MIN (last - buf, 4); |
|
|
|
memcpy (buf, "true", len); |
|
|
|
case 'G': |
|
|
|
if (*fmt == 'g') { |
|
|
|
f = (long double) va_arg (args, double); |
|
|
|
} |
|
|
|
else { |
|
|
|
len = MIN (last - buf, 5); |
|
|
|
memcpy (buf, "false", len); |
|
|
|
f = (long double) va_arg (args, long double); |
|
|
|
} |
|
|
|
fmt++; |
|
|
|
|
|
|
|
continue; |
|
|
|
g_ascii_formatd (numbuf, sizeof (numbuf), "%g", (double)f); |
|
|
|
slen = strlen (numbuf); |
|
|
|
RSPAMD_PRINTF_APPEND (numbuf, slen); |
|
|
|
|
|
|
|
case 'G': |
|
|
|
f = (long double) va_arg (args, long double); |
|
|
|
continue; |
|
|
|
|
|
|
|
if (f < 0) { |
|
|
|
*buf++ = '-'; |
|
|
|
f = -f; |
|
|
|
} |
|
|
|
g_ascii_formatd (buf, last - buf, "%g", (double)f); |
|
|
|
buf += strlen (buf); |
|
|
|
fmt++; |
|
|
|
case 'b': |
|
|
|
bv = (gboolean) va_arg (args, double); |
|
|
|
RSPAMD_PRINTF_APPEND (bv ? "true" : "false", bv ? 4 : 5); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
@@ -631,39 +616,43 @@ rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args) |
|
|
|
break; |
|
|
|
|
|
|
|
case 'c': |
|
|
|
d = va_arg (args, gint); |
|
|
|
*buf++ = (gchar) (d & 0xff); |
|
|
|
fmt++; |
|
|
|
c = va_arg (args, gint); |
|
|
|
c &= 0xff; |
|
|
|
RSPAMD_PRINTF_APPEND (&c, 1); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
case 'Z': |
|
|
|
*buf++ = '\0'; |
|
|
|
fmt++; |
|
|
|
c = '\0'; |
|
|
|
RSPAMD_PRINTF_APPEND (&c, 1); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
case 'N': |
|
|
|
*buf++ = LF; |
|
|
|
fmt++; |
|
|
|
c = LF; |
|
|
|
RSPAMD_PRINTF_APPEND (&c, 1); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
case '%': |
|
|
|
*buf++ = '%'; |
|
|
|
fmt++; |
|
|
|
c = '%'; |
|
|
|
RSPAMD_PRINTF_APPEND (&c, 1); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
default: |
|
|
|
*buf++ = *fmt++; |
|
|
|
c = *fmt; |
|
|
|
RSPAMD_PRINTF_APPEND (&c, 1); |
|
|
|
|
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
/* Print number */ |
|
|
|
p = numbuf; |
|
|
|
last = p + sizeof (numbuf); |
|
|
|
if (sign) { |
|
|
|
if (i64 < 0) { |
|
|
|
*buf++ = '-'; |
|
|
|
*p++ = '-'; |
|
|
|
ui64 = (guint64) -i64; |
|
|
|
|
|
|
|
} else { |
|
|
@@ -672,19 +661,29 @@ rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args) |
|
|
|
} |
|
|
|
|
|
|
|
if (!humanize) { |
|
|
|
buf = rspamd_sprintf_num (buf, last, ui64, zero, hex, width); |
|
|
|
p = rspamd_sprintf_num (p, last, ui64, zero, hex, width); |
|
|
|
} |
|
|
|
else { |
|
|
|
buf = rspamd_humanize_number (buf, last, ui64, bytes); |
|
|
|
p = rspamd_humanize_number (p, last, ui64, bytes); |
|
|
|
} |
|
|
|
slen = p - numbuf; |
|
|
|
RSPAMD_PRINTF_APPEND (numbuf, slen); |
|
|
|
|
|
|
|
} else { |
|
|
|
fmt++; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
*buf++ = *fmt++; |
|
|
|
/* Finish buffer */ |
|
|
|
if (fmt > buf_start) { |
|
|
|
wr = func (buf_start, fmt - buf_start, apd); |
|
|
|
if (wr <= 0) { |
|
|
|
goto oob; |
|
|
|
} |
|
|
|
written += wr; |
|
|
|
} |
|
|
|
|
|
|
|
return buf; |
|
|
|
oob: |
|
|
|
return written; |
|
|
|
} |
|
|
|
|