90
93
possibility of that happening is if time had moved
91
94
backwards, but even then it's highly unlikely. */
92
95
if (stat(str_c(path), &st) == 0) {
93
/* try another file name */
96
/* try another file name */
94
97
} else if (errno != ENOENT) {
95
98
sieve_storage_set_critical(storage,
96
99
"stat(%s) failed: %m", str_c(path));
171
174
if ( scriptname != NULL ) {
172
175
/* Validate script name */
173
176
if ( !sieve_script_name_is_valid(scriptname) ) {
174
sieve_storage_set_error(storage,
177
sieve_storage_set_error(storage,
175
178
SIEVE_ERROR_BAD_PARAMS,
176
179
"Invalid script name '%s'.", scriptname);
180
/* Prevent overwriting the active script link when it resides in the
183
/* Prevent overwriting the active script link when it resides in the
181
184
* sieve storage directory.
183
186
if ( *(storage->link_path) == '\0' ) {
187
190
svext = strrchr(storage->active_fname, '.');
188
191
namelen = svext - storage->active_fname;
189
192
if ( svext != NULL && strncmp(svext+1, "sieve", 5) == 0 &&
190
strlen(scriptname) == namelen &&
191
strncmp(scriptname, storage->active_fname, namelen) == 0 )
193
strlen(scriptname) == namelen &&
194
strncmp(scriptname, storage->active_fname, namelen) == 0 )
193
196
sieve_storage_set_error(
194
storage, SIEVE_ERROR_BAD_PARAMS,
195
"Script name '%s' is reserved for internal use.", scriptname);
197
storage, SIEVE_ERROR_BAD_PARAMS,
198
"Script name '%s' is reserved for internal use.", scriptname);
202
205
ctx = p_new(pool, struct sieve_save_context, 1);
203
206
ctx->pool = pool;
204
207
ctx->storage = storage;
205
ctx->scriptname = scriptname;
208
ctx->scriptname = p_strdup(pool, scriptname);
206
209
ctx->scriptobject = NULL;
210
ctx->mtime = (time_t)-1;
209
213
ctx->fd = sieve_storage_create_tmp(storage, scriptname, &path);
278
282
return ( ctx->failed ? -1 : 0 );
285
void sieve_storage_save_set_mtime
286
(struct sieve_save_context *ctx, time_t mtime)
281
291
static void sieve_storage_save_destroy(struct sieve_save_context **ctx)
283
293
if ((*ctx)->scriptobject != NULL)
290
300
struct sieve_script *sieve_storage_save_get_tempscript
291
301
(struct sieve_save_context *ctx)
293
const char *scriptname =
294
( ctx->scriptname == NULL ? "" : ctx->scriptname );
303
const char *scriptname =
304
( ctx->scriptname == NULL ? "" : ctx->scriptname );
299
309
if ( ctx->scriptobject != NULL )
300
310
return ctx->scriptobject;
302
312
ctx->scriptobject = sieve_storage_script_init_from_path
303
(ctx->storage, ctx->tmp_path, scriptname);
313
(ctx->storage, ctx->tmp_path, scriptname);
305
315
if ( ctx->scriptobject == NULL ) {
306
316
if ( ctx->storage->error_code == SIEVE_ERROR_NOT_FOUND ) {
307
sieve_storage_set_critical(ctx->storage,
308
"save: Temporary script file with name '%s' got lost, "
309
"which should not happen (possibly deleted externally).",
317
sieve_storage_set_critical(ctx->storage,
318
"save: Temporary script file '%s' got lost, "
319
"which should not happen (possibly deleted externally).",
324
334
const char *scriptname;
327
ret = sieve_storage_get_active_scriptfile(ctx->storage, &scriptname);
337
ret = sieve_storage_active_script_get_name(ctx->storage, &scriptname);
329
/* Is the requested script active? */
339
/* Is the requested script active? */
330
340
result = ( strcmp(ctx->scriptname, scriptname) == 0 );
337
int sieve_storage_save_commit(struct sieve_save_context **ctx)
347
static void sieve_storage_update_mtime(const char *path, time_t mtime)
349
struct utimbuf times = { .actime = mtime, .modtime = mtime };
351
if ( utime(path, ×) < 0 ) {
356
i_error("sieve-storage: %s", eacces_error_get("utime", path));
359
i_error("sieve-storage: utime(%s) failed: %m", path);
364
int sieve_storage_save_commit(struct sieve_save_context **_ctx)
366
struct sieve_save_context *ctx = *_ctx;
367
struct sieve_storage *storage = ctx->storage;
339
368
const char *dest_path;
340
369
bool failed = FALSE;
342
i_assert((*ctx)->output == NULL);
343
i_assert((*ctx)->finished);
344
i_assert((*ctx)->scriptname != NULL);
371
i_assert(ctx->output == NULL);
372
i_assert(ctx->finished);
373
i_assert(ctx->scriptname != NULL);
347
dest_path = t_strconcat((*ctx)->storage->dir, "/",
348
sieve_scriptfile_from_name((*ctx)->scriptname), NULL);
376
dest_path = t_strconcat(storage->dir, "/",
377
sieve_scriptfile_from_name(ctx->scriptname), NULL);
350
failed = !sieve_storage_script_move((*ctx), dest_path);
379
failed = !sieve_storage_script_move(ctx, dest_path);
380
if ( ctx->mtime != (time_t)-1 )
381
sieve_storage_update_mtime(dest_path, ctx->mtime);
353
sieve_storage_save_destroy(ctx);
384
/* set INBOX mailbox attribute */
386
sieve_storage_inbox_script_attribute_set(storage, ctx->scriptname);
388
sieve_storage_save_destroy(_ctx);
355
390
return ( failed ? -1 : 0 );
369
404
sieve_storage_save_destroy(ctx);
407
int sieve_storage_save_as_active_script(struct sieve_storage *storage,
408
struct istream *input, time_t mtime)
412
struct ostream *output;
414
temp_path = t_str_new(256);
415
str_append(temp_path, storage->active_path);
416
str_append_c(temp_path, '.');
417
fd = safe_mkstemp_hostpid
418
(temp_path, storage->file_create_mode, (uid_t)-1, (gid_t)-1);
420
if ( errno == EACCES ) {
421
sieve_storage_set_critical(storage,
422
"failed to create temporary file: %s",
423
eacces_error_get_creating("open", str_c(temp_path)));
425
sieve_storage_set_critical(storage,
426
"failed to create temporary file: open(%s) failed: %m",
432
output = o_stream_create_fd(fd, 0, FALSE);
433
if (o_stream_send_istream(output, input) < 0) {
434
sieve_storage_set_critical(storage,
435
"o_stream_send_istream(%s) failed: %m", str_c(temp_path));
436
o_stream_destroy(&output);
437
(void)unlink(str_c(temp_path));
440
o_stream_destroy(&output);
442
if (rename(str_c(temp_path), storage->active_path) < 0) {
443
if ( ENOSPACE(errno) ) {
444
sieve_storage_set_error(storage,
445
SIEVE_ERROR_NO_SPACE, "Not enough disk space");
446
} else if ( errno == EACCES ) {
447
sieve_storage_set_critical(storage,
448
"%s", eacces_error_get("rename", storage->active_path));
450
sieve_storage_set_critical(storage,
451
"rename(%s, %s) failed: %m", str_c(temp_path), storage->active_path);
454
sieve_storage_update_mtime(storage->active_path, mtime);
457
(void)unlink(str_c(temp_path));