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

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

I've created a bbftpd log facility to replace syslog.
At present it allows you to log messages to a file in addition
to syslog. This should help testing on other machines.

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