[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd
From: |
Beau Kuiper |
Subject: |
[Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd |
Date: |
Wed, 19 Nov 2003 08:00:22 -0500 |
Module name: muddleftpd
Branch: dev-rugger-nat
Changes by: Beau Kuiper <address@hidden> 03/11/19 08:00:22
Reply-to: address@hidden
CVSROOT: /cvsroot/muddleftpd
Module name: muddleftpd
Branch: dev-rugger-nat
Changes by: Beau Kuiper <address@hidden> 03/11/19 08:00:22
Modified files:
. : ChangeLog NEWS
src : ftptrans.c
Log message:
Fixed file descriptor leak when a user attempts to download a file
after they have exhausted their file download credits
CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/muddleftpd/muddleftpd/ChangeLog.diff?only_with_tag=dev-rugger-nat&tr1=1.9.2.3&tr2=1.9.2.4&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/muddleftpd/muddleftpd/NEWS.diff?only_with_tag=dev-rugger-nat&tr1=1.4.2.2&tr2=1.4.2.3&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/muddleftpd/muddleftpd/src/ftptrans.c.diff?only_with_tag=dev-rugger-nat&tr1=1.1&tr2=1.1.8.1&r1=text&r2=text
Patches:
Index: muddleftpd/ChangeLog
diff -c muddleftpd/ChangeLog:1.9.2.3 muddleftpd/ChangeLog:1.9.2.4
*** muddleftpd/ChangeLog:1.9.2.3 Wed Nov 19 00:24:41 2003
--- muddleftpd/ChangeLog Wed Nov 19 08:00:21 2003
***************
*** 2,7 ****
--- 2,9 ----
* checkip.c: Added code to detect and use abbreviated netmasks, eg
192.168.1.0/24.
+ * ftptrans.c: Fixed file descriptor leak when a user's file quota is
+ is exhausted and they attempt to download more.
2003-11-06 Beau Kuiper <address@hidden>
Index: muddleftpd/NEWS
diff -c muddleftpd/NEWS:1.4.2.2 muddleftpd/NEWS:1.4.2.3
*** muddleftpd/NEWS:1.4.2.2 Wed Nov 19 00:24:41 2003
--- muddleftpd/NEWS Wed Nov 19 08:00:21 2003
***************
*** 14,19 ****
--- 14,20 ----
the servers external address specified by ipnat option.
5) Change: Added support for abbreviated netmasks, eg 192.168.0.0/24
instead of 192.168.0.0/255.255.0.0.
+ 6) Bug Fix: Fixed file decriptor leak in ratio code.
Version 1.3.13:
Index: muddleftpd/src/ftptrans.c
diff -c /dev/null muddleftpd/src/ftptrans.c:1.1.8.1
*** /dev/null Wed Nov 19 08:00:22 2003
--- muddleftpd/src/ftptrans.c Wed Nov 19 08:00:22 2003
***************
*** 0 ****
--- 1,361 ----
+ /* Copyright (C) 1999 Beau Kuiper
+
+ This program 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, or (at your option)
+ any later version.
+
+ This program 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+ #include "ftpd.h"
+ #include "ftpcmd.h"
+ #include "reply.h"
+
+ extern FTPCMD ftpcommandtable[];
+
+
+ int filter_toascii(char *data, int *len)
+ {
+ int count, len2 = *len;
+ char buffer2[BUFFERSIZE * 2];
+ int last = 0;
+ char *b2ptr = buffer2;
+
+ for (count = 0; count < len2; count++)
+ {
+ if ((data[count] == 10) && (last != 13))
+ {
+ *b2ptr = 13;
+ b2ptr++;
+ (*len)++;
+ }
+ *b2ptr = data[count];
+ last = *b2ptr;
+ b2ptr++;
+ }
+ memcpy(data, buffer2, *len);
+ return(*len);
+ }
+
+ int filter_fromascii(char *data, int *len)
+ {
+ char *dptr = data;
+ int count, len2 = *len;
+
+ for (count = 0; count < len2; count++)
+ {
+ if (data[count] != 13)
+ {
+ *dptr = data[count];
+ dptr++;
+ }
+ else
+ (*len)--;
+ }
+ return(len2);
+ }
+
+ int download_write(SELECTER *sel, int fd, void *peerv)
+ {
+ FTPSTATE *peer = (FTPSTATE *)peerv;
+ DATAPORT *d = peer->dport;
+ int startp, size, size2, finished = FALSE;
+ char indata[BUFFERSIZE * 2];
+ int maxsize;
+
+ /* determine maximum transfer size */
+
+ if (peer->maxtranspd_down)
+ maxsize = MINIMUM(peer->maxtranspd_down, BUFFERSIZE);
+ else if (peer->maxtranspd)
+ maxsize = MINIMUM(peer->maxtranspd, BUFFERSIZE);
+ else
+ maxsize = BUFFERSIZE;
+
+ /* if we have binary mode and no ratios to worry about,
+ use sendfile to improve performace. A huge amount of data
+ may be transmitted at a time using sendfile. But at the moment
+ sendfile in Linux REALLY SUCKS. Must keep size small otherwise
+ I hog processor/machine from other processes. Even other CPUS
+ are halted during a sendfile! (also any file operation) */
+
+ #ifdef HAVE_SENDFILE
+ #ifdef Linux /* Don't know if this will work all the time */
+
+ if ((d->binary) && (!peer->ratioinfo))
+ {
+ if (d->startpos != 0)
+ {
+ d->pos = d->startpos;
+ d->startpos = 0;
+ }
+ size2 = size = sendfile(d->socketfd, d->filefd, &(d->pos),
maxsize);
+ } else
+ #endif
+ #ifdef FreeBSD
+ if ((d->binary) && (!peer->ratioinfo))
+ {
+ int result;
+ if (d->startpos != 0)
+ {
+ d->pos = d->startpos;
+ d->startpos = 0;
+ }
+ result = sendfile(d->filefd, d->socketfd, d->pos, maxsize,
+ NULL, (off_t *)&size, 0);
+ d->pos += size;
+ if ((result == -1) && (errno != EAGAIN))
+ size = -1;
+ size2 = size;
+ } else
+ #endif
+ #endif
+ if (STRLENGTH(d->buffer) == 0)
+ {
+ size = read(d->filefd, indata, maxsize);
+ size2 = 0;
+
+ if ((size > 0) && (!d->binary))
+ filter_toascii(indata, &size);
+
+ d->pos += size;
+ if (d->pos < d->startpos)
+ return(FALSE);
+ else
+ startp = MAXIMUM(0, size - (d->pos - d->startpos));
+
+ if (((size - startp) > 0) && (peer->ratioinfo))
+ if (ratio_downloadbytes(peer->ratioinfo, (size -
startp)))
+ {
+ finished = TRUE;
+ size = 0;
+ ftp_write(peer, TRUE, 0, REPLY_BYTELIMIT);
+ }
+
+ if ((size > 0) && (startp != size))
+ size2 = write(d->socketfd, indata + startp, size -
startp);
+
+ if ((size2 > 0) && ((size2 + startp) < size))
+ string_cat(&(d->buffer), indata + startp + size2, size
- (startp + size2));
+ }
+ else
+ {
+ size = size2 = write(d->socketfd, STRTOCHAR(d->buffer),
STRLENGTH(d->buffer));
+ if (size2 > 0)
+ string_dropfront(&(d->buffer), size);
+ }
+
+ if ((size <= 0) || (size2 <= 0) || finished)
+ {
+ if (d->download_limiter)
+ limiter_add(d->download_limiter, 0, TRUE);
+
+ select_delfd(sel, d->filefd);
+ if ((size == 0) && (!finished))
+ ftp_write(peer, FALSE, 226,
REPLY_TRANSDONE(peer->dport->transbytes));
+ else
+ ftp_write(peer, FALSE, 426,
REPLY_TRANSABORT(peer->dport->transbytes));
+ closedatasocket(peer);
+ return(2);
+ }
+
+ if (d->download_limiter)
+ limiter_add(d->download_limiter, size, FALSE);
+
+ d->transbytes += size;
+ peer->downloadedfilebytes += size;
+ return(FALSE);
+ }
+
+ int upload_read(SELECTER *sel, int fd, void *peerv)
+ {
+ FTPSTATE *peer = (FTPSTATE *)peerv;
+ DATAPORT *d = peer->dport;
+ int size, size2;
+ int finished = FALSE;
+ char indata[BUFFERSIZE * 2];
+ int maxsize;
+
+ /* determine maximum read size */
+
+ if (peer->maxtranspd_up)
+ maxsize = MINIMUM(peer->maxtranspd_up, BUFFERSIZE);
+ else if (peer->maxtranspd)
+ maxsize = MINIMUM(peer->maxtranspd, BUFFERSIZE);
+ else
+ maxsize = BUFFERSIZE;
+
+ size = read(d->socketfd, indata, maxsize);
+
+ /* false alarm, no data, return */
+ if ((size == -1) && (errno == EAGAIN))
+ return FALSE;
+
+ if (size > 0)
+ {
+ d->transbytes += size;
+ peer->uploadedfilebytes += size;
+ if (peer->maxtranspd || peer->maxtranspd_up)
+ limiter_add(d->upload_limiter, size, FALSE);
+ if (peer->ratioinfo)
+ ratio_uploadbytes(peer->ratioinfo, size);
+ }
+
+ if ((size > 0) && (!d->binary))
+ filter_fromascii(indata, &size);
+
+ if (size > 0)
+ {
+ int re = 0;
+ size2 = 0;
+ while(((size - size2) > 0) && (re != -1))
+ {
+ re = write(d->filefd, indata + size2, size - size2);
+ if (re == -1)
+ finished = TRUE;
+ else
+ size2 += re;
+ }
+ }
+
+ if ((size <= 0) || finished)
+ {
+ select_delfd(sel, d->filefd);
+ if (peer->maxtranspd || peer->maxtranspd_up)
+ limiter_add(d->upload_limiter, size, FALSE);
+
+ if ((size == 0) && (!finished))
+ ftp_write(peer, FALSE, 226,
REPLY_TRANSDONE(peer->dport->transbytes));
+ else
+ ftp_write(peer, FALSE, 426,
REPLY_TRANSABORT(peer->dport->transbytes));
+ closedatasocket(peer);
+ return(2);
+ }
+
+
+ return(FALSE);
+ }
+
+ int ftp_retr(FTPSTATE *peer, char *filename)
+ {
+ int filefd;
+ off_t size;
+ char *fullname;
+
+ if ((filefd = file_readopen(peer, filename, &fullname)) < 0)
+ reporterror(peer, filename, errno);
+ else
+ {
+ if (peer->ratioinfo)
+ if (ratio_downloadfile(peer->ratioinfo))
+ {
+ ftp_write(peer, FALSE, 550, REPLY_FILELIMIT);
+ close(filefd);
+ return(FALSE);
+ }
+
+ peer->downloadedfiles++;
+
+ /* if ascii transfer size is set to -1, else size is binary
filesize */
+ size = -1;
+ if (peer->binary)
+ {
+ size = lseek(filefd, 0, SEEK_END);
+ lseek(filefd, MINIMUM(size, peer->restartpos),
SEEK_SET);
+ }
+
+ if (startdatasocket(peer, filefd, TRANS_DOWNLOAD, size) == 0)
+ log_giveentry(MYLOG_FTRANS, peer,
safe_snprintf("retrieve %s", fullname));
+ }
+ freewrapper(fullname);
+ return(FALSE);
+ }
+
+ int ftp_stor_core(FTPSTATE *peer, char *filename, int unique)
+ {
+ int filefd;
+ int nounique = FALSE;
+ char *fullname;
+
+ /* There is 2 good reasons thus is here:
+ 1) My code won't work for resume ASCII upload.
+ 2) It is impossible to do. Telnet ascii to unix ascii is
+ irreversible. Therefore you don't know where the user
+ wants to start saving.
+ */
+ if ((peer->restartpos != 0) && (!peer->binary))
+ return(ftp_write(peer, FALSE, 500, REPLY_RESUMEASCIIUP));
+
+ /* if the user asked for a unique filename, find one */
+ if (unique)
+ filefd = file_ustoreopen(peer, filename, &nounique, &fullname);
+ else
+ filefd = file_storeopen(peer, filename, &fullname);
+
+ if (nounique)
+ ftp_write(peer, FALSE, 500, REPLY_STOUNOUNIQUE);
+ else if (filefd < 0)
+ reporterror(peer, filename, errno);
+ else
+ {
+ peer->uploadedfiles++;
+ if (startdatasocket(peer, filefd, TRANS_UPLOAD, -1) == 0)
+ {
+ log_giveentry(MYLOG_FTRANS, peer, safe_snprintf("store
%s", fullname));
+ /* now truncate the file to the restart pos length */
+ ftruncate(filefd, peer->dport->pos);
+ lseek(filefd, peer->dport->pos, SEEK_SET);
+ }
+ }
+
+ freewrapper(fullname);
+ return(FALSE);
+ }
+
+ int ftp_stor(FTPSTATE *peer, char *filename)
+ {
+ return(ftp_stor_core(peer, filename, FALSE));
+ }
+
+ int ftp_stou(FTPSTATE *peer, char *filename)
+ {
+ return(ftp_stor_core(peer, filename, TRUE));
+ }
+
+ int ftp_appe(FTPSTATE *peer, char *filename)
+ {
+ int filefd;
+ char *fullname;
+
+ peer->restartpos = 0;
+
+ filefd = file_storeopen(peer, filename, &fullname);
+
+ if (filefd < 0)
+ reporterror(peer, filename, errno);
+ else
+ {
+ peer->uploadedfiles++;
+
+ if (startdatasocket(peer, filefd, TRANS_UPLOAD, -1) == 0)
+ {
+ log_giveentry(MYLOG_FTRANS, peer, safe_snprintf("append
%s", fullname));
+
+ /* this is for ratios, If the final file position is 0,
then it is
+ a fresh upload. */
+ if (lseek(filefd, 0, SEEK_END) == 0) /* set to append */
+ peer->dport->trans_type = TRANS_SUPLOAD;
+
+ }
+ }
+
+ freewrapper(fullname);
+ return(FALSE);
+ }
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, (continued)
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Joerg Jaspert, 2003/11/06
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Joerg Jaspert, 2003/11/06
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Joerg Jaspert, 2003/11/06
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Joerg Jaspert, 2003/11/06
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Joerg Jaspert, 2003/11/06
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Joerg Jaspert, 2003/11/06
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Joerg Jaspert, 2003/11/06
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Joerg Jaspert, 2003/11/06
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Joerg Jaspert, 2003/11/06
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Beau Kuiper, 2003/11/19
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd,
Beau Kuiper <=