~james-page/ubuntu/raring/dovecot/autopkgtest

« back to all changes in this revision

Viewing changes to src/lib-storage/index/maildir/maildir-save.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2012-06-11 11:11:54 UTC
  • mfrom: (1.15.2) (4.1.27 sid)
  • Revision ID: package-import@ubuntu.com-20120611111154-678cwbdj6ktgsv1h
Tags: 1:2.1.7-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/{control,rules}: enable PIE hardening.
  + 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.
  + d/control: Added Pre-Depends: dpkg (>= 1.15.6) to dovecot-dbg to support
    xz compression in Ubuntu.
  + d/control: Demote dovecot-common Recommends: to Suggests: to prevent
    install of extra packages on upgrade.
  + d/patches/dovecot-drac.patch: Updated with version for dovecot >= 2.0.0.
  + d/control: Drop B-D on systemd.
* Dropped changes:
  + d/patches/fix-racey-restart.patch: part of 2.1.x, no longer required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2002-2011 Dovecot authors, see the included COPYING file */
 
1
/* Copyright (c) 2002-2012 Dovecot authors, see the included COPYING file */
2
2
 
3
3
#include "lib.h"
4
4
#include "ioloop.h"
15
15
#include "maildir-uidlist.h"
16
16
#include "maildir-keywords.h"
17
17
#include "maildir-filename.h"
 
18
#include "maildir-filename-flags.h"
18
19
#include "maildir-sync.h"
19
20
 
20
21
#include <stdio.h>
33
34
 
34
35
        uoff_t size, vsize;
35
36
        enum mail_flags flags;
 
37
        unsigned int pop3_order;
36
38
        unsigned int preserve_filename:1;
37
39
        unsigned int keywords_count;
38
40
        /* unsigned int keywords[]; */
116
118
{
117
119
        struct maildir_mailbox *mbox = (struct maildir_mailbox *)t->box;
118
120
        struct maildir_save_context *ctx;
 
121
        const char *path;
119
122
        pool_t pool;
120
123
 
121
124
        pool = pool_alloconly_create("maildir_save_context", 4096);
127
130
        ctx->files_tail = &ctx->files;
128
131
        ctx->fd = -1;
129
132
 
130
 
        ctx->tmpdir = p_strconcat(pool, mbox->box.path, "/tmp", NULL);
131
 
        ctx->newdir = p_strconcat(pool, mbox->box.path, "/new", NULL);
132
 
        ctx->curdir = p_strconcat(pool, mbox->box.path, "/cur", NULL);
 
133
        path = mailbox_get_path(&mbox->box);
 
134
        ctx->tmpdir = p_strconcat(pool, path, "/tmp", NULL);
 
135
        ctx->newdir = p_strconcat(pool, path, "/new", NULL);
 
136
        ctx->curdir = p_strconcat(pool, path, "/cur", NULL);
133
137
 
134
138
        buffer_create_const_data(&ctx->keywords_buffer, NULL, 0);
135
139
        array_create_from_buffer(&ctx->keywords_array, &ctx->keywords_buffer,
184
188
        }
185
189
        if (_ctx->pop3_uidl != NULL)
186
190
                mf->pop3_uidl = p_strdup(ctx->pool, _ctx->pop3_uidl);
 
191
        mf->pop3_order = _ctx->pop3_order;
187
192
 
188
193
        /* insert into index */
189
194
        mail_index_append(ctx->trans, _ctx->uid, &ctx->seq);
208
213
                        ctx->mail = mail_alloc(_ctx->transaction, 0, NULL);
209
214
                _ctx->dest_mail = ctx->mail;
210
215
        }
211
 
        mail_set_seq(_ctx->dest_mail, ctx->seq);
212
 
        _ctx->dest_mail->saving = TRUE;
 
216
        mail_set_seq_saving(_ctx->dest_mail, ctx->seq);
213
217
 
214
218
        if (ctx->input == NULL) {
215
219
                /* copying with hardlinking. */
268
272
                        return TRUE;
269
273
                }
270
274
 
271
 
                *fname_r = maildir_filename_set_flags(NULL, basename,
 
275
                *fname_r = maildir_filename_flags_set(NULL, basename,
272
276
                                        mf->flags & MAIL_FLAGS_MASK, NULL);
273
277
                return FALSE;
274
278
        }
276
280
        i_assert(ctx->keywords_sync_ctx != NULL || mf->keywords_count == 0);
277
281
        buffer_create_const_data(&ctx->keywords_buffer, mf + 1,
278
282
                                 mf->keywords_count * sizeof(unsigned int));
279
 
        *fname_r = maildir_filename_set_flags(ctx->keywords_sync_ctx, basename,
 
283
        *fname_r = maildir_filename_flags_set(ctx->keywords_sync_ctx, basename,
280
284
                                              mf->flags & MAIL_FLAGS_MASK,
281
285
                                              &ctx->keywords_array);
282
286
        return FALSE;
322
326
                              const char **fname_r)
323
327
{
324
328
        struct mailbox *box = &mbox->box;
 
329
        const struct mailbox_permissions *perm = mailbox_get_permissions(box);
325
330
        unsigned int prefix_len;
326
331
        const char *tmp_fname;
327
332
        string_t *path;
342
347
                   might return an existing filename is if the time moved
343
348
                   backwards. so we'll use O_EXCL anyway, although it's mostly
344
349
                   useless. */
345
 
                old_mask = umask(0777 & ~box->file_create_mode);
 
350
                old_mask = umask(0777 & ~perm->file_create_mode);
346
351
                fd = open(str_c(path),
347
352
                          O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0777);
348
353
                umask(old_mask);
357
362
                        mail_storage_set_critical(box->storage,
358
363
                                "open(%s) failed: %m", str_c(path));
359
364
                }
360
 
        } else if (box->file_create_gid != (gid_t)-1) {
361
 
                if (fchown(fd, (uid_t)-1, box->file_create_gid) < 0) {
 
365
        } else if (perm->file_create_gid != (gid_t)-1) {
 
366
                if (fchown(fd, (uid_t)-1, perm->file_create_gid) < 0) {
362
367
                        if (errno == EPERM) {
363
368
                                mail_storage_set_critical(box->storage, "%s",
364
369
                                        eperm_error_get_chgrp("fchown",
365
370
                                                str_c(path),
366
 
                                                box->file_create_gid,
367
 
                                                box->file_create_gid_origin));
 
371
                                                perm->file_create_gid,
 
372
                                                perm->file_create_gid_origin));
368
373
                        } else {
369
374
                                mail_storage_set_critical(box->storage,
370
375
                                        "fchown(%s) failed: %m", str_c(path));
490
495
 
491
496
static void maildir_save_remove_last_filename(struct maildir_save_context *ctx)
492
497
{
493
 
        struct index_transaction_context *t =
494
 
                (struct index_transaction_context *)ctx->ctx.transaction;
495
498
        struct maildir_filename **fm;
496
499
 
497
500
        mail_index_expunge(ctx->trans, ctx->seq);
498
501
        /* currently we can't just drop pending cache updates for this one
499
502
           specific record, so we'll reset the whole cache transaction. */
500
 
        mail_cache_transaction_reset(t->cache_trans);
 
503
        mail_cache_transaction_reset(ctx->ctx.transaction->cache_trans);
501
504
        ctx->seq--;
502
505
 
503
506
        for (fm = &ctx->files; (*fm)->next != NULL; fm = &(*fm)->next) ;
514
517
        struct maildir_save_context *ctx = (struct maildir_save_context *)_ctx;
515
518
        struct mail_storage *storage = &ctx->mbox->storage->storage;
516
519
        const char *path;
 
520
        off_t real_size;
 
521
        uoff_t size;
517
522
        int output_errno;
518
523
 
519
524
        ctx->last_save_finished = TRUE;
523
528
        }
524
529
 
525
530
        path = t_strconcat(ctx->tmpdir, "/", ctx->file_last->tmp_name, NULL);
526
 
        if (o_stream_flush(_ctx->output) < 0) {
 
531
        if (!ctx->failed && o_stream_flush(_ctx->output) < 0) {
527
532
                if (!mail_storage_set_error_from_errno(storage)) {
528
533
                        mail_storage_set_critical(storage,
529
534
                                "o_stream_flush(%s) failed: %m", path);
569
574
                        ctx->failed = TRUE;
570
575
                }
571
576
        }
 
577
        real_size = lseek(ctx->fd, 0, SEEK_END);
 
578
        if (real_size == (off_t)-1) {
 
579
                mail_storage_set_critical(storage,
 
580
                                          "lseek(%s) failed: %m", path);
 
581
        } else if (real_size != (off_t)ctx->file_last->size &&
 
582
                   (!maildir_filename_get_size(ctx->file_last->dest_basename,
 
583
                                               MAILDIR_EXTRA_FILE_SIZE, &size) ||
 
584
                    size != ctx->file_last->size)) {
 
585
                /* e.g. zlib plugin was used. the "physical size" must be in
 
586
                   the maildir filename, since stat() will return wrong size */
 
587
                ctx->file_last->preserve_filename = FALSE;
 
588
                /* reset the base name as well, just in case there's a
 
589
                   ,W=vsize */
 
590
                ctx->file_last->dest_basename = ctx->file_last->tmp_name;
 
591
        }
572
592
        if (close(ctx->fd) < 0) {
573
593
                if (!mail_storage_set_error_from_errno(storage)) {
574
594
                        mail_storage_set_critical(storage,
740
760
                next_uid = maildir_save_set_recent_flags(ctx);
741
761
        } T_END;
742
762
 
743
 
        if ((mbox->box.flags & MAILBOX_FLAG_KEEP_RECENT) == 0)
 
763
        if ((mbox->box.flags & MAILBOX_FLAG_DROP_RECENT) != 0)
744
764
                first_recent_uid = next_uid;
745
765
        else if (ctx->last_nonrecent_uid != 0)
746
766
                first_recent_uid = ctx->last_nonrecent_uid + 1;
763
783
static void
764
784
maildir_save_rollback_index_changes(struct maildir_save_context *ctx)
765
785
{
766
 
        struct index_transaction_context *t =
767
 
                (struct index_transaction_context *)ctx->ctx.transaction;
768
786
        uint32_t seq;
769
787
 
770
788
        if (ctx->seq == 0)
773
791
        for (seq = ctx->seq; seq >= ctx->first_seq; seq--)
774
792
                mail_index_expunge(ctx->trans, seq);
775
793
 
776
 
        mail_cache_transaction_reset(t->cache_trans);
 
794
        mail_cache_transaction_reset(ctx->ctx.transaction->cache_trans);
777
795
}
778
796
 
779
797
static bool maildir_filename_has_conflict(struct maildir_filename *mf,
913
931
                                MAILDIR_UIDLIST_REC_EXT_POP3_UIDL,
914
932
                                mf->pop3_uidl);
915
933
                }
 
934
                if (mf->pop3_order > 0) {
 
935
                        maildir_uidlist_sync_set_ext(ctx->uidlist_sync_ctx, rec,
 
936
                                MAILDIR_UIDLIST_REC_EXT_POP3_ORDER,
 
937
                                t_strdup_printf("%u", mf->pop3_order));
 
938
                }
916
939
        } T_END;
917
940
        i_assert(!seq_range_array_iter_nth(&iter, n, &uid));
918
941
}