#ifndef SIEVE_BINARY_PRIVATE_H #define SIEVE_BINARY_PRIVATE_H #include "sieve-common.h" #include "sieve-binary.h" #include "sieve-extensions.h" #include #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