muddleftpd-cvs
[Top][All Lists]
Advanced

[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);
+ }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]