/*
* bbftpd/bbftpd_retr_rfio.c
* Copyright (C) 1999, 2000, 2001, 2002 IN2P3, CNRS
* bbftp@in2p3.fr
* http://doc.in2p3.fr/bbftp
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/****************************************************************************
bbftpd_retr_rfio.c v 2.0.0 2001/02/22 - Routines creation
v 2.0.1 2001/04/17 - Realy wait STARTCHILDTO
- Correct indentation
- Port to IRIX
v 2.0.2 2001/05/04 - Correct include for RFIO
- Add debug
- Get serrno instead of errno
v 2.1.0 2001/05/30 - Correct syslog level
- Reorganise routines as in bbftp_
*****************************************************************************/
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <signal.h>
#include <syslog.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <utime.h>
#include <bbftpd.h>
#include <common.h>
#include <daemon.h>
#include <daemon_proto.h>
#include <status.h>
#include <structures.h>
#ifdef WITH_RFIO64
#include <shift/rfio_api.h>
#include <shift/serrno.h>
#else
#include <shift.h>
#endif
#ifdef WITH_GZIP
#include <zlib.h>
#endif
extern int transferoption ;
extern my64_t filesize ;
extern int requestedstreamnumber ;
extern int buffersizeperstream ;
extern int maxstreams ;
extern int filemode ;
extern int *myports ;
extern char *readbuffer ;
extern char *compbuffer ;
extern int *mychildren ;
extern int *mysockets ;
extern int nbpidchild ;
extern int unlinkfile ;
extern int incontrolsock ;
extern int outcontrolsock ;
extern int ackto ;
extern int datato ;
extern int state ;
extern int childendinerror ;
extern int flagsighup ;
extern char lastaccess[9] ;
extern char lastmodif[9] ;
extern int debug ;
extern struct timeval tstart ;
extern int protocolversion ;
/*******************************************************************************
** bbftpd_retrlisdir : *
** *
** Routine to list a directory *
** *
** OUPUT variable : *
** filelist : Where to store the file list (to be freed by caller *
** filelistlen: Length of filelist buffer *
** logmessage : to write the error message in case of error *
** *
** GLOBAL VARIABLE USED : * *
** *
** RETURN: *
** -1 Unrecoverable error *
** 0 OK *
** 1 recoverable error *
** *
*******************************************************************************/
int bbftpd_retrlistdir_rfio(char *pattern,char **filelist,int *filelistlen,char *logmessage)
{
int lastslash ;
char *pointer ;
char *dirpath ;
DIR *curdir ;
struct dirent *dp ;
#ifdef WITH_RFIO64
struct stat64 statbuf;
#else
struct stat statbuf;
#endif
int lengthtosend;
int numberoffile ;
/*
** Structure to keep the filenames
*/
struct keepfile {
char *filename ;
char filechar[3] ;
struct keepfile *next ;
} ;
struct keepfile *first_item ;
struct keepfile *current_item ;
struct keepfile *used_item ;
char *filepos ;
int i ;
char *slash ;
int savederrno ;
/*
** We are going allocate memory for the directory name
** We allocate stelent(pattern) + 1 char for \0 + 3 char
** if the directory is "."
*/
if ( (dirpath = (char *) malloc ( strlen(pattern) + 1 + 3 )) == NULL ) {
sprintf(logmessage,"Error allocating memory for dirpath %s",strerror(errno)) ;
return -1 ;
}
pointer = pattern ;
slash = pattern ;
lastslash = strlen(pattern) - 1 ;
/*
** Within rfio as we have no chdir the file has to be an absolute
** path
*/
if ( *slash == '/' ) {
/*
** It is an absolute path
*/
} else {
/*
** find the :
*/
i = 0 ;
while (*slash != ':' && i < strlen(pattern) ) {
slash++;
i++ ;
}
if ( i == strlen(pattern) ) {
sprintf(logmessage,"Incorrect RFIO pattern : %s",pattern) ;
FREE(dirpath) ;
return -1 ;
}
}
while ( lastslash >= 0 && pointer[lastslash] != '/') lastslash-- ;
if ( lastslash == -1 ) {
/*
** No slash in the path, so the parre
**
*/
sprintf(logmessage,"Incorrect RFIO pattern : %s",pattern) ;
FREE(dirpath) ;
return -1 ;
} else if ( lastslash == 0 ) {
/*
** A slash in first position so we are going to open the
** / directory
*/
if ( debug ) {
fprintf(stdout,"**In list_rfio : rfio_opendir(/) \n") ;
}
if ( (curdir = rfio_opendir("/")) == NULL ) {
if ( serrno != 0 ) {
savederrno = serrno ;
} else if ( rfio_errno != 0 ) {
savederrno = rfio_errno ;
} else if ( errno != 0 ){
savederrno = errno ;
} else {
/*
** We use EBFONT in case of undescribed error
*/
savederrno = 57 ;
}
sprintf(logmessage,"rfio_opendir / failed : %s ",rfio_serror()) ;
if ( savederrno == EACCES ) {
FREE(dirpath) ;
return -1 ;
} else {
FREE(dirpath) ;
return 1 ;
}
}
strcpy(dirpath,"/") ;
pointer++ ;
} else if ( lastslash == strlen(pointer) - 1 ) {
/*
** The pattern end with a slash ..... error
*/
sprintf(logmessage,"Pattern %s ends with a /",pattern) ;
FREE(dirpath) ;
return -1 ;
} else {
pointer[lastslash] = '\0';
/*
** Srip unnecessary / at the end of dirpath and reset
** only one
*/
strcpy(dirpath,pointer) ;
strip_trailing_slashes(dirpath) ;
dirpath[strlen(dirpath)+1] = '\0';
dirpath[strlen(dirpath)] = '/';
if ( debug ) {
fprintf(stdout,"**In list_rfio : rfio_opendir(dirpath) (%s) \n",dirpath) ;
}
if ( (curdir = rfio_opendir(dirpath)) == NULL ) {
if ( serrno != 0 ) {
savederrno = serrno ;
} else if ( rfio_errno != 0 ) {
savederrno = rfio_errno ;
} else if ( errno != 0 ){
savederrno = errno ;
} else {
/*
** We use EBFONT in case of undescribed error
*/
savederrno = 57 ;
}
sprintf(logmessage,"opendir %s failed : %s ",dirpath,rfio_serror()) ;
if ( savederrno == EACCES ) {
FREE(dirpath) ;
return -1 ;
} else {
FREE(dirpath) ;
return -1 ;
}
}
for ( i = 0 ; i <= lastslash ; i++ ) pointer++ ;
}
/*
** At this stage pointer point to the pattern and curdir
** is the opened directory and dirpath contain the
** directory name
*/
/*
** As we are using the fnmatch routine we are obliged to
** first count the number of bytes we are sending.
*/
lengthtosend = 0 ;
numberoffile = 0 ;
errno = 0 ;
serrno = 0 ;
rfio_errno = 0 ;
first_item = NULL ;
if ( debug ) {
fprintf(stdout,"**In list_rfio : rfio_readdir(curdir) \n") ;
}
while ( (dp = rfio_readdir(curdir) ) != NULL) {
if ( fnmatch(pointer, dp->d_name,0) == 0) {
numberoffile++ ;
lengthtosend = lengthtosend + strlen(dirpath) + strlen(dp->d_name) + 1 + 3 ;
if ( ( current_item = (struct keepfile *) malloc( sizeof(struct keepfile)) ) == NULL ) {
sprintf(logmessage,"Error getting memory for structure : %s",strerror(errno)) ;
if ( debug ) {
fprintf(stdout,"**In list_rfio : rfio_closedir(curdir) \n") ;
}
current_item = first_item ;
while ( current_item != NULL ) {
free(current_item->filename) ;
used_item = current_item->next ;
free(current_item) ;
current_item = used_item ;
}
rfio_closedir(curdir) ;
FREE(dirpath) ;
return 1 ;
}
if ( ( current_item->filename = (char *) malloc( strlen(dirpath) + strlen(dp->d_name) + 1) ) == NULL ) {
sprintf(logmessage,"Error getting memory for filename : %s",strerror(errno)) ;
/*
** Clean memory
*/
FREE(current_item) ;
current_item = first_item ;
while ( current_item != NULL ) {
free(current_item->filename) ;
used_item = current_item->next ;
free(current_item) ;
current_item = used_item ;
}
if ( debug ) {
fprintf(stdout,"**In list_rfio : rfio_closedir(curdir) \n") ;
}
rfio_closedir(curdir) ;
FREE(dirpath) ;
return 1 ;
}
current_item->next = NULL ;
if ( first_item == NULL ) {
first_item = current_item ;
used_item = first_item ;
} else {
used_item = first_item ;
while ( used_item->next != NULL ) used_item = used_item->next ;
used_item->next = current_item ;
}
sprintf(current_item->filename,"%s%s",dirpath,dp->d_name) ;
if ( debug ) {
fprintf(stdout,"**In list_rfio : rfio_lstat(current_item->filename,&statbuf) (%s) \n",current_item->filename) ;
}
#ifdef WITH_RFIO64
if ( rfio_lstat64(current_item->filename,&statbuf) < 0 ) {
#else
if ( rfio_lstat(current_item->filename,&statbuf) < 0 ) {
#endif
sprintf(logmessage,"Error lstating file %s",current_item->filename) ;
current_item = first_item ;
while ( current_item != NULL ) {
free(current_item->filename) ;
used_item = current_item->next ;
free(current_item) ;
current_item = used_item ;
}
rfio_closedir(curdir) ;
FREE(dirpath) ;
return 1 ;
}
if ( (statbuf.st_mode & S_IFLNK) == S_IFLNK) {
current_item->filechar[0] = 'l' ;
if ( debug ) {
fprintf(stdout,"**In list_rfio : rfio_stat(current_item->ilename,&statbuf) (%s) \n",current_item->filename) ;
}
#ifdef WITH_RFIO64
if ( rfio_stat64(current_item->filename,&statbuf) < 0 ) {
#else
if ( rfio_stat(current_item->filename,&statbuf) < 0 ) {
#endif
/*
** That means that the link refer to an unexisting file
*/
current_item->filechar[1] = 'u' ;
} else {
if ( (statbuf.st_mode & S_IFDIR) == S_IFDIR) {
current_item->filechar[1] = 'd' ;
} else {
current_item->filechar[1] = 'f' ;
}
}
} else {
current_item->filechar[0] = ' ' ;
if ( (statbuf.st_mode & S_IFDIR) == S_IFDIR) {
current_item->filechar[1] = 'd' ;
} else {
current_item->filechar[1] = 'f' ;
}
}
current_item->filechar[2] = '\0' ;
}
errno = 0 ;
serrno = 0 ;
rfio_errno = 0 ;
}
if ( debug ) {
fprintf(stdout,"**In list_rfio : number of file found = %d \n",numberoffile) ;
}
/*
** Check errno in case of error during readdir
** for the following readir we are not going to check
** so that may be a cause of problem
*/
savederrno = 0 ;
if ( serrno != 0 ) {
savederrno = serrno ;
} else if ( rfio_errno != 0 ) {
savederrno = rfio_errno ;
} else if ( errno != 0 ){
savederrno = errno ;
}
if ( savederrno != 0 ) {
sprintf(logmessage,"Error on readdir %s (%s) ",dirpath,rfio_serror()) ;
if ( debug ) {
fprintf(stdout,"**In list_rfio : rfio_closedir(curdir) \n") ;
}
current_item = first_item ;
while ( current_item != NULL ) {
free(current_item->filename) ;
used_item = current_item->next ;
free(current_item) ;
current_item = used_item ;
}
rfio_closedir(curdir) ;
FREE(dirpath) ;
return 1 ;
}
/*
** Check if numberoffile is zero and reply now in this
** case
*/
if ( numberoffile == 0 ) {
*filelistlen = 0 ;
if ( debug ) {
fprintf(stdout,"**In list_rfio : rfio_closedir(curdir) \n") ;
}
rfio_closedir(curdir) ;
current_item = first_item ;
while ( current_item != NULL ) {
free(current_item->filename) ;
used_item = current_item->next ;
free(current_item) ;
current_item = used_item ;
}
FREE(dirpath) ;
return 0 ;
}
/*
** Now everything is ready so prepare the answer
*/
if ( ( *filelist = (char *) malloc (lengthtosend) ) == NULL ) {
sprintf(logmessage,"Error allocating memory for filelist %s",strerror(errno)) ;
if ( debug ) {
fprintf(stdout,"**In list_rfio : rfio_closedir(curdir) \n") ;
}
rfio_closedir(curdir) ;
current_item = first_item ;
while ( current_item != NULL ) {
free(current_item->filename) ;
used_item = current_item->next ;
free(current_item) ;
current_item = used_item ;
}
FREE(dirpath) ;
return -1 ;
}
current_item = first_item ;
filepos = *filelist ;
while ( current_item != NULL ) {
sprintf(filepos,"%s",current_item->filename) ;
filepos = filepos + strlen(filepos) + 1 ;
sprintf(filepos,"%s",current_item->filechar) ;
filepos = filepos + strlen(filepos) + 1 ;
current_item = current_item->next ;
}
*filelistlen = lengthtosend ;
if ( debug ) {
fprintf(stdout,"**In list_rfio : rfio_closedir(curdir) The Last\n") ;
}
rfio_closedir(curdir) ;
current_item = first_item ;
while ( current_item != NULL ) {
free(current_item->filename) ;
used_item = current_item->next ;
free(current_item) ;
current_item = used_item ;
}
FREE(dirpath) ;
return 0 ;
}
/*******************************************************************************
** bbftpd_retrcheckfile_rfio : *
** *
** Routine to check a file and set the global parameters *
** *
** OUPUT variable : *
** logmessage : to write the error message in case of error *
** *
** GLOBAL VARIABLE USED : * *
** transferoption NOT MODIFIED *
** filemode MODIFIED *
** lastaccess MODIFIED *
** lastmodif MODIFIED *
** filesize MODIFIED *
** requestedstreamnumber POSSIBLY MODIFIED *
** *
** RETURN: *
** -1 Incorrect options *
** 0 OK *
** *
*******************************************************************************/
int bbftpd_retrcheckfile_rfio(char *filename,char *logmessage)
{
#ifdef WITH_RFIO64
struct stat64 statbuf;
#else
struct stat statbuf;
#endif
int savederrno ;
int tmpnbport ;
if ( debug ) {
fprintf(stdout,"**In retrcheckfile_rfio : rfio_stat(filename,&statbuf) (%s)\n",filename) ;
}
#ifdef WITH_RFIO64
if ( rfio_stat64(filename,&statbuf) < 0 ) {
#else
if ( rfio_stat(filename,&statbuf) < 0 ) {
#endif
/*
** It may be normal to get an error if the file
** does not exist but some error code must lead
** to the interruption of the transfer:
** EACCES : Search permission denied
** ELOOP : To many symbolic links on path
** ENAMETOOLONG : Path argument too long
** ENOENT : The file does not exists
** ENOTDIR : A component in path is not a directory
*/
if ( serrno != 0 ) {
savederrno = serrno ;
} else if ( rfio_errno != 0 ) {
savederrno = rfio_errno ;
} else if ( errno != 0 ){
savederrno = errno ;
} else {
/*
** We use EBFONT in case of undescribed error
*/
savederrno = 57 ;
}
sprintf(logmessage,"Error stating file %s : %s ",filename,rfio_serror()) ;
if ( savederrno == EACCES ||
savederrno == ELOOP ||
savederrno == ENAMETOOLONG ||
savederrno == ENOENT ||
savederrno == ENOTDIR ) {
return -1 ;
} else {
return 1 ;
}
} else {
/*
** The file exists so check if it is a directory
*/
if ( (statbuf.st_mode & S_IFDIR) == S_IFDIR) {
sprintf(logmessage,"File %s is a directory",filename) ;
return -1 ;
}
}
if (S_ISREG(statbuf.st_mode)) {
filemode = statbuf.st_mode & ~S_IFREG;
} else {
filemode = statbuf.st_mode;
}
sprintf(lastaccess,"%08x",statbuf.st_atime) ;
sprintf(lastmodif,"%08x",statbuf.st_mtime) ;
lastaccess[8] = '\0' ;
lastmodif[8] = '\0' ;
filesize = statbuf.st_size ;
tmpnbport = filesize/(buffersizeperstream*1024) ;
if ( tmpnbport == 0 ) {
requestedstreamnumber = 1 ;
} else if ( tmpnbport < requestedstreamnumber ) {
requestedstreamnumber = tmpnbport ;
}
if ( requestedstreamnumber > maxstreams ) requestedstreamnumber = maxstreams ;
return 0 ;
}
/*******************************************************************************
** bbftpd_retrtransferfile_rfio : *
** *
** Routine to transfer a file *
** *
** INPUT variable : *
** filename : file to create NOT MODIFIED *
** *
** OUTPUT variable : *
** logmessage : to write the error message in case of error *
** *
** GLOBAL VARIABLE USED : * *
** *
** RETURN: *
** -1 transfer failed unrecoverable error *
** 0 Keep the connection open (does not mean that the file has been *
** successfully transfered) *
** >0 Recoverable error but calling has the cleaning to do *
** *
*******************************************************************************/
int bbftpd_retrtransferfile_rfio(char *filename,int simulation,char *logmessage)
{
#ifdef WITH_RFIO64
off64_t nbperchild ;
off64_t nbtosend;
off64_t startpoint ;
off64_t nbread ;
off64_t numberread ;
off64_t nbsent ;
off64_t toseek ;
off64_t realnbtosend ;
#else
off_t nbperchild ;
off_t nbtosend;
off_t startpoint ;
off_t nbread ;
off_t numberread ;
off_t nbsent ;
off_t toseek ;
off_t realnbtosend ;
#endif
/*struct stat statbuf ;*/
my64_t toprint64 ;
#ifdef WITH_GZIP
uLong buflen ;
uLong bufcomplen ;
#endif
int lentosend ;
int sendsock ;
int retcode ;
int *pidfree ;
int *sockfree ; /* for PASV mode only */
int *portnumber ;
int i ;
int nfds ;
fd_set selectmask ;
struct timeval wait_timer;
int fd ;
struct mess_compress *msg_compress ;
struct message *msg ;
int waitedtime ;
childendinerror = 0 ; /* No child so no error */
if ( protocolversion <= 2 ) { /* Active mode */
portnumber = myports ;
} else {
sockfree = mysockets ;
}
nbperchild = filesize/requestedstreamnumber ;
pidfree = mychildren ;
nbpidchild = 0 ;
unlinkfile = 3 ;
/*
** Now start all our children
*/
for (i = 1 ; i <= requestedstreamnumber ; i++) {
if ( i == requestedstreamnumber ) {
startpoint = (i-1)*nbperchild;
nbtosend = filesize-(nbperchild*(requestedstreamnumber-1)) ;
} else {
startpoint = (i-1)*nbperchild;
nbtosend = nbperchild ;
}
if (protocolversion <= 2) { /* ACTIVE MODE */
/*
** Now create the socket to send
*/
sendsock = 0 ;
while (sendsock == 0 ) {
sendsock = bbftpd_createreceivesocket(*portnumber,logmessage) ;
}
if ( sendsock < 0 ) {
/*
** We set childendinerror to 1 in order to prevent the father
** to send a BAD message which can desynchronize the client and the
** server (We need only one error message)
** Bug discovered by amlutz on 2000/03/11
*/
if ( childendinerror == 0 ) {
childendinerror = 1 ;
reply(MSG_BAD,logmessage) ;
}
clean_child() ;
return 1 ;
}
portnumber++ ;
} else { /* PASSIVE MODE */
sendsock = *sockfree ;
sockfree++ ;
}
/*
** Set flagsighup to zero in order to be able in child
** not to wait STARTCHILDTO if signal was sent before
** entering select. (Seen on Linux with one child)
*/
flagsighup = 0 ;
/*
** At this stage we are ready to receive packets
** So we are going to fork
*/
if ( (retcode = fork()) == 0 ) {
int ns ;
/*
** We are in child
*/
/*
** Pause until father send a SIGHUP in order to prevent
** child to die before father has started all children
*/
waitedtime = 0 ;
while (flagsighup == 0 && waitedtime < STARTCHILDTO) {
int nfds2 ;
wait_timer.tv_sec = 1 ;
wait_timer.tv_usec = 0 ;
nfds2 = sysconf(_SC_OPEN_MAX) ;
select(nfds2,0,0,0,&wait_timer) ;
waitedtime = waitedtime + 1 ;
}
syslog(BBFTPD_DEBUG,"Child %d starting",getpid()) ;
/*
** Close all unnecessary stuff
*/
close(incontrolsock) ;
close(outcontrolsock) ;
if ( debug != 0 ) {
sprintf(logmessage,"/tmp/bbftp.rfio.trace.level.%d.%d",debug,getpid()) ;
(void) freopen(logmessage,"w",stdout) ;
fprintf(stdout,"**Starting rfio trace for child number %d (pid=%d)\n",i,getpid()) ;
}
/*
** And open the file
*/
if ( debug ) {
fprintf(stdout,"**In retrtransferfile_rfio : rfio_open(filename,O_RDONLY) (%s)\n",filename) ;
}
#ifdef WITH_RFIO64
if ( (fd = rfio_open64(filename,O_RDONLY,0)) < 0 ) {
#else
if ( (fd = rfio_open(filename,O_RDONLY,0)) < 0 ) {
#endif
/*
** An error on openning the local file is considered
** as fatal. Maybe this need to be improved depending
** on errno
*/
if ( serrno != 0 ) {
i = serrno ;
} else if ( rfio_errno != 0 ) {
i = rfio_errno ;
} else if ( errno != 0 ){
i = errno ;
} else {
/*
** We use EBFONT in case of undescribed error
*/
i = 57 ;
}
syslog(BBFTPD_ERR,"Error opening local file %s : %s",filename,rfio_serror()) ;
close(sendsock) ;
exit(i) ;
}
#ifdef WITH_RFIO64
if ( rfio_lseek64(fd,startpoint,SEEK_SET) < 0 ) {
#else
if ( rfio_lseek(fd,startpoint,SEEK_SET) < 0 ) {
#endif
if ( serrno != 0 ) {
i = serrno ;
} else if ( rfio_errno != 0 ) {
i = rfio_errno ;
} else if ( errno != 0 ){
i = errno ;
} else {
/*
** We use EBFONT in case of undescribed error
*/
i = 57 ;
}
if ( debug ) {
fprintf(stdout,"**In retrtransferfile_rfio : rfio_close(fd) (%d)\n",fd) ;
}
rfio_close(fd) ;
syslog(BBFTPD_ERR,"Error seeking file : %s",rfio_serror()) ;
close(sendsock) ;
exit(i) ;
}
/*
** PASSIVE MODE: accept connection
*/
if ( protocolversion >= 3 ) {
if ( (ns = accept(sendsock,0,0) ) < 0 ) {
i = errno ;
rfio_close(fd) ;
syslog(BBFTPD_ERR,"Error accept socket : %s",strerror(errno)) ;
close(sendsock) ;
exit(i) ;
}
close(sendsock) ;
} else {
ns = sendsock ;
}
/*
** Start the sending loop
** Handle the simulation mode
*/
if (!simulation) {
nbread = 0 ;
while ( nbread < nbtosend ) {
if ( (numberread = rfio_read( fd, readbuffer, ( (buffersizeperstream*1024) <= nbtosend - nbread) ? (buffersizeperstream*1024) : (int)(nbtosend-nbread)) ) > 0 ) {
nbread = nbread+numberread ;
if ( (transferoption & TROPT_GZIP ) == TROPT_GZIP ) {
#ifdef WITH_GZIP
/*
** In case of compression we are going to use
** a temporary buffer
*/
bufcomplen = buffersizeperstream*1024 ;
buflen = numberread ;
retcode = compress((Bytef *)compbuffer,&bufcomplen,(Bytef *)readbuffer,buflen) ;
if ( retcode != 0 ) {
msg_compress = ( struct mess_compress *) compbuffer;
/*
** Compress error, in this cas we are sending the
** date uncompressed
*/
msg_compress->code = DATA_NOCOMPRESS ;
lentosend = numberread ;
#ifndef WORDS_BIGENDIAN
msg_compress->datalen = ntohl(lentosend) ;
#else
msg_compress->datalen = lentosend ;
#endif
realnbtosend = numberread ;
} else {
memcpy(readbuffer,compbuffer,buffersizeperstream*1024) ;
msg_compress = ( struct mess_compress *) compbuffer;
msg_compress->code = DATA_COMPRESS ;
lentosend = bufcomplen ;
#ifndef WORDS_BIGENDIAN
msg_compress->datalen = ntohl(lentosend) ;
#else
msg_compress->datalen = lentosend ;
#endif
realnbtosend = bufcomplen ;
}
/*
** Send the header
*/
if ( writemessage(ns,compbuffer,COMPMESSLEN,datato) < 0 ) {
i = ETIMEDOUT ;
syslog(BBFTPD_ERR,"Error sending header data") ;
close(ns) ;
if ( debug ) {
fprintf(stdout,"**In retrtransferfile_rfio : rfio_close(fd) (%d)\n",fd) ;
}
rfio_close(fd) ;
exit(i) ;
}
#else
msg_compress = ( struct mess_compress *) compbuffer;
/*
** Compress unavailable, in this cas we are sending the
** date uncompressed
*/
msg_compress->code = DATA_NOCOMPRESS ;
lentosend = numberread ;
#ifndef WORDS_BIGENDIAN
msg_compress->datalen = ntohl(lentosend) ;
#else
msg_compress->datalen = lentosend ;
#endif
realnbtosend = numberread ;
#endif
} else {
realnbtosend = numberread ;
}
/*
** Send the data
*/
nbsent = 0 ;
while ( nbsent < realnbtosend ) {
lentosend = realnbtosend-nbsent ;
nfds = sysconf(_SC_OPEN_MAX) ;
FD_ZERO(&selectmask) ;
FD_SET(ns,&selectmask) ;
wait_timer.tv_sec = datato ;
wait_timer.tv_usec = 0 ;
if ( (retcode = select(nfds,0,&selectmask,0,&wait_timer) ) == -1 ) {
/*
** Select error
*/
i = errno ;
syslog(BBFTPD_ERR,"Error select while sending : %s",strerror(errno)) ;
if ( debug ) {
fprintf(stdout,"**In retrtransferfile_rfio : rfio_close(fd) (%d)\n",fd) ;
}
rfio_close(fd) ;
close(ns) ;
exit(i) ;
} else if ( retcode == 0 ) {
syslog(BBFTPD_ERR,"Time out while sending") ;
if ( debug ) {
fprintf(stdout,"**In retrtransferfile_rfio : rfio_close(fd) (%d)\n",fd) ;
}
rfio_close(fd) ;
i=ETIMEDOUT ;
close(ns) ;
exit(i) ;
} else {
retcode = send(ns,&readbuffer[nbsent],lentosend,0) ;
if ( retcode < 0 ) {
i = errno ;
syslog(BBFTPD_ERR,"Error while sending %s",strerror(i)) ;
if ( debug ) {
fprintf(stdout,"**In retrtransferfile_rfio : rfio_close(fd) (%d)\n",fd) ;
}
rfio_close(fd) ;
close(ns) ;
exit(i) ;
} else if ( retcode == 0 ) {
i = ECONNRESET ;
syslog(BBFTPD_ERR,"Connexion breaks") ;
if ( debug ) {
fprintf(stdout,"**In retrtransferfile_rfio : rfio_close(fd) (%d)\n",fd) ;
}
rfio_close(fd) ;
close(ns) ;
exit(i) ;
} else {
nbsent = nbsent+retcode ;
}
}
}
} else {
if ( debug ) {
fprintf(stdout,"**In retrtransferfile_rfio : rfio_read(%d) returns (%d)\n",fd,numberread) ;
}
if ( serrno != 0 ) {
i = serrno ;
} else if ( rfio_errno != 0 ) {
i = rfio_errno ;
} else if ( errno != 0 ){
i = errno ;
} else {
/*
** We use EBFONT in case of undescribed error
*/
i = 57 ;
}
syslog(BBFTPD_ERR,"Child Error reading fd (%d) : %s",fd,rfio_serror()) ;
close(ns) ;
if ( debug ) {
fprintf(stdout,"**In retrtransferfile_rfio : rfio_close(fd) (%d)\n",fd) ;
}
rfio_close(fd) ;
exit(i) ;
}
}
if ( debug ) {
fprintf(stdout,"**In retrtransferfile_rfio : rfio_close(fd) (%d)\n",fd) ;
}
/*
** All data has been sent so wait for the acknoledge
*/
if ( readmessage(ns,readbuffer,MINMESSLEN,ackto) < 0 ) {
syslog(BBFTPD_ERR,"Error waiting ACK") ;
close(ns) ;
exit(ETIMEDOUT) ;
}
msg = (struct message *) readbuffer ;
if ( msg->code != MSG_ACK) {
syslog(BBFTPD_ERR,"Error unknown messge while waiting ACK %d",msg->code) ;
close(ns) ;
exit(1) ;
}
toprint64 = nbtosend ;
syslog(BBFTPD_DEBUG,"Child send %" LONG_LONG_FORMAT " bytes ; end correct ",toprint64) ;
}
rfio_close(fd) ;
close(ns) ;
exit(0) ;
} else {
/*
** We are in father
*/
if ( retcode == -1 ) {
/*
** Fork failed ...
*/
syslog(BBFTPD_ERR,"fork failed : %s",strerror(errno)) ;
sprintf(logmessage,"fork failed : %s ",strerror(errno)) ;
if ( childendinerror == 0 ) {
childendinerror = 1 ;
reply(MSG_BAD,logmessage) ;
}
clean_child() ;
return 1 ;
} else {
nbpidchild++ ;
*pidfree++ = retcode ;
close(sendsock) ;
}
}
}
/*
** Set the state before starting children because if the file was
** small the child has ended before state was setup to correct value
*/
state = S_SENDING ;
/*
** Start all children
*/
pidfree = mychildren ;
for (i = 0 ; i<nbpidchild ; i++) {
if ( *pidfree != 0 ) {
kill(*pidfree,SIGHUP) ;
}
pidfree++ ;
}
(void) gettimeofday(&tstart, (struct timezone *)0);
return 0 ;
}
syntax highlighted by Code2HTML, v. 0.9.1