diff options
Diffstat (limited to 'pigeonhole/src/lib-sieve/sieve-binary-private.h')
-rw-r--r-- | pigeonhole/src/lib-sieve/sieve-binary-private.h | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/pigeonhole/src/lib-sieve/sieve-binary-private.h b/pigeonhole/src/lib-sieve/sieve-binary-private.h new file mode 100644 index 0000000..73d2d75 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-binary-private.h @@ -0,0 +1,240 @@ +#ifndef SIEVE_BINARY_PRIVATE_H +#define SIEVE_BINARY_PRIVATE_H + +#include "sieve-common.h" +#include "sieve-binary.h" +#include "sieve-extensions.h" + +#include <sys/stat.h> + +#define SIEVE_BINARY_FILE_LOCK_TIMEOUT 10 + +/* + * Binary file + */ + +enum SIEVE_BINARY_FLAGS { + SIEVE_BINARY_FLAG_RESOURCE_LIMIT = BIT(0), +}; + +struct sieve_binary_header { + uint32_t magic; + uint16_t version_major; + uint16_t version_minor; + uint32_t blocks; + + uint32_t hdr_size; + uint32_t flags; + + struct { + uint64_t update_time; + uint32_t cpu_time_msecs; + } resource_usage; +}; + +struct sieve_binary_file { + pool_t pool; + const char *path; + struct sieve_binary *sbin; + + struct stat st; + int fd; + off_t offset; +}; + +void sieve_binary_file_close(struct sieve_binary_file **_file); + +/* + * Internal structures + */ + +/* Extension registration */ + +struct sieve_binary_extension_reg { + /* The identifier of the extension within this binary */ + int index; + + /* Global extension object */ + const struct sieve_extension *extension; + + /* Extension to the binary; typically used to manage extension-specific + blocks in the binary and as a means to get a binary_free notification + to release references held by extensions. + */ + const struct sieve_binary_extension *binext; + + /* Context data associated to the binary by this extension */ + void *context; + + /* Main block for this extension */ + unsigned int block_id; +}; + +/* Block */ + +struct sieve_binary_block { + struct sieve_binary *sbin; + unsigned int id; + int ext_index; + + buffer_t *data; + + uoff_t offset; +}; + +/* + * Binary object + */ + +struct sieve_binary { + pool_t pool; + int refcount; + struct sieve_instance *svinst; + struct event *event; + + struct sieve_script *script; + + struct sieve_binary_file *file; + struct sieve_binary_header header; + struct sieve_resource_usage rusage; + + /* When the binary is loaded into memory or when it is being constructed + by the generator, extensions can be associated to the binary. The + extensions array is a sequential list of all linked extensions. The + extension_index array is a mapping ext_id -> binary_extension. This + is used to obtain the index code associated with an extension for + this particular binary. The linked_extensions list all extensions + linked to this binary object other than the preloaded language + features implemented as 'extensions'. + + All arrays refer to the same extension registration objects. Upon + loading a binary, the 'require'd extensions will sometimes need to + associate context data to the binary object in memory. This is stored + in these registration objects as well. + */ + ARRAY(struct sieve_binary_extension_reg *) extensions; + ARRAY(struct sieve_binary_extension_reg *) extension_index; + ARRAY(struct sieve_binary_extension_reg *) linked_extensions; + + /* Attributes of a loaded binary */ + const char *path; + + /* Blocks */ + ARRAY(struct sieve_binary_block *) blocks; + + bool rusage_updated:1; +}; + +void sieve_binary_update_event(struct sieve_binary *sbin, const char *new_path) + ATTR_NULL(2); + +struct sieve_binary * +sieve_binary_create(struct sieve_instance *svinst, struct sieve_script *script); + +/* Blocks management */ + +static inline struct sieve_binary_block * +sieve_binary_block_index(struct sieve_binary *sbin, unsigned int id) +{ + struct sieve_binary_block * const *sblock; + + if (id >= array_count(&sbin->blocks)) + return NULL; + + sblock = array_idx(&sbin->blocks, id); + if (*sblock == NULL) + return NULL; + return *sblock; +} + +static inline size_t +_sieve_binary_block_get_size(const struct sieve_binary_block *sblock) +{ + return buffer_get_used_size(sblock->data); +} + +struct sieve_binary_block * +sieve_binary_block_create_id(struct sieve_binary *sbin, unsigned int id); + +buffer_t *sieve_binary_block_get_buffer(struct sieve_binary_block *sblock); + +/* Extension registration */ + +static inline struct sieve_binary_extension_reg * +sieve_binary_extension_create_reg(struct sieve_binary *sbin, + const struct sieve_extension *ext) +{ + int index = array_count(&sbin->extensions); + struct sieve_binary_extension_reg *ereg; + + if (ext->id < 0) + return NULL; + + ereg = p_new(sbin->pool, struct sieve_binary_extension_reg, 1); + ereg->index = index; + ereg->extension = ext; + + array_idx_set(&sbin->extensions, (unsigned int) index, &ereg); + array_idx_set(&sbin->extension_index, (unsigned int) ext->id, &ereg); + + return ereg; +} + +static inline struct sieve_binary_extension_reg * +sieve_binary_extension_get_reg(struct sieve_binary *sbin, + const struct sieve_extension *ext, + bool create) +{ + struct sieve_binary_extension_reg *reg = NULL; + + if (ext->id >= 0 && + ext->id < (int)array_count(&sbin->extension_index)) { + struct sieve_binary_extension_reg * const *ereg = + array_idx(&sbin->extension_index, + (unsigned int)ext->id); + + reg = *ereg; + } + + /* Register if not known */ + if (reg == NULL && create) + return sieve_binary_extension_create_reg(sbin, ext); + return reg; +} + +static inline int +sieve_binary_extension_register(struct sieve_binary *sbin, + const struct sieve_extension *ext, + struct sieve_binary_extension_reg **reg_r) +{ + struct sieve_binary_extension_reg *ereg; + + if ((ereg = sieve_binary_extension_get_reg(sbin, ext, FALSE)) == NULL) { + ereg = sieve_binary_extension_create_reg(sbin, ext); + + if (ereg == NULL) + return -1; + + array_append(&sbin->linked_extensions, &ereg, 1); + } + + if (reg_r != NULL) + *reg_r = ereg; + return ereg->index; +} + +/* Load/Save */ + +bool sieve_binary_load_block(struct sieve_binary_block *); + +/* + * Resource limits + */ + +bool sieve_binary_check_resource_usage(struct sieve_binary *sbin); + +int sieve_binary_file_update_resource_usage(struct sieve_binary *sbin, + enum sieve_error *error_r) + ATTR_NULL(2); + +#endif |