source: TI05-delivery/trunk/src/bbftp-server-3.2.0/bbftpd/bbftpd_retr.c @ 1392

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI05-delivery/trunk/src/bbftp-server-3.2.0/bbftpd/bbftpd_retr.c@1392
Revision 1392, 33.0 KB checked in by spascoe, 13 years ago (diff)

More missing #includes exposed when compiling on easterly.

Line 
1/*
2 * bbftpd/bbftpd_retr.c
3 * Copyright (C) 1999, 2000, 2001, 2002 IN2P3, CNRS
4 * bbftp@in2p3.fr
5 * http://doc.in2p3.fr/bbftp
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 */ 
21
22/****************************************************************************
23
24 
25 bbftpd_retr.c  v 2.0.0 2001/02/22  - Routines creation
26                v 2.0.1 2001/04/17  - Realy wait STARTCHILDTO
27                                    - Correct indentation
28                                    - Port to IRIX
29                v 2.0.2 2001/05/04  - Correct include for RFIO
30                v 2.1.0 2001/05/30  - Correct bbftpd_log level
31                                    - Reorganise routines as in bbftp_
32             
33*****************************************************************************/
34#include <bbftpd.h>
35
36#include <stdio.h>
37
38#include <stdlib.h>
39#include <dirent.h>
40#include <errno.h>
41#include <fcntl.h>
42#include <fnmatch.h>
43#include <netinet/in.h>
44#include <signal.h>
45#include <bbftpd_private_log.h>
46#include <sys/stat.h>
47#include <sys/types.h>
48#if TIME_WITH_SYS_TIME
49# include <sys/time.h>
50# include <time.h>
51#else
52# if HAVE_SYS_TIME_H
53#  include <sys/time.h>
54# else
55#  include <time.h>
56# endif
57#endif
58#include <unistd.h>
59#include <utime.h>
60#if HAVE_STRING_H
61# include <string.h>
62#endif
63
64#include <common.h>
65#include <daemon.h>
66#include <daemon_proto.h>
67#include <status.h>
68#include <structures.h>
69
70#ifdef WITH_GZIP
71#include <zlib.h>
72#endif
73
74extern int  transferoption ;
75extern my64_t  filesize ;
76extern int  requestedstreamnumber ;
77extern int  buffersizeperstream ;
78extern int  maxstreams ;
79extern int  filemode ;
80extern int  *myports ;
81extern char *readbuffer ;
82extern char *compbuffer ;
83extern int  *mychildren ;
84extern int  *mysockets ;
85extern int  nbpidchild ;
86extern int  unlinkfile ;
87extern int  incontrolsock ;
88extern int  outcontrolsock ;
89extern  int     datato ;
90extern  int     ackto ;
91extern int  state ;
92extern int  childendinerror ;
93extern int  flagsighup ;
94extern char lastaccess[9] ;
95extern char lastmodif[9] ;
96extern struct  timeval  tstart ;
97extern int  protocolversion ;
98
99/*******************************************************************************
100** bbftpd_retrlisdir :                                                         *
101**                                                                             *
102**      Routine to list a directory                                            *
103**                                                                             *
104**      OUPUT variable :                                                       *
105**          filelist   :  Where to store the file list (to be freed by caller  *
106**          filelistlen:  Length of filelist buffer                            *
107**          logmessage :  to write the error message in case of error          *
108**                                                                             *
109**      GLOBAL VARIABLE USED :                                                 *                                                                      *
110**                                                                             *
111**      RETURN:                                                                *
112**          -1  Unrecoverable error                                            *
113**           0  OK                                                             *
114**           1  recoverable error                                              *
115**                                                                             *
116*******************************************************************************/
117
118int bbftpd_retrlistdir(char *pattern,char **filelist,int *filelistlen,char *logmessage)
119{
120    int     lastslash ;
121    char    *pointer ;
122    char    *dirpath ;
123     DIR     *curdir ;
124#ifdef STANDART_FILE_CALL
125    struct dirent *dp ;
126    struct stat statbuf;
127#else
128#ifdef STANDART_READDIR_CALL
129    struct dirent *dp ;
130#else
131    struct dirent64 *dp ;
132#endif
133    struct stat64 statbuf ;
134#endif
135    int     lengthtosend;
136    int     numberoffile ;
137    /*
138    ** Structure to keep the filenames
139    */
140    struct keepfile {
141        char    *filename ;
142        char    filechar[3] ;
143        struct  keepfile *next ;
144    } ;
145    struct keepfile *first_item ;
146    struct keepfile *current_item ;
147    struct keepfile *used_item ;
148    char    *filepos ;
149    int     i ;
150    int     savederrno ;
151   
152    /*
153    ** Check if it is a rfio list
154    */
155    if ( (transferoption & TROPT_RFIO) == TROPT_RFIO ) {
156#if defined(WITH_RFIO) || defined(WITH_RFIO64)
157        return bbftpd_retrlistdir_rfio(pattern,filelist,filelistlen,logmessage) ;
158#else
159        /*
160        ** Just reply that RFIO is not supported
161        */
162        sprintf(logmessage,"Fail to LIST : RFIO not supported") ;
163        return -1 ;
164#endif
165    }
166    /*
167    **  We are going allocate memory for the directory name
168    **  We allocate stelent(pattern) + 1 char for \0 + 3 char
169    **  if the directory is "."
170    */
171    if ( (dirpath = (char *) malloc ( strlen(pattern) + 1 + 3 )) == NULL ) {
172        sprintf(logmessage,"Error allocating memory for dirpath %s",strerror(errno)) ;
173        return -1 ;
174    } 
175    pointer = pattern ;
176    lastslash = strlen(pointer) - 1 ;
177    while ( lastslash >= 0 && pointer[lastslash] != '/') lastslash-- ;
178    if ( lastslash == -1 ) {
179        /*
180        ** No slash in the path, so this is a pattern and we have
181        ** to opendir .
182        */
183        if ( (curdir = opendir(".")) == NULL ) {
184            savederrno = errno ;
185            sprintf(logmessage,"opendir . failed : %s ",strerror(errno)) ;
186            if ( savederrno == EACCES ) {
187                FREE(dirpath) ;
188                return -1 ;
189            } else {
190                FREE(dirpath) ;
191                return 1 ;
192            }
193        }
194        strcpy(dirpath,"./") ;
195    } else if ( lastslash == 0 ) {
196        /*
197        ** A slash in first position so we are going to open the
198        ** / directory
199        */
200        if ( (curdir = opendir("/")) == NULL ) {
201            savederrno = errno ;
202            sprintf(logmessage,"opendir / failed : %s ",strerror(errno)) ;
203            if ( savederrno == EACCES ) {
204                FREE(dirpath) ;
205                return -1 ;
206            } else {
207                FREE(dirpath) ;
208                return 1 ;
209            }
210        }
211        strcpy(dirpath,"/") ;
212        pointer++ ;
213    } else if ( lastslash == strlen(pointer) - 1 ) {
214        /*
215        ** The filename end with a slash ..... error
216        */
217        sprintf(logmessage,"Pattern %s ends with a /",pattern) ;
218        FREE(dirpath) ;
219        return -1 ;
220    } else {
221        pointer[lastslash] = '\0';
222        /*
223        ** Srip unnecessary / at the end of dirpath and reset
224        ** only one
225        */
226        strcpy(dirpath,pointer) ;
227        strip_trailing_slashes(dirpath) ;
228        dirpath[strlen(dirpath)+1] = '\0';
229        dirpath[strlen(dirpath)] = '/';
230        if ( (curdir = opendir(dirpath)) == NULL ) {
231            savederrno = errno ;
232            sprintf(logmessage,"opendir %s failed : %s ",dirpath,strerror(errno)) ;
233            if ( savederrno == EACCES ) {
234                FREE(dirpath) ;
235                return -1 ;
236            } else {
237                FREE(dirpath) ;
238                return 1 ;
239            }
240        }
241        for ( i = 0 ; i <= lastslash ; i++ ) pointer++ ;
242    }
243    /*
244    ** At this stage pointer point to the pattern and curdir
245    ** is the opened directory and dirpath contain the
246    ** directory name
247    */
248    /*
249    ** As we are using the fnmatch routine we are obliged to
250    ** first count the number of bytes we are sending.
251    */
252    lengthtosend = 0 ;
253    numberoffile = 0 ;
254    errno = 0 ;
255    first_item = NULL ;
256#ifdef STANDART_FILE_CALL
257    while ( (dp = readdir(curdir) ) != NULL) {
258#else
259#ifdef STANDART_READDIR_CALL
260    while ( (dp = readdir(curdir) ) != NULL) {
261#else
262    while ( (dp = readdir64(curdir) ) != NULL) {
263#endif
264#endif
265        if ( fnmatch(pointer, dp->d_name,0) == 0) {
266            numberoffile++ ;
267            lengthtosend = lengthtosend +  strlen(dirpath) + strlen(dp->d_name) + 1 + 3 ;
268            if ( ( current_item = (struct keepfile *) malloc( sizeof(struct keepfile)) ) == NULL ) {
269                sprintf(logmessage,"Error getting memory for structure : %s",strerror(errno)) ;
270                current_item = first_item ;
271                while ( current_item != NULL ) {
272                    free(current_item->filename) ;
273                    used_item = current_item->next ;
274                    free(current_item) ;
275                    current_item = used_item ;
276                }
277                closedir(curdir) ;
278                FREE(dirpath) ;
279                return 1 ;
280            }
281            if ( ( current_item->filename = (char *) malloc( strlen(dirpath) + strlen(dp->d_name) + 1) ) == NULL ) {
282                sprintf(logmessage,"Error getting memory for filename : %s",strerror(errno)) ;
283                /*
284                ** Clean memory
285                */
286                FREE(current_item) ;
287                current_item = first_item ;
288                while ( current_item != NULL ) {
289                    free(current_item->filename) ;
290                    used_item = current_item->next ;
291                    free(current_item) ;
292                    current_item = used_item ;
293                }
294                closedir(curdir) ;
295                FREE(dirpath) ;
296                return 1 ;
297            }
298            current_item->next = NULL ;
299            if ( first_item == NULL ) {
300                first_item = current_item ;
301                used_item = first_item ;
302            } else {
303                used_item = first_item ;
304                while ( used_item->next != NULL ) used_item = used_item->next ;
305                used_item->next = current_item ;
306            }
307            sprintf(current_item->filename,"%s%s",dirpath,dp->d_name) ;
308#ifdef STANDART_FILE_CALL
309            if ( lstat(current_item->filename,&statbuf) < 0 ) {
310#else
311            if ( lstat64(current_item->filename,&statbuf) < 0 ) {
312#endif
313                sprintf(logmessage,"Error lstating file %s",current_item->filename) ;
314                current_item = first_item ;
315                while ( current_item != NULL ) {
316                    free(current_item->filename) ;
317                    used_item = current_item->next ;
318                    free(current_item) ;
319                    current_item = used_item ;
320                }
321                closedir(curdir) ;
322                FREE(dirpath) ;
323                return 1 ;
324             }
325             if ( (statbuf.st_mode & S_IFLNK) == S_IFLNK) {
326                current_item->filechar[0] = 'l' ;
327#ifdef STANDART_FILE_CALL
328                if ( stat(current_item->filename,&statbuf) < 0 ) {
329#else
330                if ( stat64(current_item->filename,&statbuf) < 0 ) {
331#endif
332                    /*
333                    ** That means that the link refer to an unexisting file
334                    */
335                    current_item->filechar[1] = 'u' ;
336                } else {
337                    if ( (statbuf.st_mode & S_IFDIR) == S_IFDIR) {
338                        current_item->filechar[1] = 'd' ;
339                    } else {
340                        current_item->filechar[1] = 'f' ;
341                    }
342                }
343            } else {
344                current_item->filechar[0] = ' ' ;
345                if ( (statbuf.st_mode & S_IFDIR) == S_IFDIR) {
346                    current_item->filechar[1] = 'd' ;
347                } else {
348                    current_item->filechar[1] = 'f' ;
349                }
350            }
351            current_item->filechar[2] = '\0' ;
352        }
353        errno = 0 ;
354    }
355    /*
356    ** Check errno in case of error during readdir
357    ** for the following readir we are not going to check
358    ** so that may be a cause of problem
359    */
360    if ( errno != 0 ) {
361        sprintf(logmessage,"Error on readdir %s (%s) ",dirpath,strerror(errno)) ;
362        current_item = first_item ;
363        while ( current_item != NULL ) {
364            free(current_item->filename) ;
365            used_item = current_item->next ;
366            free(current_item) ;
367            current_item = used_item ;
368        }
369        closedir(curdir) ;
370        FREE(dirpath) ;
371        return 1 ;
372    }
373    /*
374    ** Check if numberoffile is zero and reply now in this
375    ** case
376    */
377    if ( numberoffile == 0 ) {
378        *filelistlen = 0 ;
379        closedir(curdir) ;
380        current_item = first_item ;
381        while ( current_item != NULL ) {
382            free(current_item->filename) ;
383            used_item = current_item->next ;
384            free(current_item) ;
385            current_item = used_item ;
386        }
387        FREE(dirpath) ;
388        return 0 ;
389    }
390    /*
391    ** Now everything is ready so prepare the answer
392    */
393    if ( ( *filelist = (char *) malloc (lengthtosend) ) == NULL ) {
394        sprintf(logmessage,"Error allocating memory for filelist %s",strerror(errno)) ;
395        closedir(curdir) ;
396        current_item = first_item ;
397        while ( current_item != NULL ) {
398            free(current_item->filename) ;
399            used_item = current_item->next ;
400            free(current_item) ;
401            current_item = used_item ;
402        }
403        FREE(dirpath) ;
404        return -1 ;
405    }
406    current_item = first_item ;
407    filepos = *filelist ;
408    while ( current_item != NULL ) {
409        sprintf(filepos,"%s",current_item->filename) ;
410        filepos = filepos + strlen(filepos) + 1 ;
411        sprintf(filepos,"%s",current_item->filechar) ;
412        filepos = filepos + strlen(filepos) + 1 ;
413        current_item = current_item->next ;
414    }
415    *filelistlen = lengthtosend ;
416    closedir(curdir) ;
417    current_item = first_item ;
418    while ( current_item != NULL ) {
419        free(current_item->filename) ;
420        used_item = current_item->next ;
421        free(current_item) ;
422        current_item = used_item ;
423    }
424    FREE(dirpath) ;
425    return 0 ;   
426}
427
428
429
430
431
432/*******************************************************************************
433** bbftpd_retrcheckfile :                                                      *
434**                                                                             *
435**      Routine to check a file and set the global parameters                  *
436**                                                                             *
437**      OUPUT variable :                                                       *
438**          logmessage :  to write the error message in case of error          *
439**                                                                             *
440**      GLOBAL VARIABLE USED :                                                 *                                                                      *
441**          transferoption                      NOT MODIFIED                   *
442**          filemode                            MODIFIED                       *
443**          lastaccess                          MODIFIED                       *
444**          lastmodif                           MODIFIED                       *
445**          filesize                            MODIFIED                       *
446**          requestedstreamnumber               POSSIBLY MODIFIED              *
447**                                                                             *
448**      RETURN:                                                                *
449**          -1  Incorrect check unrecoverable error                            *
450**           0  OK                                                             *
451**          >0  Incorrect check recoverable error                              *
452**                                                                             *
453*******************************************************************************/
454
455int bbftpd_retrcheckfile(char *filename,char *logmessage)
456{
457#ifdef STANDART_FILE_CALL
458    struct stat statbuf;
459#else
460    struct stat64 statbuf ;
461#endif
462    int     tmpnbport ;
463    int     savederrno ;
464    /*
465    ** Check if it is a rfio creation
466    */
467    if ( (transferoption & TROPT_RFIO) == TROPT_RFIO ) {
468#if defined(WITH_RFIO) || defined(WITH_RFIO64)
469        return bbftpd_retrcheckfile_rfio(filename,logmessage) ;
470#else
471        sprintf(logmessage,"Fail to retreive : RFIO not supported") ;
472        return -1 ;
473#endif
474    }
475
476#ifdef STANDART_FILE_CALL
477    if ( stat(filename,&statbuf) < 0 ) {
478#else
479    if ( stat64(filename,&statbuf) < 0 ) {
480#endif
481        /*
482        ** It may be normal to get an error if the file
483        ** does not exist but some error code must lead
484        ** to the interruption of the transfer:
485        **        EACCES        : Search permission denied
486        **        ELOOP        : To many symbolic links on path
487        **        ENAMETOOLONG: Path argument too long
488        **        ENOENT        : The file does not exists
489        **        ENOTDIR        : A component in path is not a directory
490        */
491        savederrno = errno ;
492        sprintf(logmessage,"Error stating file %s : %s ",filename,strerror(savederrno)) ;
493        if ( savederrno == EACCES ||
494            savederrno == ELOOP ||
495            savederrno == ENAMETOOLONG ||
496            savederrno == ENOENT ||
497            savederrno == ENOTDIR ) {
498            return -1 ;
499        } else {
500            return 1 ;
501        }
502    } else {
503        /*
504        ** The file exists so check if it is a directory
505        */
506        if ( (statbuf.st_mode & S_IFDIR) == S_IFDIR) {
507            sprintf(logmessage,"File %s is a directory",filename) ;
508            return -1 ;
509        }
510    }
511    sprintf(lastaccess,"%08x",statbuf.st_atime) ;
512    sprintf(lastmodif,"%08x",statbuf.st_mtime) ;
513    lastaccess[8] = '\0' ;
514    lastmodif[8]  = '\0' ;
515    if (S_ISREG(statbuf.st_mode)) {
516        filemode = statbuf.st_mode & ~S_IFREG;
517    } else {
518        filemode = statbuf.st_mode;
519    }
520    filesize = statbuf.st_size ;
521    tmpnbport = filesize/(buffersizeperstream*1024) ;
522    if ( tmpnbport == 0 ) {
523        requestedstreamnumber = 1 ;
524    } else if ( tmpnbport < requestedstreamnumber ) {
525        requestedstreamnumber = tmpnbport ;
526    }
527    if ( requestedstreamnumber > maxstreams ) requestedstreamnumber = maxstreams ;
528    return 0 ;   
529}
530
531/*******************************************************************************
532** bbftpd_retrtransferfile :                                                   *
533**                                                                             *
534**      Routine to transfer a file                                             *
535**                                                                             *
536**      INPUT variable :                                                       *
537**          filename    :  file to send    NOT MODIFIED                        *
538**                                                                             *
539**      OUTPUT variable :                                                      *
540**          logmessage :  to write the error message in case of error          *
541**                                                                             *
542**      GLOBAL VARIABLE USED :                                                 *                                                                      *
543**                                                                             *
544**      RETURN:                                                                *
545**          -1  transfer failed unrecoverable error                            *
546**           0  Keep the connection open (does not mean that the file has been *
547**                successfully transfered)                                     *
548**          >0  Recoverable error but calling has the cleaning to do           *
549**                                                                             *
550*******************************************************************************/
551 
552int bbftpd_retrtransferfile(char *filename,int simulation,char *logmessage) 
553{
554#ifdef STANDART_FILE_CALL
555    off_t         nbperchild ;
556    off_t         nbtosend;
557    off_t         startpoint ;
558    off_t         nbread ;
559    off_t         numberread ;
560    off_t         nbsent ;
561    off_t        realnbtosend ;
562#else
563    off64_t     nbperchild ;
564    off64_t     nbtosend;
565    off64_t        startpoint ;
566    off64_t     nbread ;
567    off64_t     numberread ;
568    off64_t     nbsent ;
569    off64_t        realnbtosend ;
570#endif
571    my64_t    toprint64 ;
572#ifdef WITH_GZIP                       
573    uLong    buflen ;
574    uLong    bufcomplen ;
575#endif
576    int        lentosend ;
577    int     sendsock ;
578    int        retcode ;
579
580    int     *pidfree ;
581    int     *sockfree ; /* for PASV mode only */
582    int     *portnumber ;
583    int     i ;
584    int     nfds ; 
585    fd_set    selectmask ;
586    struct timeval    wait_timer;
587    int     fd ;
588
589    struct mess_compress *msg_compress ;
590    struct message *msg ;
591    int     waitedtime ;
592    /*
593    ** Check if it is a rfio transfer
594    */
595    if ( (transferoption & TROPT_RFIO) == TROPT_RFIO ) {
596#if defined(WITH_RFIO) || defined(WITH_RFIO64)
597        return bbftpd_retrtransferfile_rfio(filename,simulation,logmessage) ;
598#else
599        return 0 ;
600#endif
601    }
602    childendinerror = 0 ; /* No child so no error */
603    if ( protocolversion <= 2 ) { /* Active mode */
604      portnumber = myports ;
605        } else {
606          sockfree = mysockets ;
607        }
608    nbperchild = filesize/requestedstreamnumber ;
609    pidfree = mychildren ;
610    nbpidchild = 0 ;
611    unlinkfile = 3 ;
612
613    /*
614    ** Now start all our children
615    */
616    for (i = 1 ; i <= requestedstreamnumber ; i++) {
617        if ( i == requestedstreamnumber ) {
618            startpoint = (i-1)*nbperchild;
619            nbtosend = filesize-(nbperchild*(requestedstreamnumber-1)) ;
620        } else {
621            startpoint = (i-1)*nbperchild;
622            nbtosend = nbperchild ;
623        }
624        if (protocolversion <= 2) { /* ACTIVE MODE */
625          /*
626          ** Now create the socket to send
627          */
628          sendsock = 0 ;
629          while (sendsock == 0 ) {
630            sendsock = bbftpd_createreceivesocket(*portnumber,logmessage) ;
631          }
632          if ( sendsock < 0 ) {
633            /*
634            ** We set childendinerror to 1 in order to prevent the father
635            ** to send a BAD message which can desynchronize the client and the
636            ** server (We need only one error message)
637            ** Bug discovered by amlutz on 2000/03/11
638            */
639            if ( childendinerror == 0 ) {
640                childendinerror = 1 ;
641                reply(MSG_BAD,logmessage) ;
642            }
643            clean_child() ;
644            return 1 ;
645          }
646          portnumber++ ;
647        } else { /* PASSIVE MODE */
648          sendsock = *sockfree ;
649          sockfree++ ;
650        }
651        /*
652        ** Set flagsighup to zero in order to be able in child
653        ** not to wait STARTCHILDTO if signal was sent before
654        ** entering select. (Seen on Linux with one child)
655        */
656        flagsighup = 0 ;
657        /*
658        ** At this stage we are ready to receive packets
659        ** So we are going to fork
660        */
661        if ( (retcode = fork()) == 0 ) {
662                    int     ns ;
663            /*
664            ** We are in child
665            */
666            /*
667            ** Pause until father send a SIGHUP in order to prevent
668            ** child to die before father has started all children
669            */
670            waitedtime = 0 ;
671            while (flagsighup == 0 && waitedtime < STARTCHILDTO) {
672                int nfds2 ;
673                                wait_timer.tv_sec  = 1 ;
674                wait_timer.tv_usec = 0 ;
675                nfds2 = sysconf(_SC_OPEN_MAX) ;
676                select(nfds2,0,0,0,&wait_timer) ;
677                waitedtime = waitedtime + 1 ;
678            }
679            bbftpd_log(BBFTPD_DEBUG,"Child %d starting",getpid()) ;
680            /*
681            ** Close all unnecessary stuff
682            */
683            close(incontrolsock) ;
684            close(outcontrolsock) ; 
685            /*
686            ** And open the file
687            */
688#ifdef STANDART_FILE_CALL
689            if ( (fd = open(filename,O_RDONLY)) < 0 ) {
690#else
691            if ( (fd = open64(filename,O_RDONLY)) < 0 ) {
692#endif
693                /*
694                ** An error on openning the local file is considered
695                ** as fatal. Maybe this need to be improved depending
696                ** on errno
697                */
698                i = errno ;
699                bbftpd_log(BBFTPD_ERR,"Error opening local file %s : %s",filename,strerror(errno)) ;
700                close(sendsock) ;
701                exit(i) ;
702            }
703#ifdef STANDART_FILE_CALL
704            if ( lseek(fd,startpoint,SEEK_SET) < 0 ) {
705#else
706            if ( lseek64(fd,startpoint,SEEK_SET) < 0 ) {
707#endif
708                i = errno ;
709                close(fd) ;
710                bbftpd_log(BBFTPD_ERR,"Error seeking file : %s",strerror(errno)) ;
711                close(sendsock) ;
712                exit(i)  ;
713            }
714            /*
715                        ** PASSIVE MODE: accept connection
716                        */
717            if ( protocolversion >= 3 ) {
718              if ( (ns = accept(sendsock,0,0) ) < 0 ) {
719                i = errno ;
720                close(fd) ;
721                bbftpd_log(BBFTPD_ERR,"Error accept socket : %s",strerror(errno)) ;
722                close(sendsock) ;
723                exit(i)  ;
724              }
725                          close(sendsock) ;
726                        } else {
727                          ns = sendsock ;
728                        }
729
730            /*
731            ** Start the sending loop
732            ** Handle the simulation mode
733            */
734            if (!simulation) {
735              nbread = 0 ;
736              while ( nbread < nbtosend ) {
737                if ( (numberread = read ( fd, readbuffer, ( (buffersizeperstream*1024) <= nbtosend - nbread) ?  (buffersizeperstream*1024) : nbtosend-nbread) ) > 0 ) {
738                    nbread = nbread+numberread ;
739                    if ( (transferoption & TROPT_GZIP ) == TROPT_GZIP ) {
740#ifdef WITH_GZIP                       
741                        /*
742                        ** In case of compression we are going to use
743                        ** a temporary buffer
744                        */
745                        bufcomplen = buffersizeperstream*1024 ;
746                        buflen = numberread ;
747                        retcode = compress((Bytef *)compbuffer,&bufcomplen,(Bytef *)readbuffer,buflen) ;
748                        if ( retcode != 0 ) {
749                            msg_compress = ( struct mess_compress *) compbuffer;
750                            /*
751                            ** Compress error, in this cas we are sending the
752                            ** date uncompressed
753                            */
754                            msg_compress->code = DATA_NOCOMPRESS ;
755                            lentosend = numberread ;
756#ifndef WORDS_BIGENDIAN
757                            msg_compress->datalen = ntohl(lentosend) ;
758#else
759                            msg_compress->datalen = lentosend ;
760#endif
761                            realnbtosend = numberread ;
762                        } else {
763                            memcpy(readbuffer,compbuffer,buffersizeperstream*1024) ;
764                            msg_compress = ( struct mess_compress *) compbuffer;
765                            msg_compress->code = DATA_COMPRESS ;
766                            lentosend = bufcomplen ;
767#ifndef WORDS_BIGENDIAN
768                            msg_compress->datalen = ntohl(lentosend) ;
769#else
770                            msg_compress->datalen = lentosend ;
771#endif
772                            realnbtosend =  bufcomplen ;
773                        }
774#else
775                        msg_compress = ( struct mess_compress *) compbuffer;
776                        /*
777                        ** Compress unavailable, in this cas we are sending the
778                        ** date uncompressed
779                        */
780                        msg_compress->code = DATA_NOCOMPRESS ;
781                        lentosend = numberread ;
782#ifndef WORDS_BIGENDIAN
783                        msg_compress->datalen = ntohl(lentosend) ;
784#else
785                        msg_compress->datalen = lentosend ;
786#endif
787                        realnbtosend = numberread ;
788#endif                       
789                        /*
790                        ** Send the header
791                        */
792                        if ( writemessage(ns,compbuffer,COMPMESSLEN,datato) < 0 ) {
793                            i = ETIMEDOUT ;
794                            bbftpd_log(BBFTPD_ERR,"Error sending header data") ;
795                            close(ns) ;
796                            exit(i) ;
797                        }
798                    } else {
799                        realnbtosend = numberread ;
800                    }
801                    /*
802                    ** Send the data
803                    */
804                    nbsent = 0 ;
805                    while ( nbsent < realnbtosend ) {
806                        lentosend = realnbtosend-nbsent ;
807                        nfds = sysconf(_SC_OPEN_MAX) ;
808                        FD_ZERO(&selectmask) ;
809                        FD_SET(ns,&selectmask) ;
810                        wait_timer.tv_sec  = datato  ;
811                        wait_timer.tv_usec = 0 ;
812                        if ( (retcode = select(nfds,0,&selectmask,0,&wait_timer) ) == -1 ) {
813                            /*
814                            ** Select error
815                            */
816                            i = errno ;
817                            bbftpd_log(BBFTPD_ERR,"Error select while sending : %s",strerror(errno)) ;
818                            close(fd) ;
819                            close(ns) ;
820                            exit(i) ;
821                        } else if ( retcode == 0 ) {
822                            bbftpd_log(BBFTPD_ERR,"Time out while selecting") ;
823                            close(fd) ;
824                            i=ETIMEDOUT ;
825                            close(ns) ;
826                            exit(i) ;
827                        } else {
828                            retcode = send(ns,&readbuffer[nbsent],lentosend,0) ;
829                            if ( retcode < 0 ) {
830                                i = errno ;
831                                bbftpd_log(BBFTPD_ERR,"Error while sending %s",strerror(i)) ;
832                                close(ns) ;
833                                exit(i) ;
834                            } else if ( retcode == 0 ) {
835                                i = ECONNRESET ;
836                                bbftpd_log(BBFTPD_ERR,"Connexion breaks") ;
837                                close(fd) ;
838                                close(ns) ;
839                                exit(i) ;
840                            } else {
841                                nbsent = nbsent+retcode ;
842                            }
843                        }
844                    }
845                } else {
846                    i = errno ;
847                    bbftpd_log(BBFTPD_ERR,"Child Error reading : %s",strerror(errno)) ;
848                    close(ns) ;
849                    close(fd) ;
850                    exit(i) ;
851                }
852              }
853              /*
854              ** All data has been sent so wait for the acknoledge
855              */
856              if ( readmessage(ns,readbuffer,MINMESSLEN,ackto) < 0 ) {
857                bbftpd_log(BBFTPD_ERR,"Error waiting ACK") ;
858                close(ns) ;
859                exit(ETIMEDOUT) ;
860              }
861              msg = (struct message *) readbuffer ;
862              if ( msg->code != MSG_ACK) {
863                bbftpd_log(BBFTPD_ERR,"Error unknown messge while waiting ACK %d",msg->code) ;
864                close(ns) ;
865                exit(1) ;
866              }
867              toprint64 = nbtosend ;
868              bbftpd_log(BBFTPD_DEBUG,"Child send %" LONG_LONG_FORMAT " bytes ; end correct ",toprint64) ;
869            }
870            close(fd) ;
871            close(ns) ;
872            exit(0) ;
873        } else {
874            /*
875            ** We are in father
876            */
877            if ( retcode == -1 ) {
878                /*
879                ** Fork failed ...
880                */
881                bbftpd_log(BBFTPD_ERR,"fork failed : %s",strerror(errno)) ;
882                sprintf(logmessage,"fork failed : %s ",strerror(errno)) ;
883                if ( childendinerror == 0 ) {
884                    childendinerror = 1 ;
885                    reply(MSG_BAD,logmessage) ;
886                }
887                clean_child() ;
888                return 1 ;
889            } else {
890                nbpidchild++ ;
891                *pidfree++ = retcode ;
892                close (sendsock) ;
893            }
894        }
895    }
896    /*
897    ** Set the state before starting children because if the file was
898    ** small the child has ended before state was setup to correct value
899    */
900    state = S_SENDING ;
901    /*
902    ** Start all children
903    */
904    pidfree = mychildren ;
905    for (i = 0 ; i<nbpidchild ; i++) {
906        if ( *pidfree != 0 ) {
907            kill(*pidfree,SIGHUP) ;
908        }
909       pidfree++ ;
910    }
911    (void) gettimeofday(&tstart, (struct timezone *)0);
912    return 0 ;
913}
Note: See TracBrowser for help on using the repository browser.