[P3L-CVS] CVS: pop3lite-ng/src/pop3lite/modules/maildrop/mbox Makefile,NONE,1.1 mbox.c,NONE,1.1 mbox
Brought to you by:
algernon
From: Gergely N. <alg...@us...> - 2001-08-11 01:30:12
|
Update of /cvsroot/pop3lite/pop3lite-ng/src/pop3lite/modules/maildrop/mbox In directory usw-pr-cvs1:/tmp/cvs-serv28086/src/pop3lite/modules/maildrop/mbox Added Files: Makefile mbox.c mbox.h Log Message: initial import --- NEW FILE --- top_srcdir = ../../../../.. SRCDIR = $(top_srcdir)/src/pop3lite/modules/maildrop/mbox MODULE_SOURCES = mbox.c LIB_SOURCES = $(MODULE_SOURCES) MODULE = mbox.la include $(top_srcdir)/mk/p3l.rules.mk --- NEW FILE --- /* * src/pop3lite/modules/maildrop/mbox/mbox.c -- mailbox handling routines * Copyright (C) 2000, 2001 Gergely Nagy <alg...@de...> * * This file is part of POP3Lite. * * POP3Lite is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * POP3Lite is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Last updated: <2001/08/10 16:35:05 algernon> * $Id: mbox.c,v 1.1 2001/08/11 01:30:09 algernon Exp $ */ #ifdef HAVE_CONFIG_H #include <config.h> #endif #ifdef HAVE_UNISTD_H #include <unistd.h> #endif #include <errno.h> #include <fcntl.h> #include <sys/stat.h> #include <pop3lite/maildrop.h> #include <pop3lite/p3l_lock.h> #include "mbox.h" #define BUFFER_SIZE 80 /* TODO: - make BUFFER_SIZE a runtime (after there is a config interface) - better error reporting (after there is a facility to do so) - update support */ int p3l_maildrop_mbox_open (p3l_maildrop_t *maildrop) { p3l_mbox_t *mbox_data; mode_t old_umask; unsigned int max_count = 10; /* By default, let's support * 10 messages */ struct stat st; off_t current_pos, *newlines; size_t i, current_line, bytes_read, max_newlines = 100; int is_header = 0; char *buf; /* If there's no maildrop, better leave now */ if (maildrop == NULL) { errno = EINVAL; return -1; } /* Aloccate memory for our own structures */ mbox_data = (p3l_mbox_t *)malloc (sizeof (p3l_mbox_t)); if (mbox_data == NULL) return -1; maildrop->_driver_data = (void *)mbox_data; mbox_data->buffer_size = BUFFER_SIZE; /* Allocate memory for the messages */ mbox_data->messages = (p3l_mbox_item_t *)malloc (sizeof (p3l_mbox_item_t) * max_count); maildrop->sizes = (size_t *)malloc (sizeof (size_t) * max_count); if (mbox_data->messages == NULL || maildrop->sizes == NULL) return -1; /* Open the file */ if ((mbox_data->fd = open (maildrop->name, O_RDWR)) < 0) { /* If there's no mailbox, try to create one */ old_umask = umask(000); if ((mbox_data->fd = open (maildrop->name, O_RDWR | O_CREAT, 0660)) < 0 ) { umask (old_umask); errno = EIO; return -1; } umask (old_umask); /* Ok, mailbox created, now set some stuff */ } /* stat the mailbox, for we need the last modification time */ if (stat(maildrop->name, &st) == -1) { maildrop->_close (maildrop); return -1; /* errno is already set by stat */ } mbox_data->last_mod_time = st.st_mtime; /* lock the mailbox. From now on, only we are supposed to be * able to access it */ if ( maildrop->_lock (maildrop, MD_LOCK_RLOCK) != 0 ) { maildrop->_close (maildrop); return -1; /* errno is already set by _lock */ } /** scan the mailbox here **/ maildrop->messages=0; /* Okay, now let's allocate some memory.. */ buf = (char *)malloc (mbox_data->buffer_size); if (buf == NULL) return -1; lseek (mbox_data->fd, 0, SEEK_SET); if (st.st_size == 0) /* This is an empty mailbox */ return 0; /* Now, let's see if it's a mailbox.. */ read (mbox_data->fd, buf, 5); if (memcmp (buf, "From ", 5)) { /* Not a mailbox, bail out */ maildrop->_close (maildrop); errno = EBADMSG; return -1; } lseek (mbox_data->fd, 0, SEEK_SET); current_pos = 0; /* * Strategy: * - first, read through the mailbox, and find every newline, * and note their position * - seek to the beginning * - read line-by-line (using the \n indexes determined * eariler * - store From line offsetts as header begining, and the * first empty line after them as the body offset */ /* Step 1 */ newlines = (off_t *)malloc (sizeof (off_t) * max_newlines); current_line = 0; while ((bytes_read = read (mbox_data->fd, buf, mbox_data->buffer_size)) > 0) { for (i = 0; i < mbox_data->buffer_size; i++) { if (buf[i]=='\n') { newlines[current_line] = current_pos + i; current_line++; /* allocate some more if we ran out of storage */ if (current_line >= max_newlines) { off_t *p; max_newlines *= 2; p = (off_t *) realloc (newlines, sizeof (off_t) * max_newlines); if (p == NULL) return -1; newlines = p; } } } current_pos += bytes_read; } current_line--; newlines[current_line+1] = newlines[current_line]; /* Step 2 */ lseek (mbox_data->fd, 0, SEEK_SET); /* Step 3 */ current_pos = 0; for (i = 0; i < current_line; i++) { lseek (mbox_data->fd, current_pos, SEEK_SET); bytes_read = read (mbox_data->fd, buf, 5); /* Is this a from line? */ if (!memcmp (buf, "From ", 5) && !is_header) { mbox_data->messages[maildrop->messages].header = current_pos; is_header = 1; /* here is a good point to calculate the size of the previous message */ if (maildrop->messages > 0) { maildrop->sizes[maildrop->messages-1] = current_pos - mbox_data->messages[maildrop->messages-1].header; } } /* Is this the start of the header? */ if (is_header && buf[0] == '\n') { is_header = 0; mbox_data->messages[maildrop->messages].body = current_pos - mbox_data->messages[maildrop->messages].header + 1; mbox_data->messages[maildrop->messages].attribs = MD_ATTR_NONE; maildrop->messages++; /* If we ran out of space, let's allocate some more */ if (maildrop->messages >= max_count) { void *p; max_count *= 2; p = (void *)realloc (maildrop->sizes, sizeof (size_t) * max_count); if (p == NULL) return -1; maildrop->sizes = (size_t *)p; p = (void *)realloc (mbox_data->messages, sizeof (p3l_mbox_item_t) * max_count ); if (p == NULL) return -1; mbox_data->messages = (p3l_mbox_item_t *)p; } } current_pos = newlines[i]+1; } if (maildrop->messages > 0) { maildrop->sizes[maildrop->messages-1] = current_pos - mbox_data->messages[maildrop->messages-1].header; } free (newlines); free (buf); return 0; } int p3l_maildrop_mbox_close (p3l_maildrop_t *maildrop) { p3l_mbox_t *data; if (maildrop == NULL) { errno = EINVAL; return -1; } data = (p3l_mbox_t *)(maildrop->_driver_data); /* FIXME: write back stuff here */ maildrop->_lock (maildrop, MD_LOCK_ULOCK); if (data) close (data->fd); free (data->messages); free (data); free (maildrop->sizes); maildrop->_driver_data = NULL; return 0; } int p3l_maildrop_mbox_set_attr (p3l_maildrop_t *maildrop, unsigned int message, int attr, int state) { p3l_mbox_t *data; /* if there's no maildrop, or the requested message does not * exist, bail out */ if (maildrop == NULL) { errno = EINVAL; return -1; } if (message-1 >= maildrop->messages) { errno = ERANGE; return -1; } data = (p3l_mbox_t *) maildrop->_driver_data; if (state) data->messages[message-1].attribs |= attr; else data->messages[message-1].attribs &= ~attr; return 0; } int p3l_maildrop_mbox_get_attr (p3l_maildrop_t *maildrop, unsigned int message, int attr) { p3l_mbox_t *data; if (maildrop == NULL) { errno = EINVAL; return -1; } if (message-1 >= maildrop->messages) { errno = ERANGE; return -1; } data = (p3l_mbox_t *) maildrop->_driver_data; return data->messages[message-1].attribs & attr; } int p3l_maildrop_mbox_lock (p3l_maildrop_t *maildrop, p3l_maildrop_lock_t lock) { p3l_mbox_t *data; if (maildrop == NULL) { errno = EINVAL; return -1; } data = (p3l_mbox_t *) maildrop->_driver_data; switch (lock) { case MD_LOCK_RLOCK: return p3l_lock_fd (data->fd, maildrop->name); break; case MD_LOCK_WLOCK: return p3l_lock_fd (data->fd, maildrop->name); break; case MD_LOCK_ULOCK: return p3l_unlock_fd (data->fd, maildrop->name); break; case MD_LOCK_TOUCH: return p3l_lock_touch (data->fd, maildrop->name); break; } errno = EINVAL; return -1; } size_t p3l_maildrop_mbox_get_body_size (p3l_maildrop_t *maildrop, unsigned int message) { p3l_mbox_t *data; if (maildrop == NULL) { errno = EINVAL; return -1; } if (message-1 >= maildrop->messages || maildrop->_get_attr (maildrop, message, MD_ATTR_DELE)) { errno = ERANGE; return -1; } data = (p3l_mbox_t *)maildrop->_driver_data; return (maildrop->sizes[message-1] - data->messages[message-1].body); } char * p3l_maildrop_mbox_get_body (p3l_maildrop_t *maildrop, unsigned int message) { p3l_mbox_t *data; char *buff; size_t body_size; if (maildrop == NULL) { errno = EINVAL; return NULL; } if (message-1 >= maildrop->messages || maildrop->_get_attr (maildrop, message, MD_ATTR_DELE)) { errno = ERANGE; return NULL; } data = (p3l_mbox_t *)maildrop->_driver_data; body_size = maildrop->_get_body_size (maildrop, message); /* Allocate memory for our message */ buff = (char *)malloc (body_size); if (buff == NULL) return NULL; /* Seek to the appropriate location */ if (lseek (data->fd, data->messages[message-1].header + data->messages[message-1].body, SEEK_SET) == (off_t) -1 ) return NULL; /* errno is set by lseek */ /* Read the body */ if (read (data->fd, (void *)buff, body_size) != body_size) return NULL; /* errno is already set by read */ return buff; } size_t p3l_maildrop_mbox_get_header_size (p3l_maildrop_t *maildrop, unsigned int message) { p3l_mbox_t *data; if (maildrop == NULL) { errno = EINVAL; return -1; } if (message-1 >= maildrop->messages || maildrop->_get_attr (maildrop, message, MD_ATTR_DELE)) { errno = ERANGE; return -1; } data = (p3l_mbox_t *)maildrop->_driver_data; return (data->messages[message-1].body - 1); /* -1, because the newline doesn't count */ } char * p3l_maildrop_mbox_get_header (p3l_maildrop_t *maildrop, unsigned int message) { p3l_mbox_t *data; char *buff; size_t header_size; if (maildrop == NULL) { errno = EINVAL; return NULL; } if (message-1 >= maildrop->messages || maildrop->_get_attr (maildrop, message, MD_ATTR_DELE)) { errno = ERANGE; return NULL; } data = (p3l_mbox_t *)maildrop->_driver_data; header_size = maildrop->_get_header_size (maildrop, message); /* Allocate memory for our header */ buff = (char *)malloc (header_size); if (buff == NULL) return NULL; /* Seek to the appropriate location */ if (lseek (data->fd, data->messages[message-1].header, SEEK_SET) == (off_t)-1 ) return NULL; /* errno is set by lseek */ /* Read the body */ if (read (data->fd, (void *)buff, header_size) != header_size) return NULL; /* errno is already set by read */ return buff; } int p3l_maildrop_mbox_init (char *name, p3l_maildrop_t *maildrop) { if (name == NULL || maildrop == NULL) { errno = EINVAL; return -1; } maildrop->name = name; maildrop->_open = p3l_maildrop_mbox_open; maildrop->_close = p3l_maildrop_mbox_close; maildrop->_set_attr = p3l_maildrop_mbox_set_attr; maildrop->_get_attr = p3l_maildrop_mbox_get_attr; maildrop->_lock = p3l_maildrop_mbox_lock; maildrop->_get_body = p3l_maildrop_mbox_get_body; maildrop->_get_body_size = p3l_maildrop_mbox_get_body_size; maildrop->_get_header = p3l_maildrop_mbox_get_header; maildrop->_get_header_size = p3l_maildrop_mbox_get_header_size; return 0; } --- NEW FILE --- /* * src/pop3lite/modules/maildrop/mbox/mbox.h -- mailbox handling * routine prototypes * Copyright (C) 2000, 2001 Gergely Nagy <alg...@de...> * * This file is part of POP3Lite. * * POP3Lite is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * POP3Lite is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Last updated: <2001/08/10 16:28:49 algernon> * $Id: mbox.h,v 1.1 2001/08/11 01:30:09 algernon Exp $ */ #ifndef _POP3LITE_MAILDROP_MBOX_H #define _POP3LITE_MAILDROP_MBOX_H 1 #include <pop3lite/maildrop.h> typedef struct _p3l_mbox_item_t { off_t header; /* Offset of the message header, relative to 0*/ off_t body; /* Body offset, relative to header */ int attribs; /* Message attributes (deleted, read, etc) */ } p3l_mbox_item_t; typedef struct _p3l_mbox_t { p3l_mbox_item_t *messages; p3l_maildrop_lock_t lockmode; time_t last_mod_time; size_t buffer_size; int fd; } p3l_mbox_t; /** Interface for the functions defined in pop3lite/maildrop.h **/ int p3l_maildrop_mbox_open (p3l_maildrop_t *maildrop); int p3l_maildrop_mbox_close (p3l_maildrop_t *maildrop); int p3l_maildrop_mbox_set_attr (p3l_maildrop_t *maildrop, unsigned int message, int attr, int state); int p3l_maildrop_mbox_get_attr (p3l_maildrop_t *maildrop, unsigned int message, int attr); int p3l_maildrop_mbox_lock (p3l_maildrop_t *maildrop, p3l_maildrop_lock_t lock); char *p3l_maildrop_mbox_get_body (p3l_maildrop_t *maildrop, unsigned int message); size_t p3l_maildrop_mbox_get_body_size (p3l_maildrop_t *maildrop, unsigned int message); char *p3l_maildrop_mbox_get_header (p3l_maildrop_t *maildrop, unsigned int message); size_t p3l_maildrop_mbox_get_header_size (p3l_maildrop_t *maildrop, unsigned int message); int p3l_maildrop_mbox_init(char *name, p3l_maildrop_t *maildrop); #endif /* ! _POP3LITE_MBOX_H */ |