diff --git a/src/lib-sieve/plugins/include/cmd-include.c b/src/lib-sieve/plugins/include/cmd-include.c index cffd608dcb1c49aef08f0c6bd3b96dac11206114..40ae8c8ed1a53e1c5b9462cd261b08f5f078a659 100644 --- a/src/lib-sieve/plugins/include/cmd-include.c +++ b/src/lib-sieve/plugins/include/cmd-include.c @@ -162,7 +162,6 @@ static bool cmd_include_validate(struct sieve_validator *validator, struct cmd_include_context_data *ctx_data = (struct cmd_include_context_data *) cmd->data; const char *script_name, *script_path; - struct sieve_script *script; struct sieve_ast *ast; if ( !sieve_validate_positional_argument @@ -185,17 +184,12 @@ static bool cmd_include_validate(struct sieve_validator *validator, else return FALSE; - script = sieve_script_create(script_path, script_name); - /* Validate */ if ( !ext_include_validate_include - (validator, cmd, script, &ast) ) { - sieve_script_unref(&script); + (validator, cmd, script_path, script_name, &ast) ) { return FALSE; } - - sieve_script_unref(&script); - + ctx_data->ast = ast; sieve_validator_argument_activate(validator, arg); diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c index 4e6394ffaafbcc41dec352119f681c2de38972f2..f9bfda0b62d7f1524894750aad01e907cd8b6d20 100644 --- a/src/lib-sieve/plugins/include/ext-include-common.c +++ b/src/lib-sieve/plugins/include/ext-include-common.c @@ -70,9 +70,10 @@ void ext_include_register_validator_context bool ext_include_validate_include (struct sieve_validator *validator, struct sieve_command_context *cmd, - struct sieve_script *script, struct sieve_ast **ast_r) + const char *script_path, const char *script_name, struct sieve_ast **ast_r) { bool result = TRUE; + struct sieve_script *script; struct sieve_validator *subvalid; struct ext_include_validator_context *parent = ext_include_get_validator_context(validator); @@ -80,6 +81,11 @@ bool ext_include_validate_include struct sieve_error_handler *ehandler = sieve_validator_get_error_handler(validator); + /* Create script object */ + if ( (script = sieve_script_create(script_path, script_name, ehandler)) + == NULL ) + return FALSE; + *ast_r = NULL; /* Check for circular include */ @@ -89,21 +95,26 @@ bool ext_include_validate_include if ( sieve_script_equals(ctx->script, script) ) { sieve_command_validate_error (validator, cmd, "circular include"); + + sieve_script_unref(&script); return FALSE; } ctx = ctx->parent; - } + } /* Parse script */ if ( (*ast_r = sieve_parse(script, ehandler)) == NULL ) { sieve_command_validate_error - (validator, cmd, "parse failed for included script '%s'", - sieve_script_name(script)); + (validator, cmd, "parse failed for included script '%s'", script_name); + sieve_script_unref(&script); return FALSE; } + /* AST now holds a reference, so we can drop it already */ + sieve_script_unref(&script); + /* Validate script */ subvalid = sieve_validator_create(*ast_r, ehandler); @@ -113,7 +124,7 @@ bool ext_include_validate_include if ( !sieve_validator_run(subvalid) || sieve_get_errors(ehandler) > 0 ) { sieve_command_validate_error (validator, cmd, "validation failed for included script '%s'", - sieve_script_name(script)); + script_name); sieve_ast_unref(ast_r); result = FALSE; } diff --git a/src/lib-sieve/plugins/include/ext-include-common.h b/src/lib-sieve/plugins/include/ext-include-common.h index f7e89a3fa491d167134aafaa06997b81b65c13a1..b4f1d51c2e6d147974fbd2f8fa2f3c4fcb3e5ef4 100644 --- a/src/lib-sieve/plugins/include/ext-include-common.h +++ b/src/lib-sieve/plugins/include/ext-include-common.h @@ -29,7 +29,7 @@ void ext_include_register_validator_context (struct sieve_validator *validator, struct sieve_script *script); bool ext_include_validate_include -(struct sieve_validator *validator, struct sieve_command_context *cmd, - struct sieve_script *script, struct sieve_ast **ast_r); + (struct sieve_validator *validator, struct sieve_command_context *cmd, + const char *script_path, const char *script_name, struct sieve_ast **ast_r); #endif /* __EXT_INCLUDE_COMMON_H */ diff --git a/src/lib-sieve/plugins/include/included3.sieve b/src/lib-sieve/plugins/include/included3.sieve index 08a6621edf5892cf2f0dce58e9abdb7984cc8a04..720364ed54e55be1beb9562d3bde825554818530 100644 --- a/src/lib-sieve/plugins/include/included3.sieve +++ b/src/lib-sieve/plugins/include/included3.sieve @@ -1 +1,4 @@ -discard +require "include"; + +include "include"; +discard; diff --git a/src/lib-sieve/sieve-lexer.c b/src/lib-sieve/sieve-lexer.c index f6e87ac232456e1780435bdabfebe8c94018a86a..db4285073bbc3628c5d3b53d311fa7e4b7fe5126 100644 --- a/src/lib-sieve/sieve-lexer.c +++ b/src/lib-sieve/sieve-lexer.c @@ -80,7 +80,7 @@ struct sieve_lexer *sieve_lexer_create struct sieve_lexer *lexer; struct istream *stream; - stream = sieve_script_open(script, ehandler); + stream = sieve_script_open(script); if ( stream == NULL ) return NULL; diff --git a/src/lib-sieve/sieve-script.c b/src/lib-sieve/sieve-script.c index 55ba5fa39a12973167e641b4307244cb241a00fb..3c472e939f84d0b3133d39a44e56de3840d031ad 100644 --- a/src/lib-sieve/sieve-script.c +++ b/src/lib-sieve/sieve-script.c @@ -13,6 +13,10 @@ struct sieve_script { pool_t pool; unsigned int refcount; + struct stat st; + + struct sieve_error_handler *ehandler; + /* Parameters */ const char *name; const char *path; @@ -25,17 +29,32 @@ struct sieve_script { /* Script object */ struct sieve_script *sieve_script_create - (const char *path, const char *name) + (const char *path, const char *name, struct sieve_error_handler *ehandler) { pool_t pool; + struct stat st; struct sieve_script *script; + /* First obtain stat data from the system */ + + if ( stat(path, &st) < 0 ) { + if ( errno == ENOENT ) + sieve_error(ehandler, name, "sieve script does not exist"); + else + sieve_critical(ehandler, path, "failed to stat sieve script: %m"); + return NULL; + } + + /* Only create object if it stat()s without problems */ + pool = pool_alloconly_create("sieve_script", 1024); script = p_new(pool, struct sieve_script, 1); script->pool = pool; script->refcount = 1; + script->ehandler = ehandler; - script->path = p_strdup(pool, path); + memcpy((void *) &script->st, (void *) &st, sizeof(st)); + script->path = p_strdup(pool, path); if ( name == NULL || *name == '\0' ) { const char *filename, *ext; @@ -84,17 +103,18 @@ void sieve_script_unref(struct sieve_script **script) /* Stream manageement */ -struct istream *sieve_script_open(struct sieve_script *script, - struct sieve_error_handler *ehandler) +struct istream *sieve_script_open(struct sieve_script *script) { int fd; if ( (fd=open(script->path, O_RDONLY)) < 0 ) { - if ( errno == ENOENT ) - sieve_error(ehandler, script->path, "sieve script '%s' does not exist", - script->name); - else - sieve_critical(ehandler, script->path, "failed to open sieve script: %m"); + if ( errno == ENOENT ) + /* Not supposed to occur, create() does stat already */ + sieve_error(script->ehandler, script->name, + "sieve script '%s' does not exist", script->name); + else + sieve_critical(script->ehandler, script->path, + "failed to open sieve script: %m"); return NULL; } @@ -112,8 +132,8 @@ void sieve_script_close(struct sieve_script *script) bool sieve_script_equals (struct sieve_script *script1, struct sieve_script *script2) -{ - return ( strcmp(script1->path, script2->path) == 0 ); +{ + return ( script1->st.st_ino == script2->st.st_ino ); } /* Inline accessors */ diff --git a/src/lib-sieve/sieve-script.h b/src/lib-sieve/sieve-script.h index 1266d17576b524845156477aee7fa938a182ec04..44ffb8ca43970e721994c7f4f684a940b6c09047 100644 --- a/src/lib-sieve/sieve-script.h +++ b/src/lib-sieve/sieve-script.h @@ -7,15 +7,15 @@ struct sieve_script; -struct sieve_script *sieve_script_create(const char *path, const char *name); +struct sieve_script *sieve_script_create + (const char *path, const char *name, struct sieve_error_handler *ehandler); void sieve_script_ref(struct sieve_script *script); void sieve_script_unref(struct sieve_script **script); /* Stream manageement */ -struct istream *sieve_script_open(struct sieve_script *script, - struct sieve_error_handler *ehandler); +struct istream *sieve_script_open(struct sieve_script *script); void sieve_script_close(struct sieve_script *script); bool sieve_script_equals diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c index ebbbd89d045db6906aa90bb6b637f755cbff0946..42cd6fee45495c3ee04fe4d8586beea930a642ee 100644 --- a/src/lib-sieve/sieve.c +++ b/src/lib-sieve/sieve.c @@ -125,7 +125,8 @@ struct sieve_binary *sieve_compile struct sieve_script *script; struct sieve_binary *sbin; - script = sieve_script_create(script_path, NULL); + if ( (script = sieve_script_create(script_path, NULL, ehandler)) == NULL ) + return NULL; sbin = sieve_compile_script(script, ehandler);