[dovecot-cvs] dovecot/src/lib-storage/subscription-file subscription-file.c,1.16,1.17 subscription-file.h,1.5,1.6
cras at procontrol.fi
cras at procontrol.fi
Wed Feb 19 21:55:30 EET 2003
- Previous message: [dovecot-cvs] dovecot/src/lib-storage/index/maildir maildir-list.c,1.12,1.13 maildir-storage.c,1.27,1.28 maildir-storage.h,1.12,1.13
- Next message: [dovecot-cvs] dovecot/src/lib-imap imap-match.c,1.4,1.5 imap-match.h,1.4,1.5
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /home/cvs/dovecot/src/lib-storage/subscription-file
In directory danu:/tmp/cvs-serv21976/src/lib-storage/subscription-file
Modified Files:
subscription-file.c subscription-file.h
Log Message:
Rewrote LIST, LSUB and subscription file handling. LIST replies aren't
sorted anymore by default, it can be enabled with client_workarounds =
list-sort.
Index: subscription-file.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/subscription-file/subscription-file.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- subscription-file.c 27 Jan 2003 02:00:00 -0000 1.16
+++ subscription-file.c 19 Feb 2003 19:55:27 -0000 1.17
@@ -1,12 +1,10 @@
-/* Copyright (C) 2002 Timo Sirainen */
-
-/* ugly code here - text files are annoying to manage */
+/* Copyright (C) 2002-2003 Timo Sirainen */
#include "lib.h"
+#include "istream.h"
+#include "ostream.h"
#include "file-lock.h"
-#include "mmap-util.h"
#include "write-full.h"
-#include "imap-match.h"
#include "mail-storage.h"
#include "subscription-file.h"
@@ -14,6 +12,17 @@
#include <fcntl.h>
#define SUBSCRIPTION_FILE_NAME ".subscriptions"
+#define MAX_MAILBOX_LENGTH PATH_MAX
+
+struct subsfile_list_context {
+ pool_t pool;
+
+ struct mail_storage *storage;
+ struct istream *input;
+ const char *path;
+
+ int failed;
+};
static int subsfile_set_syscall_error(struct mail_storage *storage,
const char *path, const char *function)
@@ -27,8 +36,7 @@
}
static int subscription_open(struct mail_storage *storage, int update,
- const char **path, void **mmap_base,
- size_t *mmap_length)
+ const char **path)
{
int fd;
@@ -42,7 +50,7 @@
return -1;
}
- return -2;
+ return -1;
}
/* FIXME: we should work without locking, rename() would be easiest
@@ -52,115 +60,108 @@
(void)close(fd);
return -1;
}
+ return fd;
+}
- *mmap_base = update ? mmap_rw_file(fd, mmap_length) :
- mmap_ro_file(fd, mmap_length);
- if (*mmap_base == MAP_FAILED) {
- *mmap_base = NULL;
- subsfile_set_syscall_error(storage, "mmap()", *path);
- (void)close(fd);
- return -1;
+static const char *next_line(struct mail_storage *storage, const char *path,
+ struct istream *input, int *failed)
+{
+ const char *line;
+
+ while ((line = i_stream_next_line(input)) == NULL) {
+ switch (i_stream_read(input)) {
+ case -1:
+ *failed = FALSE;
+ return NULL;
+ case -2:
+ /* mailbox name too large */
+ mail_storage_set_critical(storage,
+ "Subscription file %s contains lines longer "
+ "than %u characters", path,
+ MAX_MAILBOX_LENGTH);
+ *failed = TRUE;
+ return NULL;
+ }
}
- (void)madvise(*mmap_base, *mmap_length, MADV_SEQUENTIAL);
- return fd;
+ *failed = FALSE;
+ return line;
}
-static int subscription_append(struct mail_storage *storage, int fd,
- const char *name, size_t len, int prefix_lf,
- const char *path)
+static int stream_cut(struct mail_storage *storage, const char *path,
+ struct istream *input, uoff_t count)
{
- char *buf;
-
- if (lseek(fd, 0, SEEK_END) < 0)
- return subsfile_set_syscall_error(storage, "lseek()", path);
+ struct ostream *output;
+ int fd, failed;
- /* @UNSAFE */
- buf = t_buffer_get(len+2);
- buf[0] = '\n';
- memcpy(buf+1, name, len);
- buf[len+1] = '\n';
+ fd = i_stream_get_fd(input);
+ i_assert(fd != -1);
- if (prefix_lf)
- len += 2;
- else {
- buf++;
- len++;
+ output = o_stream_create_file(fd, default_pool, 4096, 0, 0);
+ if (o_stream_seek(output, input->start_offset + input->v_offset) < 0) {
+ failed = TRUE;
+ errno = output->stream_errno;
+ subsfile_set_syscall_error(storage, "o_stream_seek()", path);
+ } else {
+ i_stream_skip(input, count);
+ failed = o_stream_send_istream(output, input) < 0;
+ if (failed) {
+ errno = output->stream_errno;
+ subsfile_set_syscall_error(storage,
+ "o_stream_send_istream()",
+ path);
+ }
}
- if (write_full(fd, buf, len) < 0) {
- subsfile_set_syscall_error(storage, "write_full()", path);
- return FALSE;
+ if (!failed) {
+ if (ftruncate(fd, output->offset) < 0) {
+ subsfile_set_syscall_error(storage, "ftruncate()",
+ path);
+ failed = TRUE;
+ }
}
- return TRUE;
+ o_stream_unref(output);
+ return !failed;
}
int subsfile_set_subscribed(struct mail_storage *storage,
const char *name, int set)
{
- void *mmap_base;
- size_t mmap_length;
- const char *path;
- char *subscriptions, *end, *p;
- size_t namelen, afterlen, removelen;
- int fd, failed, prefix_lf;
+ const char *path, *line;
+ struct istream *input;
+ uoff_t offset;
+ int fd, failed;
if (strcasecmp(name, "INBOX") == 0)
name = "INBOX";
- fd = subscription_open(storage, TRUE, &path, &mmap_base, &mmap_length);
+ fd = subscription_open(storage, TRUE, &path);
if (fd == -1)
return FALSE;
- namelen = strlen(name);
-
- subscriptions = mmap_base;
- if (subscriptions == NULL)
- p = NULL;
- else {
- end = subscriptions + mmap_length;
- for (p = subscriptions; p != end; p++) {
- if (*p == *name && p+namelen <= end &&
- strncmp(p, name, namelen) == 0) {
- /* make sure beginning and end matches too */
- if ((p == subscriptions || p[-1] == '\n') &&
- (p+namelen == end || p[namelen] == '\n'))
- break;
- }
- }
-
- if (p == end)
- p = NULL;
- }
-
- failed = FALSE;
- if (p != NULL && !set) {
- /* remove it */
- afterlen = mmap_length - (size_t) (p - subscriptions);
- removelen = namelen < afterlen ? namelen+1 : namelen;
-
- if (removelen < afterlen)
- memmove(p, p+removelen, afterlen-removelen);
+ input = i_stream_create_file(fd, default_pool,
+ MAX_MAILBOX_LENGTH, FALSE);
+ do {
+ offset = input->v_offset;
+ line = next_line(storage, path, input, &failed);
+ } while (line != NULL && strcmp(line, name) != 0);
- if (ftruncate(fd, (off_t) (mmap_length - removelen)) == -1) {
- subsfile_set_syscall_error(storage, "ftruncate()",
- path);
- failed = TRUE;
+ if (!failed) {
+ if (set && line == NULL) {
+ /* add subscription. we're at EOF so just write it */
+ write_full(fd, t_strconcat(name, "\n", NULL),
+ strlen(name)+1);
+ } else if (!set && line != NULL) {
+ /* remove subcription. */
+ uoff_t size = input->v_offset - offset;
+ i_stream_seek(input, offset);
+ if (!stream_cut(storage, path, input, size))
+ failed = TRUE;
}
- } else if (p == NULL && set) {
- /* append it */
- prefix_lf = mmap_length > 0 &&
- subscriptions[mmap_length-1] != '\n';
- if (!subscription_append(storage, fd, name, namelen,
- prefix_lf, path))
- failed = TRUE;
}
- if (mmap_base != NULL && munmap(mmap_base, mmap_length) < 0) {
- subsfile_set_syscall_error(storage, "munmap()", path);
- failed = TRUE;
- }
+ i_stream_unref(input);
if (close(fd) < 0) {
subsfile_set_syscall_error(storage, "close()", path);
@@ -169,45 +170,45 @@
return !failed;
}
-int subsfile_foreach(struct mail_storage *storage, const char *mask,
- subsfile_foreach_callback_t *callback, void *context)
+struct subsfile_list_context *
+subsfile_list_init(struct mail_storage *storage)
{
- struct imap_match_glob *glob;
- const char *path, *start, *end, *p, *line;
- void *mmap_base;
- size_t mmap_length;
- int fd, ret;
+ struct subsfile_list_context *ctx;
+ pool_t pool;
+ const char *path;
+ int fd;
- fd = subscription_open(storage, FALSE, &path, &mmap_base, &mmap_length);
- if (fd < 0) {
- /* -2 = no subscription file, ignore */
- return fd == -1 ? -1 : 1;
- }
+ fd = subscription_open(storage, FALSE, &path);
+ if (fd == -1 && errno != ENOENT)
+ return NULL;
- glob = imap_match_init(mask, TRUE, storage->hierarchy_sep);
+ pool = pool_alloconly_create("subsfile_list", MAX_MAILBOX_LENGTH+1024);
- start = mmap_base; end = start + mmap_length; ret = 1;
- while (ret) {
- t_push();
+ ctx = p_new(pool, struct subsfile_list_context, 1);
+ ctx->pool = pool;
+ ctx->storage = storage;
+ ctx->input = fd == -1 ? NULL :
+ i_stream_create_file(fd, pool, MAX_MAILBOX_LENGTH, TRUE);
+ ctx->path = p_strdup(pool, path);
+ return ctx;
+}
- for (p = start; p != end; p++) {
- if (*p == '\n')
- break;
- }
+int subsfile_list_deinit(struct subsfile_list_context *ctx)
+{
+ int failed;
- line = t_strdup_until(start, p);
- if (line != NULL && *line != '\0' && imap_match(glob, line) > 0)
- ret = callback(storage, line, context);
- t_pop();
+ failed = ctx->failed;
+ if (ctx->input != NULL)
+ i_stream_unref(ctx->input);
+ pool_unref(ctx->pool);
- if (p == end)
- break;
- start = p+1;
- }
+ return !failed;
+}
- if (mmap_base != NULL && munmap(mmap_base, mmap_length) < 0)
- subsfile_set_syscall_error(storage, "munmap()", path);
- if (close(fd) < 0)
- subsfile_set_syscall_error(storage, "close()", path);
- return ret;
+const char *subsfile_list_next(struct subsfile_list_context *ctx)
+{
+ if (ctx->failed || ctx->input == NULL)
+ return NULL;
+
+ return next_line(ctx->storage, ctx->path, ctx->input, &ctx->failed);
}
Index: subscription-file.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/subscription-file/subscription-file.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- subscription-file.h 27 Jan 2003 02:00:00 -0000 1.5
+++ subscription-file.h 19 Feb 2003 19:55:27 -0000 1.6
@@ -3,15 +3,17 @@
#include "mail-storage.h"
-/* Returns FALSE if foreach should be aborted */
-typedef int subsfile_foreach_callback_t(struct mail_storage *storage,
- const char *name, void *context);
+/* Initialize new subscription file listing. Returns NULL if failed. */
+struct subsfile_list_context *
+subsfile_list_init(struct mail_storage *storage);
+
+/* Deinitialize subscription file listing. Returns FALSE if some error occured
+ while listing. */
+int subsfile_list_deinit(struct subsfile_list_context *ctx);
+/* Returns the next subscribed mailbox, or NULL. */
+const char *subsfile_list_next(struct subsfile_list_context *ctx);
int subsfile_set_subscribed(struct mail_storage *storage,
const char *name, int set);
-
-/* Returns -1 if error, 0 if foreach function returned FALSE or 1 if all ok */
-int subsfile_foreach(struct mail_storage *storage, const char *mask,
- subsfile_foreach_callback_t *callback, void *context);
#endif
- Previous message: [dovecot-cvs] dovecot/src/lib-storage/index/maildir maildir-list.c,1.12,1.13 maildir-storage.c,1.27,1.28 maildir-storage.h,1.12,1.13
- Next message: [dovecot-cvs] dovecot/src/lib-imap imap-match.c,1.4,1.5 imap-match.h,1.4,1.5
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the dovecot-cvs
mailing list