/* Handle printing failures */
static jmp_buf printf_failure;
-static int __attribute__((format(printf, 2, 3)))
-safe_snprintf(struct ipset_session *session, const char *fmt, ...)
+static int
+handle_snprintf_error(struct ipset_session *session,
+ int len, int ret, int loop)
{
- va_list args;
- int len, ret, loop = 0;
-
-retry:
- len = strlen(session->outbuf);
- D("len: %u, retry %u", len, loop);
- va_start(args, fmt);
- ret = vsnprintf(session->outbuf + len, IPSET_OUTBUFLEN - len,
- fmt, args);
- va_end(args);
-
if (ret < 0 || ret >= IPSET_OUTBUFLEN - len) {
/* Buffer was too small, push it out and retry */
- D("print buffer and try again: %u", len);
- if (loop++) {
+ D("print buffer and try again: len: %u, ret: %d", len, ret);
+ if (loop) {
ipset_err(session,
"Internal error at printing, loop detected!");
longjmp(printf_failure, 1);
}
session->outbuf[len] = '\0';
- if (!call_outfn(session))
- goto retry;
+ if (call_outfn(session)) {
+ ipset_err(session,
+ "Internal error, could not print output buffer!");
+ longjmp(printf_failure, 1);
+ }
+ return 1;
}
+ return 0;
+}
+
+static int __attribute__((format(printf, 2, 3)))
+safe_snprintf(struct ipset_session *session, const char *fmt, ...)
+{
+ va_list args;
+ int len, ret, loop = 0;
+
+ do {
+ len = strlen(session->outbuf);
+ D("len: %u, retry %u", len, loop);
+ va_start(args, fmt);
+ ret = vsnprintf(session->outbuf + len,
+ IPSET_OUTBUFLEN - len,
+ fmt, args);
+ va_end(args);
+ loop = handle_snprintf_error(session, len, ret, loop);
+ } while (loop);
+
return ret;
}
{
int len, ret, loop = 0;
-retry:
- len = strlen(session->outbuf);
- D("len: %u, retry %u", len, loop);
- ret = fn(session->outbuf + len, IPSET_OUTBUFLEN - len,
- session->data, opt, session->envopts);
-
- if (ret < 0 || ret >= IPSET_OUTBUFLEN - len) {
- /* Buffer was too small, push it out and retry */
- D("print buffer and try again: %u", len);
- if (loop++) {
- ipset_err(session,
- "Internal error at printing, loop detected!");
- longjmp(printf_failure, 1);
- }
+ do {
+ len = strlen(session->outbuf);
+ D("len: %u, retry %u", len, loop);
+ ret = fn(session->outbuf + len, IPSET_OUTBUFLEN - len,
+ session->data, opt, session->envopts);
+ loop = handle_snprintf_error(session, len, ret, loop);
+ } while (loop);
- session->outbuf[len] = '\0';
- if (!call_outfn(session))
- goto retry;
- }
return ret;
}