1 #ifndef MAILDIR_UIDLIST_H
2 #define MAILDIR_UIDLIST_H
3 
4 #include "mail-storage.h"
5 
6 #define MAILDIR_UIDLIST_NAME "dovecot-uidlist"
7 /* how many seconds to wait before overriding uidlist.lock */
8 #define MAILDIR_UIDLIST_LOCK_STALE_TIMEOUT (60*2)
9 
10 struct maildir_mailbox;
11 struct maildir_uidlist;
12 struct maildir_uidlist_sync_ctx;
13 struct maildir_uidlist_rec;
14 
15 enum maildir_uidlist_sync_flags {
16 	MAILDIR_UIDLIST_SYNC_PARTIAL	= 0x01,
17 	MAILDIR_UIDLIST_SYNC_KEEP_STATE	= 0x02,
18 	MAILDIR_UIDLIST_SYNC_FORCE	= 0x04,
19 	MAILDIR_UIDLIST_SYNC_TRYLOCK	= 0x08,
20 	MAILDIR_UIDLIST_SYNC_NOREFRESH	= 0x10,
21 	MAILDIR_UIDLIST_SYNC_NOLOCK	= 0x20
22 };
23 
24 enum maildir_uidlist_rec_flag {
25 	MAILDIR_UIDLIST_REC_FLAG_NEW_DIR	= 0x01,
26 	MAILDIR_UIDLIST_REC_FLAG_MOVED		= 0x02,
27 	MAILDIR_UIDLIST_REC_FLAG_RECENT		= 0x04,
28 	MAILDIR_UIDLIST_REC_FLAG_NONSYNCED	= 0x08,
29 	MAILDIR_UIDLIST_REC_FLAG_RACING		= 0x10
30 };
31 
32 enum maildir_uidlist_hdr_ext_key {
33 	MAILDIR_UIDLIST_HDR_EXT_UID_VALIDITY		= 'V',
34 	MAILDIR_UIDLIST_HDR_EXT_NEXT_UID		= 'N',
35 	MAILDIR_UIDLIST_HDR_EXT_GUID			= 'G',
36 	/* POP3 UIDL format unless overridden by records */
37 	MAILDIR_UIDLIST_HDR_EXT_POP3_UIDL_FORMAT	= 'P'
38 };
39 
40 #define MAILDIR_UIDLIST_REC_EXT_KEY_IS_VALID(c) \
41 	((c) >= 'A' && (c) <= 'Z')
42 enum maildir_uidlist_rec_ext_key {
43 	/* Physical message size. If filename also contains ,S=<vsize> this
44 	   isn't written to uidlist. */
45 	MAILDIR_UIDLIST_REC_EXT_PSIZE		= 'S',
46 	/* Virtual message size. If filename also contains ,W=<vsize> this
47 	   isn't written to uidlist. */
48 	MAILDIR_UIDLIST_REC_EXT_VSIZE		= 'W',
49 	/* POP3 UIDL overriding the default format */
50 	MAILDIR_UIDLIST_REC_EXT_POP3_UIDL	= 'P',
51 	/* POP3 message ordering number. Lower numbered messages are listed
52 	   first. Messages without ordering number are listed after them.
53 	   The idea is to be able to preserve POP3 UIDL list and IMAP UIDs
54 	   perfectly when migrating from other servers. */
55 	MAILDIR_UIDLIST_REC_EXT_POP3_ORDER	= 'O',
56 	/* Message GUID (default is the base filename) */
57 	MAILDIR_UIDLIST_REC_EXT_GUID		= 'G'
58 };
59 
60 int maildir_uidlist_lock(struct maildir_uidlist *uidlist);
61 int maildir_uidlist_try_lock(struct maildir_uidlist *uidlist);
62 int maildir_uidlist_lock_touch(struct maildir_uidlist *uidlist);
63 void maildir_uidlist_unlock(struct maildir_uidlist *uidlist);
64 bool maildir_uidlist_is_locked(struct maildir_uidlist *uidlist);
65 bool maildir_uidlist_is_read(struct maildir_uidlist *uidlist);
66 /* Returns TRUE if uidlist file is currently open */
67 bool maildir_uidlist_is_open(struct maildir_uidlist *uidlist);
68 
69 struct maildir_uidlist *maildir_uidlist_init(struct maildir_mailbox *mbox);
70 void maildir_uidlist_deinit(struct maildir_uidlist **uidlist);
71 
72 /* Returns -1 if error, 0 if file is broken or lost, 1 if ok. If nfs_flush=TRUE
73    and storage has NFS_FLUSH flag set, the NFS attribute cache is flushed to
74    make sure that we see the latest uidlist file. */
75 int maildir_uidlist_refresh(struct maildir_uidlist *uidlist);
76 /* Like maildir_uidlist_refresh(), but if uidlist isn't opened yet, try to
77    fill in the uidvalidity/nextuid from index file instead. */
78 int maildir_uidlist_refresh_fast_init(struct maildir_uidlist *uidlist);
79 
80 /* Look up uidlist record for given filename. Returns 1 if found,
81    0 if not found, -1 if error */
82 int maildir_uidlist_lookup(struct maildir_uidlist *uidlist, uint32_t uid,
83 			   enum maildir_uidlist_rec_flag *flags_r,
84 			   const char **fname_r);
85 /* Returns extension's value or NULL if it doesn't exist. */
86 const char *
87 maildir_uidlist_lookup_ext(struct maildir_uidlist *uidlist, uint32_t uid,
88 			   enum maildir_uidlist_rec_ext_key key);
89 
90 uint32_t maildir_uidlist_get_uid_validity(struct maildir_uidlist *uidlist);
91 uint32_t maildir_uidlist_get_next_uid(struct maildir_uidlist *uidlist);
92 int maildir_uidlist_get_mailbox_guid(struct maildir_uidlist *uidlist,
93 				     guid_128_t mailbox_guid);
94 void maildir_uidlist_set_mailbox_guid(struct maildir_uidlist *uidlist,
95 				      const guid_128_t mailbox_guid);
96 
97 void maildir_uidlist_set_uid_validity(struct maildir_uidlist *uidlist,
98 				      uint32_t uid_validity);
99 void maildir_uidlist_set_next_uid(struct maildir_uidlist *uidlist,
100 				  uint32_t next_uid, bool force);
101 
102 /* Update extended record. */
103 void maildir_uidlist_set_ext(struct maildir_uidlist *uidlist, uint32_t uid,
104 			     enum maildir_uidlist_rec_ext_key key,
105 			     const char *value);
106 void maildir_uidlist_unset_ext(struct maildir_uidlist *uidlist, uint32_t uid,
107 			       enum maildir_uidlist_rec_ext_key key);
108 
109 /* If uidlist has changed, update it. This is mostly meant to be used with
110    maildir_uidlist_set_ext() */
111 int maildir_uidlist_update(struct maildir_uidlist *uidlist);
112 
113 void maildir_uidlist_set_all_nonsynced(struct maildir_uidlist *uidlist);
114 /* Sync uidlist with what's actually on maildir. Returns same as
115    maildir_uidlist_lock(). */
116 int maildir_uidlist_sync_init(struct maildir_uidlist *uidlist,
117 			      enum maildir_uidlist_sync_flags sync_flags,
118 			      struct maildir_uidlist_sync_ctx **sync_ctx_r);
119 int maildir_uidlist_sync_next(struct maildir_uidlist_sync_ctx *ctx,
120 			      const char *filename,
121 			      enum maildir_uidlist_rec_flag flags);
122 int maildir_uidlist_sync_next_uid(struct maildir_uidlist_sync_ctx *ctx,
123 				  const char *filename, uint32_t uid,
124 				  enum maildir_uidlist_rec_flag flags,
125 				  struct maildir_uidlist_rec **rec_r);
126 void maildir_uidlist_sync_remove(struct maildir_uidlist_sync_ctx *ctx,
127 				 const char *filename);
128 void maildir_uidlist_sync_set_ext(struct maildir_uidlist_sync_ctx *ctx,
129 				  struct maildir_uidlist_rec *rec,
130 				  enum maildir_uidlist_rec_ext_key key,
131 				  const char *value);
132 void maildir_uidlist_update_fname(struct maildir_uidlist *uidlist,
133 				  const char *filename);
134 const char *
135 maildir_uidlist_sync_get_full_filename(struct maildir_uidlist_sync_ctx *ctx,
136 				       const char *filename);
137 void maildir_uidlist_sync_recreate(struct maildir_uidlist_sync_ctx *ctx);
138 void maildir_uidlist_sync_finish(struct maildir_uidlist_sync_ctx *ctx);
139 int maildir_uidlist_sync_deinit(struct maildir_uidlist_sync_ctx **ctx,
140 				bool success);
141 
142 bool maildir_uidlist_get_uid(struct maildir_uidlist *uidlist,
143 			     const char *filename, uint32_t *uid_r);
144 const char *
145 maildir_uidlist_get_full_filename(struct maildir_uidlist *uidlist,
146 				  const char *filename);
147 
148 void maildir_uidlist_add_flags(struct maildir_uidlist *uidlist,
149 			       const char *filename,
150 			       enum maildir_uidlist_rec_flag flags);
151 
152 /* List all maildir files. */
153 struct maildir_uidlist_iter_ctx *
154 maildir_uidlist_iter_init(struct maildir_uidlist *uidlist);
155 bool maildir_uidlist_iter_next(struct maildir_uidlist_iter_ctx *ctx,
156 			       uint32_t *uid_r,
157 			       enum maildir_uidlist_rec_flag *flags_r,
158 			       const char **filename_r);
159 void maildir_uidlist_iter_deinit(struct maildir_uidlist_iter_ctx **ctx);
160 
161 #endif
162