~ubuntu-branches/ubuntu/utopic/dovecot/utopic

« back to all changes in this revision

Viewing changes to pigeonhole/src/lib-sievestorage/sieve-storage-save.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-01-08 09:35:49 UTC
  • mfrom: (4.1.35 sid)
  • Revision ID: package-import@ubuntu.com-20140108093549-i72o93pux8p0dlaf
Tags: 1:2.2.9-1ubuntu1
* Merge from Debian unstable, remaining changes:
  + Add mail-stack-delivery package:
    - Update d/rules
    - d/control: convert existing dovecot-postfix package to a dummy
      package and add new mail-stack-delivery package.
    - Update maintainer scripts.
    - Rename d/dovecot-postfix.* to debian/mail-stack-delivery.*
    - d/mail-stack-delivery.preinst: Move previously installed backups and
      config files to a new package namespace.
    - d/mail-stack-delivery.prerm: Added to handle downgrades.
  + Use Snakeoil SSL certificates by default:
    - d/control: Depend on ssl-cert.
    - d/dovecot-core.postinst: Relax grep for SSL_* a bit.
  + Add autopkgtest to debian/tests/*.
  + Add ufw integration:
    - d/dovecot-core.ufw.profile: new ufw profile.
    - d/rules: install profile in dovecot-core.
    - d/control: dovecot-core - suggest ufw.
  + d/dovecot-core.dirs: Added usr/share/doc/dovecot-core
  + Add apport hook:
    - d/rules, d/source_dovecot.py
  + Add upstart job:
    - d/rules, d/dovecot-core.dovecot.upstart, d/control,
      d/dovecot-core.dirs, dovecot-imapd.{postrm, postinst, prerm},
      d/dovecot-pop3d.{postinst, postrm, prerm}.
      d/mail-stack-deliver.postinst: Convert init script to upstart.
  + Use the autotools-dev dh addon to update config.guess/config.sub for
    arm64.
* Dropped changes, included in Debian:
  - Update Dovecot name to reflect distribution in login greeting.
  - Update Drac plugin for >= 2.0.0 support.
* d/control: Drop dovecot-postfix package as its no longer required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2002-2012 Pigeonhole authors, see the included COPYING file
 
1
/* Copyright (c) 2002-2013 Pigeonhole authors, see the included COPYING file
2
2
 */
3
3
 
4
4
#include "lib.h"
9
9
#include "ostream.h"
10
10
#include "str.h"
11
11
#include "eacces-error.h"
 
12
#include "safe-mkstemp.h"
12
13
 
13
14
#include "sieve-script.h"
14
15
#include "sieve-script-file.h"
36
37
        int fd;
37
38
        const char *tmp_path;
38
39
 
 
40
        time_t mtime;
 
41
 
39
42
        unsigned int failed:1;
40
43
        unsigned int moving:1;
41
44
        unsigned int finished:1;
76
79
        string_t *path;
77
80
        int fd;
78
81
 
79
 
        path = t_str_new(256);  
 
82
        path = t_str_new(256);
80
83
        str_append(path, storage->dir);
81
84
        str_append(path, "/tmp/");
82
85
        prefix_len = str_len(path);
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));
118
121
                        sieve_storage_set_critical(storage,
119
122
                                "open(%s) failed: %m", str_c(path));
120
123
                }
121
 
        } 
 
124
        }
122
125
 
123
126
        return fd;
124
127
}
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);
177
180
                        return NULL;
178
181
                }
179
182
 
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.
182
185
                 */
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 )
192
195
                        {
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);
196
199
                                return NULL;
197
200
                        }
198
201
                }
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;
207
211
 
208
212
        T_BEGIN {
209
213
                ctx->fd = sieve_storage_create_tmp(storage, scriptname, &path);
261
265
 
262
266
                if ( ctx->failed ) {
263
267
                        /* delete the tmp file */
264
 
                        if (unlink(ctx->tmp_path) < 0 && errno != ENOENT) 
 
268
                        if (unlink(ctx->tmp_path) < 0 && errno != ENOENT)
265
269
                                i_warning("sieve-storage: Unlink(%s) failed: %m", ctx->tmp_path);
266
270
 
267
271
                        errno = output_errno;
278
282
        return ( ctx->failed ? -1 : 0 );
279
283
}
280
284
 
 
285
void sieve_storage_save_set_mtime
 
286
(struct sieve_save_context *ctx, time_t mtime)
 
287
{
 
288
        ctx->mtime = mtime;
 
289
}
 
290
 
281
291
static void sieve_storage_save_destroy(struct sieve_save_context **ctx)
282
292
{
283
293
        if ((*ctx)->scriptobject != NULL)
290
300
struct sieve_script *sieve_storage_save_get_tempscript
291
301
(struct sieve_save_context *ctx)
292
302
{
293
 
        const char *scriptname = 
294
 
                ( ctx->scriptname == NULL ? "" : ctx->scriptname ); 
 
303
        const char *scriptname =
 
304
                ( ctx->scriptname == NULL ? "" : ctx->scriptname );
295
305
 
296
 
        if (ctx->failed) 
 
306
        if (ctx->failed)
297
307
                return NULL;
298
308
 
299
309
        if ( ctx->scriptobject != NULL )
300
310
                return ctx->scriptobject;
301
311
 
302
312
        ctx->scriptobject = sieve_storage_script_init_from_path
303
 
                (ctx->storage, ctx->tmp_path, scriptname);      
 
313
                (ctx->storage, ctx->tmp_path, scriptname);
304
314
 
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).",
310
320
                                ctx->tmp_path);
311
321
                }
312
322
                return NULL;
324
334
                const char *scriptname;
325
335
                int ret;
326
336
 
327
 
                ret = sieve_storage_get_active_scriptfile(ctx->storage, &scriptname);
 
337
                ret = sieve_storage_active_script_get_name(ctx->storage, &scriptname);
328
338
                if ( ret > 0 ) {
329
 
                        /* Is the requested script active? */
 
339
                        /* Is the requested script active? */
330
340
                        result = ( strcmp(ctx->scriptname, scriptname) == 0 );
331
341
                }
332
342
        } T_END;
334
344
        return result;
335
345
}
336
346
 
337
 
int sieve_storage_save_commit(struct sieve_save_context **ctx)
338
 
{
 
347
static void sieve_storage_update_mtime(const char *path, time_t mtime)
 
348
{
 
349
        struct utimbuf times = { .actime = mtime, .modtime = mtime };
 
350
 
 
351
        if ( utime(path, &times) < 0 ) {
 
352
                switch ( errno ) {      
 
353
                case ENOENT:
 
354
                        break;
 
355
                case EACCES:
 
356
                        i_error("sieve-storage: %s", eacces_error_get("utime", path));
 
357
                        break;
 
358
                default:
 
359
                        i_error("sieve-storage: utime(%s) failed: %m", path);
 
360
                }
 
361
        }
 
362
}
 
363
 
 
364
int sieve_storage_save_commit(struct sieve_save_context **_ctx)
 
365
{
 
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;
341
370
 
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);
345
374
 
346
375
        T_BEGIN {
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);
349
378
 
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);
351
382
        } T_END;
352
383
 
353
 
        sieve_storage_save_destroy(ctx);
 
384
        /* set INBOX mailbox attribute */
 
385
        if ( !failed )
 
386
                sieve_storage_inbox_script_attribute_set(storage, ctx->scriptname);
 
387
 
 
388
        sieve_storage_save_destroy(_ctx);
354
389
 
355
390
        return ( failed ? -1 : 0 );
356
391
}
359
394
{
360
395
        (*ctx)->failed = TRUE;
361
396
 
362
 
        if (!(*ctx)->finished) 
 
397
        if (!(*ctx)->finished)
363
398
                (void)sieve_storage_save_finish(*ctx);
364
399
        else
365
400
                (void)unlink((*ctx)->tmp_path);
368
403
 
369
404
        sieve_storage_save_destroy(ctx);
370
405
}
 
406
 
 
407
int sieve_storage_save_as_active_script(struct sieve_storage *storage,
 
408
        struct istream *input, time_t mtime)
 
409
{
 
410
        int fd;
 
411
        string_t *temp_path;
 
412
        struct ostream *output;
 
413
 
 
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);
 
419
        if ( fd < 0 ) {
 
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)));
 
424
                } else {
 
425
                        sieve_storage_set_critical(storage,
 
426
                                "failed to create temporary file: open(%s) failed: %m",
 
427
                                str_c(temp_path));
 
428
                }
 
429
                return -1;
 
430
        }
 
431
 
 
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));
 
438
                return -1;
 
439
        }
 
440
        o_stream_destroy(&output);
 
441
 
 
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));
 
449
                } else {
 
450
                        sieve_storage_set_critical(storage,
 
451
                                "rename(%s, %s) failed: %m", str_c(temp_path), storage->active_path);
 
452
                }
 
453
        } else {
 
454
                sieve_storage_update_mtime(storage->active_path, mtime);
 
455
        }
 
456
 
 
457
        (void)unlink(str_c(temp_path));
 
458
        return 0;
 
459
}