This increases the size of struct output_ctx quite a bit, but allows to
simplify internal functions dealing with the cookies mainly because
output_fp becomes accessible from struct cookie.

Signed-off-by: Phil Sutter <p...@nwl.cc>
---
 include/nftables.h | 15 ++++++---
 src/libnftables.c  | 95 +++++++++++++++++++-----------------------------------
 2 files changed, 44 insertions(+), 66 deletions(-)

diff --git a/include/nftables.h b/include/nftables.h
index 5c181be5a4ec3..75134def9b8d4 100644
--- a/include/nftables.h
+++ b/include/nftables.h
@@ -8,10 +8,11 @@
 #include <nftables/nftables.h>
 
 struct cookie {
+       FILE *fp;
+       FILE *orig_fp;
        char *buf;
        size_t buflen;
        size_t pos;
-       FILE *orig_fp;
 };
 
 struct output_ctx {
@@ -20,10 +21,14 @@ struct output_ctx {
        unsigned int ip2name;
        unsigned int handle;
        unsigned int echo;
-       FILE *output_fp;
-       FILE *error_fp;
-       struct cookie *output_cookie;
-       struct cookie *error_cookie;
+       union {
+               FILE *output_fp;
+               struct cookie output_cookie;
+       };
+       union {
+               FILE *error_fp;
+               struct cookie error_cookie;
+       };
 };
 
 struct nft_cache {
diff --git a/src/libnftables.c b/src/libnftables.c
index 73363e3a32f87..44e06e1a50835 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -177,14 +177,6 @@ struct nft_ctx *nft_ctx_new(uint32_t flags)
        return ctx;
 }
 
-static void free_cookie(struct cookie *cookie)
-{
-       if (cookie) {
-               free(cookie->buf);
-               free(cookie);
-       }
-}
-
 static ssize_t cookie_write(void *cptr, const char *buf, size_t buflen)
 {
        struct cookie *cookie = cptr;
@@ -208,20 +200,13 @@ static ssize_t cookie_write(void *cptr, const char *buf, 
size_t buflen)
        return buflen;
 }
 
-static int init_cookie(struct cookie **cpptr, FILE **fp)
+static int init_cookie(struct cookie *cookie)
 {
-       struct cookie *cookie;
        cookie_io_functions_t cookie_fops = {
                .write = cookie_write,
        };
-       FILE *cookie_fp;
-
-       if (!cpptr || !fp)
-               return 1;
-
-       cookie = *cpptr;
 
-       if (cookie) { /* just rewind buffer */
+       if (cookie->orig_fp) { /* just rewind buffer */
                if (cookie->buflen) {
                        cookie->pos = 0;
                        cookie->buf[0] = '\0';
@@ -229,69 +214,61 @@ static int init_cookie(struct cookie **cpptr, FILE **fp)
                return 0;
        }
 
-       cookie = xzalloc(sizeof(*cookie));
-       cookie->orig_fp = *fp;
+       cookie->orig_fp = cookie->fp;
 
-       cookie_fp = fopencookie(cookie, "w", cookie_fops);
-       if (!cookie_fp) {
-               free(cookie);
+       cookie->fp = fopencookie(cookie, "w", cookie_fops);
+       if (!cookie->fp) {
+               cookie->fp = cookie->orig_fp;
                return 1;
        }
 
-       *cpptr = cookie;
-       *fp = cookie_fp;
        return 0;
 }
 
-int nft_ctx_buffer_output(struct nft_ctx *ctx)
+static int exit_cookie(struct cookie *cookie)
 {
-       struct output_ctx *octx = &ctx->output;
+       if (!cookie->orig_fp)
+               return 1;
 
-       return init_cookie(&octx->output_cookie, &octx->output_fp);
+       fclose(cookie->fp);
+       cookie->fp = cookie->orig_fp;
+       free(cookie->buf);
+       cookie->buf = NULL;
+       cookie->buflen = 0;
+       cookie->pos = 0;
+       return 0;
 }
 
-int nft_ctx_unbuffer_output(struct nft_ctx *ctx)
+int nft_ctx_buffer_output(struct nft_ctx *ctx)
 {
-       if (!ctx->output.output_cookie)
-               return 1;
+       return init_cookie(&ctx->output.output_cookie);
+}
 
-       ctx->output.output_fp = ctx->output.output_cookie->orig_fp;
-       free_cookie(ctx->output.output_cookie);
-       ctx->output.output_cookie = NULL;
-       return 0;
+int nft_ctx_unbuffer_output(struct nft_ctx *ctx)
+{
+       return exit_cookie(&ctx->output.output_cookie);
 }
 
 int nft_ctx_buffer_error(struct nft_ctx *ctx)
 {
-       struct output_ctx *octx = &ctx->output;
-
-       return init_cookie(&octx->error_cookie, &octx->error_fp);
+       return init_cookie(&ctx->output.error_cookie);
 }
 
 int nft_ctx_unbuffer_error(struct nft_ctx *ctx)
 {
-       if (!ctx->output.error_cookie)
-               return 1;
-
-       ctx->output.error_fp = ctx->output.error_cookie->orig_fp;
-       free_cookie(ctx->output.error_cookie);
-       ctx->output.error_cookie = NULL;
-       return 0;
+       return exit_cookie(&ctx->output.error_cookie);
 }
 
-static const char *get_cookie_buffer(struct cookie *cookie, FILE *cookie_fp)
+static const char *get_cookie_buffer(struct cookie *cookie)
 {
-       if (!cookie)
-               return NULL;
-
-       fflush(cookie_fp);
+       fflush(cookie->fp);
 
        /* This is a bit tricky: Rewind the buffer for future use and return
-        * the old content at the same time.
-        * Therefore just reset buffer position, don't change it's content. And
-        * return an empty string if buffer position is zero. */
+        * the old content at the same time. Therefore return an empty string
+        * if buffer position is zero, otherwise just rewind buffer position
+        * and return the unmodified buffer. */
 
-       if (!cookie->buflen || !cookie->pos)
+       if (!cookie->pos)
                return "";
 
        cookie->pos = 0;
@@ -300,16 +277,12 @@ static const char *get_cookie_buffer(struct cookie 
*cookie, FILE *cookie_fp)
 
 const char *nft_ctx_get_output_buffer(struct nft_ctx *ctx)
 {
-       struct output_ctx *octx = &ctx->output;
-
-       return get_cookie_buffer(octx->output_cookie, octx->output_fp);
+       return get_cookie_buffer(&ctx->output.output_cookie);
 }
 
 const char *nft_ctx_get_error_buffer(struct nft_ctx *ctx)
 {
-       struct output_ctx *octx = &ctx->output;
-
-       return get_cookie_buffer(octx->error_cookie, octx->error_fp);
+       return get_cookie_buffer(&ctx->output.error_cookie);
 }
 
 void nft_ctx_free(struct nft_ctx *ctx)
@@ -317,8 +290,8 @@ void nft_ctx_free(struct nft_ctx *ctx)
        if (ctx->nf_sock)
                netlink_close_sock(ctx->nf_sock);
 
-       free_cookie(ctx->output.output_cookie);
-       free_cookie(ctx->output.error_cookie);
+       exit_cookie(&ctx->output.output_cookie);
+       exit_cookie(&ctx->output.error_cookie);
        iface_cache_release();
        cache_release(&ctx->cache);
        nft_ctx_clear_include_paths(ctx);
-- 
2.16.1

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to