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

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

Eliminated many socket related compile time warnings. These
were due to missing #include statements in the bbftp source.

MOST test cases now succeed on callisto! cross-platform stability
is looking more optimistic :-)

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