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

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

Implemented two hooks in the bbftpd source that allow
python code to be executed before and afer a fork(). This is needed
to reset python logging and will probably be usefull for other things
in the future.

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