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

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