]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib,lib-storage: Move hook building code to lib
authorAki Tuomi <aki.tuomi@dovecot.fi>
Mon, 20 Feb 2017 13:28:36 +0000 (15:28 +0200)
committerAki Tuomi <aki.tuomi@dovecot.fi>
Mon, 20 Feb 2017 15:15:54 +0000 (17:15 +0200)
This allows it to be reused elsewhere

src/lib-storage/mail-storage-hooks.c
src/lib/Makefile.am
src/lib/hook-build.c [new file with mode: 0644]
src/lib/hook-build.h [new file with mode: 0644]

index cef47f265c163fe884f458c842e0816e7ab52198..c91ed18a9f14080bf4aa14bd636f283752596aac 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "array.h"
+#include "hook-build.h"
 #include "llist.h"
 #include "module-dir.h"
 #include "mail-user.h"
@@ -15,28 +16,6 @@ struct mail_storage_module_hooks {
        bool forced;
 };
 
-struct hook_stack {
-       struct hook_stack *prev, *next;
-
-       /* Pointer to vfuncs struct. This assumes that a struct containing
-          function pointers equals to an array of function pointers. Not
-          ANSI-C, but should work in all OSes supported by Dovecot. Much
-          easier anyway than doing this work manually.. */
-       void (**vfuncs)();
-       /* nonzero in the areas where vfuncs has been changed */
-       void (**mask)();
-};
-
-struct hook_build_context {
-       pool_t pool;
-       /* size of the vfuncs struct */
-       size_t size;
-       /* number of function pointers in the struct */
-       unsigned int count;
-
-       struct hook_stack *head, *tail;
-};
-
 static ARRAY(struct mail_storage_module_hooks) module_hooks = ARRAY_INIT;
 static ARRAY(const struct mail_storage_hooks *) internal_hooks = ARRAY_INIT;
 
@@ -176,93 +155,6 @@ static void mail_user_add_plugin_hooks(struct mail_user *user)
        array_append_array(&user->hooks, &internal_hooks);
 }
 
-static void hook_build_append(struct hook_build_context *ctx, void (**vfuncs)())
-{
-       struct hook_stack *stack;
-
-       stack = p_new(ctx->pool, struct hook_stack, 1);
-       stack->vfuncs = vfuncs;
-       stack->mask = p_malloc(ctx->pool, ctx->size);
-       DLLIST2_APPEND(&ctx->head, &ctx->tail, stack);
-}
-
-static struct hook_build_context *
-hook_build_init(void (**vfuncs)(), size_t size)
-{
-       struct hook_build_context *ctx;
-       pool_t pool;
-
-       i_assert((size % sizeof(void (*)())) == 0);
-
-       pool = pool_alloconly_create("hook build context", 2048);
-       ctx = p_new(pool, struct hook_build_context, 1);
-       ctx->pool = pool;
-       ctx->size = size;
-       ctx->count = size / sizeof(void (*)());
-       hook_build_append(ctx, vfuncs);
-       return ctx;
-}
-
-static void
-hook_update_mask(struct hook_build_context *ctx, struct hook_stack *stack,
-                void (**vlast)())
-{
-       unsigned int i;
-
-       for (i = 0; i < ctx->count; i++) {
-               if (stack->vfuncs[i] != vlast[i]) {
-                       i_assert(stack->vfuncs[i] != NULL);
-                       stack->mask[i] = stack->vfuncs[i];
-               }
-       }
-}
-
-static void
-hook_copy_stack(struct hook_build_context *ctx, struct hook_stack *stack)
-{
-       unsigned int i;
-
-       i_assert(stack->next != NULL);
-
-       for (i = 0; i < ctx->count; i++) {
-               if (stack->mask[i] == NULL) {
-                       stack->vfuncs[i] = stack->next->vfuncs[i];
-                       stack->mask[i] = stack->next->mask[i];
-               }
-       }
-}
-
-static void hook_build_update(struct hook_build_context *ctx, void *_vlast)
-{
-       void (**vlast)() = _vlast;
-       struct hook_stack *stack;
-
-       if (ctx->tail->vfuncs == vlast) {
-               /* no vfuncs overridden */
-               return;
-       }
-
-       /* ctx->vfuncs_stack->vfuncs points to the root vfuncs,
-          ctx->vfuncs_stack->next->vfuncs points to the first super function
-          that is being called, and so on.
-
-          the previous plugin added its vfuncs to the stack tail.
-          vlast contains the previous plugin's super vfuncs, which is where
-          the next plugin should put its own vfuncs.
-
-          first we'll need to figure out what vfuncs the previous plugin
-          changed and update the mask */
-       hook_update_mask(ctx, ctx->tail, vlast);
-
-       /* now go up in the stack as long as the mask isn't set,
-          and update the vfuncs */
-       for (stack = ctx->tail->prev; stack != NULL; stack = stack->prev)
-               hook_copy_stack(ctx, stack);
-
-       /* add vlast to stack */
-       hook_build_append(ctx, vlast);
-}
-
 void hook_mail_user_created(struct mail_user *user)
 {
        const struct mail_storage_hooks *const *hooks;
@@ -279,7 +171,7 @@ void hook_mail_user_created(struct mail_user *user)
                } T_END;
        }
        user->vlast = NULL;
-       pool_unref(&ctx->pool);
+       hook_build_deinit(&ctx);
 }
 
 void hook_mail_namespace_storage_added(struct mail_namespace *ns)
@@ -333,7 +225,7 @@ void hook_mail_storage_created(struct mail_storage *storage)
                } T_END;
        }
        storage->vlast = NULL;
-       pool_unref(&ctx->pool);
+       hook_build_deinit(&ctx);
 }
 
 void hook_mailbox_list_created(struct mailbox_list *list)
@@ -350,7 +242,7 @@ void hook_mailbox_list_created(struct mailbox_list *list)
                } T_END;
        }
        list->vlast = NULL;
-       pool_unref(&ctx->pool);
+       hook_build_deinit(&ctx);
 }
 
 void hook_mailbox_allocated(struct mailbox *box)
@@ -367,7 +259,7 @@ void hook_mailbox_allocated(struct mailbox *box)
                } T_END;
        }
        box->vlast = NULL;
-       pool_unref(&ctx->pool);
+       hook_build_deinit(&ctx);
 }
 
 void hook_mailbox_opened(struct mailbox *box)
@@ -396,5 +288,5 @@ void hook_mail_allocated(struct mail *mail)
                } T_END;
        }
        pmail->vlast = NULL;
-       pool_unref(&ctx->pool);
+       hook_build_deinit(&ctx);
 }
index 54308b28cfc5a89a5accfdc4d0d5ffe01e3f306f..eaaf63469121ede862cff37d3596b985f321a504 100644 (file)
@@ -49,6 +49,7 @@ liblib_la_SOURCES = \
        hmac.c \
        hmac-cram-md5.c \
        home-expand.c \
+       hook-build.c \
        hostpid.c \
        imem.c \
        ipwd.c \
@@ -199,6 +200,7 @@ headers = \
        hmac.h \
        hmac-cram-md5.h \
        home-expand.h \
+       hook-build.h \
        hostpid.h \
        imem.h \
        ipwd.h \
diff --git a/src/lib/hook-build.c b/src/lib/hook-build.c
new file mode 100644 (file)
index 0000000..86c8489
--- /dev/null
@@ -0,0 +1,121 @@
+/* Copyright (c) 2009-2017 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "llist.h"
+#include "hook-build.h"
+
+struct hook_stack {
+       struct hook_stack *prev, *next;
+
+       /* Pointer to vfuncs struct. This assumes that a struct containing
+          function pointers equals to an array of function pointers. Not
+          ANSI-C, but should work in all OSes supported by Dovecot. Much
+          easier anyway than doing this work manually.. */
+       void (**vfuncs)();
+       /* nonzero in the areas where vfuncs has been changed */
+       void (**mask)();
+};
+
+struct hook_build_context {
+       pool_t pool;
+       /* size of the vfuncs struct */
+       size_t size;
+       /* number of function pointers in the struct */
+       unsigned int count;
+
+       struct hook_stack *head, *tail;
+};
+
+static void hook_build_append(struct hook_build_context *ctx, void (**vfuncs)())
+{
+       struct hook_stack *stack;
+
+       stack = p_new(ctx->pool, struct hook_stack, 1);
+       stack->vfuncs = vfuncs;
+       stack->mask = p_malloc(ctx->pool, ctx->size);
+       DLLIST2_APPEND(&ctx->head, &ctx->tail, stack);
+}
+
+struct hook_build_context *hook_build_init(void (**vfuncs)(), size_t size)
+{
+       struct hook_build_context *ctx;
+       pool_t pool;
+
+       i_assert((size % sizeof(void (*)())) == 0);
+
+       pool = pool_alloconly_create("hook build context", 2048);
+       ctx = p_new(pool, struct hook_build_context, 1);
+       ctx->pool = pool;
+       ctx->size = size;
+       ctx->count = size / sizeof(void (*)());
+       hook_build_append(ctx, vfuncs);
+       return ctx;
+}
+
+static void
+hook_update_mask(struct hook_build_context *ctx, struct hook_stack *stack,
+                void (**vlast)())
+{
+       unsigned int i;
+
+       for (i = 0; i < ctx->count; i++) {
+               if (stack->vfuncs[i] != vlast[i]) {
+                       i_assert(stack->vfuncs[i] != NULL);
+                       stack->mask[i] = stack->vfuncs[i];
+               }
+       }
+}
+
+static void
+hook_copy_stack(struct hook_build_context *ctx, struct hook_stack *stack)
+{
+       unsigned int i;
+
+       i_assert(stack->next != NULL);
+
+       for (i = 0; i < ctx->count; i++) {
+               if (stack->mask[i] == NULL) {
+                       stack->vfuncs[i] = stack->next->vfuncs[i];
+                       stack->mask[i] = stack->next->mask[i];
+               }
+       }
+}
+
+void hook_build_update(struct hook_build_context *ctx, void *_vlast)
+{
+       void (**vlast)() = _vlast;
+       struct hook_stack *stack;
+
+       if (ctx->tail->vfuncs == vlast) {
+               /* no vfuncs overridden */
+               return;
+       }
+
+       /* ctx->vfuncs_stack->vfuncs points to the root vfuncs,
+          ctx->vfuncs_stack->next->vfuncs points to the first super function
+          that is being called, and so on.
+
+          the previous plugin added its vfuncs to the stack tail.
+          vlast contains the previous plugin's super vfuncs, which is where
+          the next plugin should put its own vfuncs.
+
+          first we'll need to figure out what vfuncs the previous plugin
+          changed and update the mask */
+       hook_update_mask(ctx, ctx->tail, vlast);
+
+       /* now go up in the stack as long as the mask isn't set,
+          and update the vfuncs */
+       for (stack = ctx->tail->prev; stack != NULL; stack = stack->prev)
+               hook_copy_stack(ctx, stack);
+
+       /* add vlast to stack */
+       hook_build_append(ctx, vlast);
+}
+
+void hook_build_deinit(struct hook_build_context **_ctx)
+{
+       struct hook_build_context *ctx = *_ctx;
+       *_ctx = NULL;
+       pool_unref(&ctx->pool);
+}
diff --git a/src/lib/hook-build.h b/src/lib/hook-build.h
new file mode 100644 (file)
index 0000000..f583bfb
--- /dev/null
@@ -0,0 +1,19 @@
+/* Copyright (c) 2017 Dovecot authors, see the included COPYING file */
+#ifndef HOOK_BUILD_H
+#define HOOK_BUILD_H 1
+
+struct hook_build_context;
+struct hook_stack;
+
+/* Initialize new hook building context, vfuncs should point to
+   the functions table that is being manipulated, and size should be
+   the size of this table. */
+struct hook_build_context *hook_build_init(void (**vfuncs)(), size_t size);
+
+/* This is called after a hook may have updated vfuncs */
+void hook_build_update(struct hook_build_context *ctx, void *_vlast);
+
+/* Free memory used by build context */
+void hook_build_deinit(struct hook_build_context **_ctx);
+
+#endif