[SVN] r450 - /branches/cvsmerge/cyrus-cvs/imap/mbdump.c

debian at incase.de debian at incase.de
Fri May 12 09:47:52 UTC 2006


Author: sven
Date: Fri May 12 11:47:51 2006
New Revision: 450

URL: https://mail.incase.de/viewcvs?rev=450&root=cyrus22&view=rev
Log:
remove limit on the size of mailbox files that can be received by UNDUMP
(write file directly to disk rather than reading the literal into memory)

Modified:
    branches/cvsmerge/cyrus-cvs/imap/mbdump.c

Modified: branches/cvsmerge/cyrus-cvs/imap/mbdump.c
URL: https://mail.incase.de/viewcvs/branches/cvsmerge/cyrus-cvs/imap/mbdump.c?rev=450&root=cyrus22&r1=449&r2=450&view=diff
==============================================================================
--- branches/cvsmerge/cyrus-cvs/imap/mbdump.c (original)
+++ branches/cvsmerge/cyrus-cvs/imap/mbdump.c Fri May 12 11:47:51 2006
@@ -1,5 +1,5 @@
 /* mbdump.c -- Mailbox dump routines
- * $Id: mbdump.c,v 1.30 2004/05/22 03:45:51 rjs3 Exp $
+ * $Id: mbdump.c,v 1.31 2006/05/11 17:43:18 murch Exp $
  * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -585,6 +585,10 @@
     while(1) {
 	char fnamebuf[MAX_MAILBOX_PATH + 1024];
 	char *seen_file = NULL;
+	int isnowait, sawdigit;
+	unsigned long size;
+	unsigned long cutoff = ULONG_MAX / 10;
+	unsigned digit, cutlim = ULONG_MAX % 10;
 	
       	c = getastring(pin, pout, &file);
 	if(c != ' ') {
@@ -676,11 +680,41 @@
 
 	    continue;
 	}
-	    
-	c = getbastring(pin, pout, &data);
-	if(c != ' ' && c != ')') {
+
+	/* read size of literal */
+	c = prot_getc(pin);
+	if (c != '{') {
 	    r = IMAP_PROTOCOL_ERROR;
 	    goto done;
+	}
+
+	size = isnowait = sawdigit = 0;
+	while ((c = prot_getc(pin)) != EOF && isdigit(c)) {
+	    sawdigit = 1;
+	    digit = c - '0';
+	    /* check for overflow */
+	    if (size > cutoff || (size == cutoff && digit > cutlim)) {
+                fatal("literal too big", EC_IOERR);
+            }
+	    size = size*10 + digit;
+	}
+	if (c == '+') {
+	    isnowait++;
+	    c = prot_getc(pin);
+	}
+	if (c == '}') {
+	    c = prot_getc(pin);
+	    if (c == '\r') c = prot_getc(pin);
+	}
+	if (!sawdigit || c != '\n') {
+	    r = IMAP_PROTOCOL_ERROR;
+	    goto done;
+	}
+
+	if (!isnowait) {
+	    /* Tell client to send the message */
+	    prot_printf(pout, "+ go ahead\r\n");
+	    prot_flush(pout);
 	}
 
 	if(userid && !strcmp(file.s, "SUBS")) {
@@ -742,7 +776,7 @@
 	    if(strncmp(file.s, "cyrus.", 6)) {
 		/* it doesn't match cyrus.*, so its a message file.
 		 * charge it against the quota */
-		quotaused += data.len;
+		quotaused += size;
 	    }
 	}	
 
@@ -760,10 +794,24 @@
 	    goto done;
 	}
 
-	if(write(curfile,data.s,data.len) == -1) {
-	    syslog(LOG_ERR, "IOERROR: writing %s: %m", fnamebuf);
-	    r = IMAP_IOERROR;
-	    goto done;
+	/* write data to file */
+	while (size) {
+	    char buf[4096+1];
+	    int n = prot_read(pin, buf, size > 4096 ? 4096 : size);
+	    if (!n) {
+		syslog(LOG_ERR,
+		       "IOERROR: reading message: unexpected end of file");
+		r = IMAP_IOERROR;
+		goto done;
+	    }
+
+	    size -= n;
+
+	    if (write(curfile, buf, n) != n) {
+		syslog(LOG_ERR, "IOERROR: writing %s: %m", fnamebuf);
+		r = IMAP_IOERROR;
+		goto done;
+	    }
 	}
 
 	close(curfile);
@@ -777,7 +825,12 @@
 	    unlink(fnamebuf);
 	}
 	
-	if(c == ')') break;
+	c = prot_getc(pin);
+	if (c == ')') break;
+	if (c != ' ') {
+	    r = IMAP_PROTOCOL_ERROR;
+	    goto done;
+	}
     }
     
     if(!r && quotaused) {



More information about the Pkg-Cyrus-imapd-Debian-devel mailing list