/*
* bbftpd/bbftpd_store_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_store_rfio.c v 2.0.0 2000/12/19 - 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
- Get serrno instead of errno
- Add debug
- Support CASTOR
v 2.1.0 2001/05/30 - Correct syslog level
- Reorganise routines as in bbftp_
v 2.1.2 2001/11/19 - Fix COS 0 case
*****************************************************************************/
#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_GZIP
#include <zlib.h>
#endif
#ifdef WITH_RFIO64
#include <shift/rfio_api.h>
#include <shift/serrno.h>
#else
#include <shift.h>
#endif
#ifdef CASTOR
#include <shift/stage_api.h>
#endif
extern int transferoption ;
extern my64_t filesize ;
extern int requestedstreamnumber ;
extern int buffersizeperstream ;
extern int maxstreams ;
extern int *myports ;
extern int *mysockets ;
extern char *readbuffer ;
extern char *compbuffer ;
extern int *mychildren ;
extern int nbpidchild ;
extern int unlinkfile ;
extern int incontrolsock ;
extern int outcontrolsock ;
extern int datato ;
extern int sendcontrolto ;
extern int state ;
extern int childendinerror ;
extern int flagsighup ;
extern int mycos ;
extern int debug ;
extern int castfd ;
extern char *castfilename ;
extern struct timeval tstart ;
extern int protocolversion ;
extern char currentusername[MAXLEN] ;
/*******************************************************************************
** bbftpd_storeclosecastfile_rfio : *
** *
** Routine to chage access time a file *
** *
** OUPUT variable : *
** logmessage : to write the error message in case of error *
** *
** GLOBAL VARIABLE USED : * *
** *
** RETURN: *
** -1 Failed *
** 0 OK *
** *
*******************************************************************************/
int bbftpd_storeclosecastfile_rfio(char *filename,char *logmessage)
{
int retcode ;
if ( castfd > 0 ) {
if ( debug ) {
fprintf(stdout,"In storeclosecastfile_rfio : rfio_close(castfd) (%d)\n",castfd) ;
}
if ( ( retcode = rfio_close(castfd) ) < 0 ){
sprintf(logmessage,"Error rfio_close on %s : %s",filename,rfio_serror()) ;
castfd = -1 ;
return -1 ;
}
castfd = -1 ;
}
return 0 ;
}
/*******************************************************************************
** bbftpd_storechmod_rfio : *
** *
** Routine to chmod a file *
** *
** OUPUT variable : *
** logmessage : to write the error message in case of error *
** *
** GLOBAL VARIABLE USED : * *
** transferoption NOT MODIFIED *
** *
** RETURN: *
** -1 Failed *
** 0 OK *
** *
*******************************************************************************/
int bbftpd_storechmod_rfio(char *filename,int mode,char *logmessage)
{
int retcode ;
if ( debug ) {
fprintf(stdout,"In storechmod_rfio : rfio_chmod(filename,mode) (%s,%d)\n",filename,mode) ;
}
retcode = rfio_chmod(filename,mode) ;
if ( retcode < 0 ) {
sprintf(logmessage,"Error chmod on file %s : %s",filename,rfio_serror()) ;
return retcode ;
}
return 0 ;
}
/*******************************************************************************
** bbftpd_storerename : *
** *
** Routine to rename a file *
** *
** OUPUT variable : *
** logmessage : to write the error message in case of error *
** *
** GLOBAL VARIABLE USED : * *
** transferoption NOT MODIFIED *
** *
** RETURN: *
** -1 Failed *
** 0 OK *
** *
*******************************************************************************/
int bbftpd_storerename_rfio(char *newfilename,char *oldfilename,char *logmessage)
{
int retcode ;
if ( debug ) {
fprintf(stdout,"**In storerename_rfio : rfio_rename(newfilename,oldfilename) (%s,%s)\n",newfilename,oldfilename) ;
}
retcode = rfio_rename(newfilename,oldfilename) ;
if ( retcode < 0 ) {
sprintf(logmessage,"Error renaming %s to %s : %s",newfilename,oldfilename,rfio_serror()) ;
return retcode ;
}
return 0 ;
}
/*******************************************************************************
** bbftpd_storeunlink_rfio : *
** *
** Routine to unlink a file *
** *
** OUPUT variable : *
** logmessage : to write the error message in case of error *
** *
** GLOBAL VARIABLE USED : * *
** *
** RETURN: *
** -1 Failed *
** 0 OK *
** *
*******************************************************************************/
int bbftpd_storeunlink_rfio(char *filename)
{
#ifdef WITH_RFIO64
struct stat64 statbuf ;
if ( rfio_stat64(filename,&statbuf ) == 0) {
#else
struct stat statbuf ;
if ( rfio_stat(filename,&statbuf ) == 0 ) {
#endif
#ifdef CASTOR
/*
** We are suppose to fill the castfilename after an open
** and to call this function only when needed
*/
if ( castfd > 0 ) {
rfio_close(castfd) ;
castfd = -1 ;
}
# ifdef HAVE_STAGECLR_PATH
if ( strncmp(filename,"/castor/",8) == 0 ) {
if ( debug ) {
fprintf(stdout,"**In storeunlink_rfio : stageclr_Path(castfilename) (%s)\n",castfilename) ;
}
stageclr_Path((u_signed64) STAGE_REMOVEHSM,NULL,castfilename) ;
} else {
if ( debug ) {
fprintf(stdout,"**In storeunlink_rfio (CASTOR case) : rfio_unlink(filename) (%s)\n",filename) ;
}
rfio_unlink(filename) ;
}
# else
if ( debug ) {
fprintf(stdout,"**In storeunlink_rfio (CASTOR case) : rfio_unlink(filename) (%s)\n",filename) ;
}
rfio_unlink(filename) ;
# endif
#else
if ( debug ) {
fprintf(stdout,"**In storeunlink_rfio : rfio_unlink(filename) (%s)\n",filename) ;
}
rfio_unlink(filename) ;
#endif
}
return 0 ;
}
/*******************************************************************************
** bbftpd_storecheckoptions_rfio : *
** *
** Routine to check the options parameters *
** *
** RETURN: *
** -1 Incorrect options *
** 0 OK *
** *
*******************************************************************************/
int bbftpd_storecheckoptions_rfio(char *logmessage)
{
int tmpoptions ;
/*
** Check the compatibility with other options
*/
if ((transferoption & TROPT_ACC) == TROPT_ACC) {
/*
** RFIO has no fonction to change access and modif time
** till now to have the same behaviour in deamon and client
** do not care
*/
}
/*
** Check all known options
*/
#ifdef CASTOR
/*
** As CASTOR in unable to support a rename discard the TROPT_TMP option
*/
tmpoptions = TROPT_ACC | TROPT_MODE | TROPT_DIR | TROPT_GZIP | TROPT_RFIO | TROPT_RFIO_O ;
#else
tmpoptions = TROPT_TMP | TROPT_ACC | TROPT_MODE | TROPT_DIR | TROPT_GZIP | TROPT_RFIO | TROPT_RFIO_O ;
#endif
transferoption = transferoption & tmpoptions ;
/*
** Check the maxstreams
*/
if ( requestedstreamnumber > maxstreams ) requestedstreamnumber = maxstreams ;
return 0 ;
}
/*******************************************************************************
** bbftpd_storemkdir_rfio : *
** *
** Routine to create a bunch of directory *
** *
** INPUT variable : *
** dirname : directory to create NOT MODIFIED *
** recursif : 1 recursif NOT MODIFIED *
** 0 non recursif *
** *
** OUPUT variable : *
** logmessage : to write the error message in case of error *
** *
** TO FREE before any return : dirpath *
** *
** RETURN: *
** -1 Creation failed unrecoverable error *
** 0 OK *
** >0 Creation failed recoverable error *
** *
*******************************************************************************/
int bbftpd_storemkdir_rfio(char *dirname,char *logmessage,int recursif)
{
char *dirpath;
char *basedir ;
char *slash ;
int savederrno ;
#ifdef WITH_RFIO64
struct stat64 statbuf ;
#else
struct stat statbuf ;
#endif
int k ;
/*
** make a copy of dirname for security
*/
if ( (dirpath = (char *) malloc (strlen(dirname)+1) ) == NULL ) {
sprintf(logmessage,"Error allocating memory for dirpath : %s",strerror(errno)) ;
return 1 ;
}
strcpy (dirpath, dirname);
/*
** Strip trailing slash
*/
strip_trailing_slashes(dirpath) ;
slash = dirpath ;
if ( recursif == 1 ) {
/*
** Recursif, we are going to create all directory
*/
/*
** This is an absolut path, but look if it is a syntax like :
** host:/.....
** /.....
*/
if ( *dirpath == '/' ) {
while (*slash == '/') slash++;
} else {
/*
** find the :
*/
k = 0 ;
while (*slash != ':' && k < strlen(dirpath) ) {
slash++;
k++ ;
}
if ( k == strlen(dirpath) ) {
sprintf(logmessage,"Incorrect directory name : %s",dirpath) ;
FREE(dirpath) ;
return -1 ;
} else {
slash++ ;
slash++ ;
}
}
while (1) {
slash = (char *) strchr (slash, '/');
if ( slash == NULL ) break ;
basedir = dirpath ;
/*
** The mkdir and stat calls below appear to be reversed.
** They are not. It is important to call mkdir first and then to
** call stat (to distinguish the three cases) only if mkdir fails.
** The alternative to this approach is to `stat' each directory,
** then to call mkdir if it doesn't exist. But if some other process
** were to create the directory between the stat & mkdir, the mkdir
** would fail with EEXIST.
** We create it with mode = 777 because the umask is set by bbftpd
*/
*slash = '\0';
if ( debug ) {
fprintf(stdout,"**In storemkdir_rfio : rfio_mkdir(basedir,0777) (%s)\n",basedir) ;
}
if ( rfio_mkdir (basedir, 0777) ) {
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 ;
}
if ( debug ) {
fprintf(stdout,"**In storemkdir_rfio : rfio_stat(basedir,&statbuf) (%s)\n",basedir) ;
}
#ifdef WITH_RFIO64
if ( rfio_stat64(basedir,&statbuf ) ) {
#else
if ( rfio_stat(basedir,&statbuf ) ) {
#endif
sprintf(logmessage,"Error creation directory %s (%s)",basedir,rfio_serror()) ;
/*
** We tell the client not to retry in the following case (even in waiting
** WAITRETRYTIME the problem will not be solved) :
** EACCES : Search permission denied
** EDQUOT : No more quota
** ENOSPC : No more space
** ELOOP : To many symbolic links on path
** ENAMETOOLONG: Path argument too long
** ENOTDIR : A component in path is not a directory
** EROFS : The path prefix resides on a read-only file system.
** ENOENT : A component of the path prefix does not exist or is a null pathname.
** EEXIST : The named file already exists.
*/
if ( savederrno == EACCES ||
savederrno == EDQUOT ||
savederrno == ENOSPC ||
savederrno == ELOOP ||
savederrno == ENAMETOOLONG ||
savederrno == ENOTDIR ||
savederrno == EROFS ||
savederrno == ENOENT ||
savederrno == EEXIST ) {
FREE(dirpath) ;
return -1 ;
} else {
FREE(dirpath) ;
return 1 ;
}
} else if ( (statbuf.st_mode & S_IFDIR) != S_IFDIR) {
sprintf(logmessage,"%s exists but is not a directory",basedir) ;
FREE(dirpath) ;
return -1 ;
} else {
/*
** dirpath already exists and is a directory.
*/
}
}
*slash++ = '/';
/*
** Avoid unnecessary calls to `stat' when given
** pathnames containing multiple adjacent slashes.
*/
while (*slash == '/') slash++;
}
}
/*
** We have created all leading directories so let see the last one
*/
basedir = dirpath ;
if ( debug ) {
fprintf(stdout,"**In storemkdir_rfio : rfio_mkdir(basedir,0777) (%s)\n",basedir) ;
}
if ( rfio_mkdir (basedir, 0777) ) {
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 ;
}
if ( debug ) {
fprintf(stdout,"**In storemkdir_rfio : rfio_stat(basedir,&statbuf) (%s)\n",basedir) ;
}
#ifdef WITH_RFIO64
if ( rfio_stat64(basedir,&statbuf ) ) {
#else
if ( rfio_stat(basedir,&statbuf ) ) {
#endif
sprintf(logmessage,"Error creation directory %s (%s)",basedir,rfio_serror()) ;
/*
** We tell the client not to retry in the following case (even in waiting
** WAITRETRYTIME the problem will not be solved) :
** EACCES : Search permission denied
** EDQUOT : No more quota
** ENOSPC : No more space
** ELOOP : To many symbolic links on path
** ENAMETOOLONG: Path argument too long
** ENOTDIR : A component in path is not a directory
** EROFS : The path prefix resides on a read-only file system.
** ENOENT : A component of the path prefix does not exist or is a null pathname.
** EEXIST : The named file already exists.
*/
if ( savederrno == EACCES ||
savederrno == EDQUOT ||
savederrno == ENOSPC ||
savederrno == ELOOP ||
savederrno == ENAMETOOLONG ||
savederrno == ENOTDIR ||
savederrno == EROFS ||
savederrno == ENOENT ||
savederrno == EEXIST ) {
FREE(dirpath) ;
return -1 ;
} else {
FREE(dirpath) ;
return 1 ;
}
} else if ( (statbuf.st_mode & S_IFDIR) != S_IFDIR) {
sprintf(logmessage,"%s exists but is not a directory",basedir) ;
FREE(dirpath) ;
return -1 ;
} else {
/*
** dirpath already exists and is a directory.
*/
FREE(dirpath) ;
return 0 ;
}
}
FREE(dirpath) ;
return 0 ;
}
/*******************************************************************************
** bbftpd_storecreatefile_rfio : *
** *
** Routine to create a file *
** *
** OUTPUT variable : *
** logmessage : to write the error message in case of error *
** *
** GLOBAL VARIABLE USED : * *
** transferoption NOT MODIFIED *
** filesize NOT MODIFIED *
** *
** TO FREE before any return : filepath *
** *
** RETURN: *
** -1 Transfer failed calling has to close the connection *
** 0 OK (Does not mean the transfer is successfull *
** *
*******************************************************************************/
int bbftpd_storecreatefile_rfio(char *filename, char *logmessage)
{
char *filepath ;
int fd ;
int lastslash ;
int savederrno ;
int retcode ;
#ifdef WITH_RFIO64
off64_t toseek ;
struct stat64 statbuf ;
#else
off_t toseek ;
struct stat statbuf ;
#endif
int hpss_file = 0;
/*
** make a copy of filename for security
*/
if ( (filepath = (char *) malloc (strlen(filename)+1) ) == NULL ) {
sprintf(logmessage,"Error allocating memory for filepath : %s",strerror(errno)) ;
return 1 ;
}
strcpy (filepath, filename);
/*
** Check if the file exist
** We are going to first see if the directory exist
** and then look at the options
** and then look if the file exist
*/
lastslash = strlen(filepath) - 1 ;
while ( lastslash >= 0 && filepath[lastslash] != '/') lastslash-- ;
if ( lastslash == -1 ) {
/*
** No slash in the path, that means that we have done a chdir
** before so do not care for the directory problem
*/
} else if ( lastslash == 0 ) {
/*
** A slash in first position so we suppose the "/" directory
** exist ... nothing to do
*/
} else if ( lastslash == strlen(filepath) - 1 ) {
/*
** The filename end with a slash ..... error
*/
sprintf(logmessage,"Filename %s ends with a /",filepath) ;
FREE(filepath) ;
return -1 ;
} else {
filepath[lastslash] = '\0';
/*
** Check the existence of the directory
*/
if ( debug ) {
fprintf(stdout,"**In storecreatefile_rfio : rfio_stat(filepath,&statbuf) (%s)\n",filepath) ;
}
#ifdef WITH_RFIO64
if ( rfio_stat64(filepath,&statbuf ) ) {
#else
if ( rfio_stat(filepath,&statbuf ) ) {
#endif
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 ;
}
/*
** It may be normal to get an error if the directory
** 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
** ENOTDIR : A component in path is not a directory
*/
if ( savederrno == EACCES ||
savederrno == ELOOP ||
savederrno == ENAMETOOLONG ||
savederrno == ENOTDIR ) {
sprintf(logmessage,"Error stating directory %s : %s ",filepath,rfio_serror()) ;
FREE(filepath) ;
return -1 ;
} else if (savederrno == ENOENT) {
/*
** The directory does not exist so check for the TROPT_DIR
** option
*/
if ( (transferoption & TROPT_DIR ) != TROPT_DIR ) {
sprintf(logmessage,"Directory (%s) creation needed but TROPT_DIR not set",filepath) ;
FREE(filepath) ;
return -1 ;
} else {
if ( (retcode = bbftpd_storemkdir_rfio(filepath,logmessage,1)) != 0 ) {
FREE(filepath) ;
return retcode ;
}
filepath[lastslash] = '/';
}
} else {
sprintf(logmessage,"Error stating directory %s : %s ",filepath,rfio_serror()) ;
FREE(filepath) ;
return 1 ;
}
} else {
/*
** The directory exist, check if it is a directory
*/
if ( (statbuf.st_mode & S_IFDIR) == S_IFDIR) {
/*
** OK correct
*/
filepath[lastslash] = '/';
/*
** check if it is a hpss file
*/
if (statbuf.st_dev == 0 && statbuf.st_ino == 1) {
hpss_file = 1;
if ( debug ) {
fprintf(stdout,"**In storecreatefile_rfio : HPSS file\n") ;
}
}
} else {
sprintf(logmessage,"%s is a not a directory",filepath) ;
FREE(filepath) ;
return -1 ;
}
}
}
/*
** At this stage all directory exists so check for the file
*/
if ( debug ) {
fprintf(stdout,"**In storecreatefile_rfio : rfio_stat(filepath,&statbuf) (%s)\n",filepath) ;
}
#ifdef WITH_RFIO64
if ( rfio_stat64(filepath,&statbuf ) < 0 ) {
#else
if ( rfio_stat(filepath,&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
** 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 ;
}
if ( savederrno == EACCES ||
savederrno == ELOOP ||
savederrno == ENAMETOOLONG ||
savederrno == ENOTDIR ) {
sprintf(logmessage,"Error stating file %s : %s ",filepath,rfio_serror()) ;
FREE(filepath) ;
return -1 ;
} else if (savederrno == ENOENT) {
/*
** That is normal the file does not exist
*/
} else {
sprintf(logmessage,"Error stating file %s : %s ",filepath,rfio_serror()) ;
FREE(filepath) ;
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",filepath) ;
FREE(filepath) ;
return -1 ;
}
/*
** check if it is writable
*/
if ( (statbuf.st_mode & S_IWUSR) != S_IWUSR) {
sprintf(logmessage,"File %s is not writable",filepath) ;
FREE(filepath) ;
return -1 ;
}
/*
** In order to set correctly the user and group id we
** erase the file first excetp if it is CASTOR
*/
#ifndef CASTOR
bbftpd_storeunlink_rfio(filepath) ;
#endif
}
#ifdef CASTOR
/*
** Do nothing except if the file length is null
*/
if ( filesize == 0 ) {
#ifdef WITH_RFIO64
if ((fd = rfio_open64(filepath,O_WRONLY|O_CREAT|O_TRUNC,0666)) < 0 ) {
#else
if ((fd = rfio_open(filepath,O_WRONLY|O_CREAT|O_TRUNC,0666)) < 0 ) {
#endif
/*
** Depending on errno we are going to tell the client to
** retry or not
*/
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 creation file %s : %s ",filepath,rfio_serror()) ;
/*
** We tell the client not to retry in the following case (even in waiting
** WAITRETRYTIME the problem will not be solved) :
** EACCES : Search permission denied
** EDQUOT : No more quota
** ENOSPC : No more space
** ELOOP : To many symbolic links on path
** ENAMETOOLONG: Path argument too long
** ENOTDIR : A component in path is not a directory
*/
if ( savederrno == EACCES ||
savederrno == EDQUOT ||
savederrno == ENOSPC ||
savederrno == ELOOP ||
savederrno == ENAMETOOLONG ||
savederrno == ENOTDIR ) {
FREE(filepath) ;
return -1 ;
} else {
FREE(filepath) ;
return 1 ;
}
}
if ( debug ) {
fprintf(stdout,"**In storecreatefile_rfio : rfio_close(fd) (%d)\n",fd) ;
}
rfio_close(fd) ;
FREE(filepath) ;
return 0 ;
} else {
if ( debug ) {
fprintf(stdout,"**In storecreatefile_rfio : I do nothing with Castor (%s)\n",filepath) ;
}
FREE(filepath) ;
return 0 ;
}
#else
/*
** We create the file
*/
if ( debug ) {
fprintf(stdout,"**In storecreatefile_rfio : rfio_open(filepath) (%s)\n",filepath) ;
}
#ifdef WITH_RFIO64
if ((fd = rfio_open64(filepath,O_WRONLY|O_CREAT|O_TRUNC,0666)) < 0 ) {
#else
if ((fd = rfio_open(filepath,O_WRONLY|O_CREAT|O_TRUNC,0666)) < 0 ) {
#endif
/*
** Depending on errno we are going to tell the client to
** retry or not
*/
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 creation file %s : %s ",filepath,rfio_serror()) ;
/*
** We tell the client not to retry in the following case (even in waiting
** WAITRETRYTIME the problem will not be solved) :
** EACCES : Search permission denied
** EDQUOT : No more quota
** ENOSPC : No more space
** ELOOP : To many symbolic links on path
** ENAMETOOLONG: Path argument too long
** ENOTDIR : A component in path is not a directory
*/
if ( savederrno == EACCES ||
savederrno == EDQUOT ||
savederrno == ENOSPC ||
savederrno == ELOOP ||
savederrno == ENAMETOOLONG ||
savederrno == ENOTDIR ) {
FREE(filepath) ;
return -1 ;
} else {
FREE(filepath) ;
return 1 ;
}
}
if ( mycos >= 0 && hpss_file) {
if ( debug ) {
fprintf(stdout,"**In storecreatefile_rfio : rfio_setcos(%d,%" LONG_LONG_FORMAT ",%d)\n", fd, filesize, mycos) ;
}
#ifdef WITH_RFIO64
rfio_setcos64(fd,filesize,mycos) ;
#else
rfio_setcos(fd,(int)filesize,mycos) ;
#endif
}
if ( filesize == 0 ) {
char statmessage[1024];
if ( debug ) {
fprintf(stdout,"**In storecreatefile_rfio : rfio_close(fd) (%d)\n",fd) ;
}
rfio_close(fd) ;
sprintf(statmessage,"PUT %s %s 0 0 0.0 0.0", currentusername, filepath);
syslog(BBFTPD_NOTICE,statmessage);
FREE(filepath) ;
return 0 ;
}
/*
** Lseek to set it to the correct size
** We use toseek because filesize is of type my64t and
** call to lseek can be done with off_t which may be
** of length 64 bits or 32 bits
*/
/* toseek = filesize-1 ;
* if ( debug ) {
* fprintf(stdout,"**In storecreatefile_rfio : rfio_lseek(fd,toseek,SEEK_SET) (%d,%d)\n",fd,toseek) ;
* }
* if ( rfio_lseek(fd,toseek,SEEK_SET) < 0 ) {
* sprintf(logmessage,"Error seeking file %s : %s ",filepath,rfio_serror()) ;
* if ( debug ) {
* fprintf(stdout,"**In storecreatefile_rfio : rfio_close(fd) (%d)\n",fd) ;
* }
* rfio_close(fd) ;
* bbftpd_storeunlink_rfio(filepath) ;
* free(filepath) ;
* return 1 ;
* }
*/
/*
** Write one byte
*/
/* if ( debug ) {
* fprintf(stdout,"**In storecreatefile_rfio : rfio_write(fd,) (%d)\n",fd) ;
* }
* if ( rfio_write(fd,"\0",1) != 1) {
* 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 writing file %s : %s ",filepath,rfio_serror()) ;
* if ( debug ) {
* fprintf(stdout,"**In storecreatefile_rfio : rfio_close(fd) (%d)\n",fd) ;
* }
* rfio_close(fd) ;
* bbftpd_storeunlink_rfio(filepath) ;
*/
/*
** We tell the client not to retry in the following case (even in waiting
** WAITRETRYTIME the problem will not be solved) :
** EDQUOT : No more quota
** ENOSPC : No space on device
*/
/* if ( savederrno == EDQUOT ||
* savederrno == ENOSPC ) {
* free(filepath) ;
* return -1 ;
* } else {
* free(filepath) ;
* return 1 ;
* }
* }
*/
/*
** And close the file
*/
if ( debug ) {
fprintf(stdout,"**In storecreatefile_rfio : rfio_close(fd) (%d)\n",fd) ;
}
if ( rfio_close(fd) < 0 ) {
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 closing file %s : %s ",filepath,rfio_serror()) ;
bbftpd_storeunlink_rfio(filepath) ;
if ( savederrno == ENOSPC ) {
FREE(filepath) ;
return -1 ;
} else {
FREE(filepath) ;
return 1 ;
}
}
FREE(filepath) ;
return 0 ;
#endif
}
/*******************************************************************************
** bbftpd_storetransferfile_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_storetransferfile_rfio(char *filename,int simulation,char *logmessage)
{
#ifdef WITH_RFIO64
off64_t nbperchild ;
off64_t nbtoget;
off64_t startpoint ;
off64_t nbget ;
off64_t toseek ;
struct stat64 statbuf ;
#else
off_t nbperchild ;
off_t nbtoget;
off_t startpoint ;
off_t nbget ;
off_t toseek ;
struct stat statbuf ;
#endif
#ifdef WITH_GZIP
uLong buflen ;
uLong bufcomplen ;
#endif
int lentowrite;
int lenwrited;
int datatoreceive;
int dataonone;
int *pidfree ;
int *sockfree ; /* for PASV mode only */
int *portnumber ;
int i ;
int recsock ;
int retcode ;
int compressionon ;
int nfds ;
fd_set selectmask ;
struct timeval wait_timer;
int fd ;
my64_t toprint64 ;
struct mess_compress *msg_compress ;
struct message *msg ;
int waitedtime ;
/*
** Set castfd to -1 to differentiate case
*/
castfd = -1 ;
if ( protocolversion <= 2 ) { /* Active mode */
portnumber = myports ;
} else {
sockfree = mysockets ;
}
nbperchild = filesize/requestedstreamnumber ;
pidfree = mychildren ;
nbpidchild = 0 ;
/*
** unlike is set to one in case of death of a children by a kill -9
** In this case the child is unable to unlink the file so that
** has to be done by the father
*/
childendinerror = 0 ; /* No child so no error */
#ifdef CASTOR
/*
** CASTOR has a very strange behaviour, you cannot open twice the
** same file with the castor name in write mode !!!. So if the
** name starts by /castor the father is going to open the file
** in write mode, look at the real file name and children will
** use this real file name. The close will be done by the
** father
** CARE HAS TO BE TAKEN FOR THIS CLOSE BECAUSE THIS MAY LEAD
** TO OPEN DESCRIPTOR IN FATHER
*/
if ( debug ) {
fprintf(stdout,"**In bbftpd_storetransferfile_rfio : rfio_open(filename) (%s)\n",filename) ;
}
#ifdef WITH_RFIO64
if ((castfd = rfio_open64(filename,O_WRONLY|O_CREAT|O_TRUNC,0666)) < 0 ) {
#else
if ((castfd = rfio_open(filename,O_WRONLY|O_CREAT|O_TRUNC,0666)) < 0 ) {
#endif
/*
** Depending on errno we are going to tell the client to
** retry or not
*/
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 ;
}
sprintf(logmessage,"Error creation file %s : %s ",filename,rfio_serror()) ;
syslog(BBFTPD_ERR,"Error creation file %s : %s ",filename,rfio_serror()) ;
/*
** We tell the client not to retry in the following case (even in waiting
** WAITRETRYTIME the problem will not be solved) :
** EACCES : Search permission denied
** EDQUOT : No more quota
** ENOSPC : No more space
** ELOOP : To many symbolic links on path
** ENAMETOOLONG: Path argument too long
** ENOTDIR : A component in path is not a directory
*/
if ( i == EACCES ||
i == EDQUOT ||
i == ENOSPC ||
i == ELOOP ||
i == ENAMETOOLONG ||
i == ENOTDIR ) {
reply(MSG_BAD_NO_RETRY,logmessage) ;
return -1 ;
} else {
reply(MSG_BAD,logmessage) ;
return 1 ;
}
}
if ( mycos >= 0 ) {
#ifdef WITH_RFIO64
if ( rfio_stat64(filename,&statbuf) < 0 ) {
#else
if ( rfio_stat(filename,&statbuf) < 0 ) {
#endif
/*
** If the file does not exist that means that another
** child has detroyed it
*/
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 stating file %s : %s ",filename,rfio_serror()) ;
close(recsock) ;
exit(i) ;
}
}
if ( strncmp(filename,"/castor/",8) == 0 ) {
if ( debug ) {
fprintf(stdout,"**In storetransferile_rfio : Case of a /castor/ file\n") ;
fprintf(stdout,"**In storetransferfile_rfio : HsmIf_FindPhysicalPath(filename,&castfilename) (%s)\n",filename) ;
}
if ( rfio_HsmIf_FindPhysicalPath(filename,&castfilename) == 0 ) {
syslog(BBFTPD_ERR,"Error finding castor physical path %s : %s ",filename,rfio_serror()) ;
sprintf(logmessage,"Error finding castor physical path %s : %s ",filename,rfio_serror()) ;
if ( debug ) {
fprintf(stdout,"**In storecreatefile_rfio : rfio_close(castfd) (%s)\n",fd) ;
}
rfio_close(castfd) ;
castfd = -1 ;
/*
** Within the actual state of CASTOR I am unable to unlink the file
** if I have not the physical name
*/
reply(MSG_BAD,logmessage) ;
return 1 ;
}
} else {
strcpy(castfilename,filename) ;
}
/*
** Write one byte
*/
if ( debug ) {
fprintf(stdout,"**In storetransferfile_rfio : rfio_write(castfd,) (%d)\n",castfd) ;
}
if ( rfio_write(castfd,"\0",1) != 1) {
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 ;
}
sprintf(logmessage,"Error writing file %s : %s ",filename,rfio_serror()) ;
syslog(BBFTPD_ERR,"Error writing file %s : %s ",filename,rfio_serror()) ;
if ( debug ) {
fprintf(stdout,"**In storetransferfile_rfio : rfio_close(fd) (%d)\n",fd) ;
}
bbftpd_storeunlink_rfio(filename) ;
/*
** We tell the client not to retry in the following case (even in waiting
** WAITRETRYTIME the problem will not be solved) :
** EDQUOT : No more quota
** ENOSPC : No space on device
*/
if ( i == EDQUOT ||
i == ENOSPC ) {
reply(MSG_BAD_NO_RETRY,logmessage) ;
return -1 ;
} else {
reply(MSG_BAD,logmessage) ;
return 1 ;
}
}
/*
** We do not need to look at the PhysicalPath, that
** has already been done by storecreatefile
*/
if ( debug ) {
fprintf(stdout,"**In storetransferfile_rfio : Real castor file name : %s\n",castfilename) ;
fflush(stdout) ;
}
#endif
unlinkfile = 2 ;
for (i = 1 ; i <= requestedstreamnumber ; i++) {
if ( i == requestedstreamnumber ) {
startpoint = (i-1)*nbperchild;
nbtoget = filesize-(nbperchild*(requestedstreamnumber-1)) ;
} else {
startpoint = (i-1)*nbperchild;
nbtoget = nbperchild ;
}
if (protocolversion <= 2) { /* ACTIVE MODE */
/*
** Now create the socket to send
*/
recsock = 0 ;
while (recsock == 0 ) {
recsock = bbftpd_createreceivesocket(*portnumber,logmessage) ;
}
if ( recsock < 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 */
recsock = *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 ;
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()) ;
}
/*
** Check if file exist
*/
if ( debug ) {
#ifdef CASTOR
fprintf(stdout,"**In storetransferfile_rfio : rfio_stat(castfilename,&statbuf) (%s)\n",castfilename) ;
#else
fprintf(stdout,"**In storetransferfile_rfio : rfio_stat(filename,&statbuf) (%s)\n",filename) ;
#endif
}
#ifdef CASTOR
# ifdef WITH_RFIO64
if ( rfio_stat64(castfilename,&statbuf) < 0 ) {
# else
if ( rfio_stat(castfilename,&statbuf) < 0 ) {
# endif
#else
# ifdef WITH_RFIO64
if ( rfio_stat64(filename,&statbuf) < 0 ) {
# else
if ( rfio_stat(filename,&statbuf) < 0 ) {
# endif
#endif
/*
** If the file does not exist that means that another
** child has detroyed it
*/
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 ;
}
#ifdef CASTOR
syslog(BBFTPD_ERR,"Error stating file %s : %s ",castfilename,rfio_serror()) ;
#else
syslog(BBFTPD_ERR,"Error stating file %s : %s ",filename,rfio_serror()) ;
#endif
close(recsock) ;
exit(i) ;
}
/*
** Open and seek to position
*/
if ( debug ) {
#ifdef CASTOR
fprintf(stdout,"**In storetransferfile_rfio : rfio_open(castfilename,O_RDWR) (%s)\n",castfilename) ;
#else
fprintf(stdout,"**In storetransferfile_rfio : rfio_open(filename,O_RDWR) (%s)\n",filename) ;
#endif
}
#ifdef CASTOR
# ifdef WITH_RFIO64
if ((fd = rfio_open64(castfilename,O_RDWR)) < 0 ) {
# else
if ((fd = rfio_open(castfilename,O_RDWR)) < 0 ) {
# endif
#else
# ifdef WITH_RFIO64
if ((fd = rfio_open64(filename,O_RDWR)) < 0 ) {
# else
if ((fd = rfio_open(filename,O_RDWR)) < 0 ) {
# endif
#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 ;
}
#ifdef CASTOR
syslog(BBFTPD_ERR,"Error opening file %s : %s ",castfilename,rfio_serror()) ;
#else
syslog(BBFTPD_ERR,"Error opening file %s : %s ",filename,rfio_serror()) ;
#endif
/*
** At this point a non recoverable error is
** EDQUOT : No more quota
** ENOSPC : No more space
*/
if ( i == EDQUOT ||
i == ENOSPC ) {
close(recsock) ;
exit(255) ;
} else {
close(recsock) ;
exit(i) ;
}
}
if ( debug ) {
fprintf(stdout,"**In storetransferfile_rfio : rfio_lseek(fd,startpoint,SEEK_SET) (%d,%d)\n",fd,startpoint) ;
}
#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 ;
}
syslog(BBFTPD_ERR,"error seeking file : %s",rfio_serror()) ;
if ( debug ) {
fprintf(stdout,"**In storetransferfile_rfio : rfio_close(fd) (%s)\n",fd) ;
}
rfio_close(fd) ;
close(recsock) ;
exit(i) ;
}
if ( protocolversion >= 3 ) {
if ( (ns = accept(recsock,0,0) ) < 0 ) {
i = errno ;
rfio_close(fd) ;
syslog(BBFTPD_ERR,"Error accept socket : %s",strerror(errno)) ;
close(recsock) ;
exit(i) ;
}
close(recsock) ;
} else {
ns = recsock ;
}
/*
** start the reading loop
** Handle the simulation mode
*/
if (!simulation) {
nbget = 0 ;
while ( nbget < nbtoget) {
if ( (transferoption & TROPT_GZIP ) == TROPT_GZIP ) {
/*
** Receive the header first
*/
if (readmessage(ns,readbuffer,COMPMESSLEN,datato) < 0 ) {
syslog(BBFTPD_ERR,"Error reading compression header") ;
if ( debug ) {
fprintf(stdout,"**In storetransferfile_rfio : rfio_close(fd) (%s)\n",fd) ;
}
rfio_close(fd) ;
i = ETIMEDOUT ;
exit(i) ;
}
msg_compress = ( struct mess_compress *) readbuffer ;
#ifndef WORDS_BIGENDIAN
msg_compress->datalen = ntohl(msg_compress->datalen) ;
#endif
if ( msg_compress->code == DATA_COMPRESS) {
compressionon = 1 ;
} else {
compressionon = 0 ;
}
datatoreceive = msg_compress->datalen ;
} else {
/*
** No compression just adjust the length to receive
*/
if (buffersizeperstream*1024 <= nbtoget-nbget ) {
datatoreceive = buffersizeperstream*1024 ;
} else {
datatoreceive = nbtoget-nbget ;
}
}
/*
** Start the data collection
*/
dataonone = 0 ;
while ( dataonone < datatoreceive ) {
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,&selectmask,0,0,&wait_timer) ) == -1 ) {
/*
** Select error
*/
i = errno ;
syslog(BBFTPD_ERR,"Error select while receiving : %s",strerror(errno)) ;
if ( debug ) {
fprintf(stdout,"**In storetransferfile_rfio : rfio_close(fd) (%s)\n",fd) ;
}
rfio_close(fd) ;
close(ns) ;
exit(i) ;
} else if ( retcode == 0 ) {
syslog(BBFTPD_ERR,"Time out while receiving") ;
if ( debug ) {
fprintf(stdout,"**In storetransferfile_rfio : rfio_close(fd) (%s)\n",fd) ;
}
rfio_close(fd) ;
i=ETIMEDOUT ;
close(ns) ;
exit(i) ;
} else {
retcode = recv(ns,&readbuffer[dataonone],datatoreceive-dataonone,0) ;
if ( retcode < 0 ) {
i = errno ;
syslog(BBFTPD_ERR,"Error while receiving : %s",strerror(errno)) ;
if ( debug ) {
fprintf(stdout,"**In storetransferfile_rfio : rfio_close(fd) (%s)\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 storetransferfile_rfio : rfio_close(fd) (%s)\n",fd) ;
}
rfio_close(fd) ;
close(ns) ;
exit(i) ;
} else {
dataonone = dataonone + retcode ;
}
}
}
/*
** We have received all data needed
*/
#ifdef WITH_GZIP
if ( (transferoption & TROPT_GZIP ) == TROPT_GZIP ) {
if ( compressionon == 1 ) {
bufcomplen = buffersizeperstream*1024 ;
buflen = dataonone ;
retcode = uncompress((Bytef *) compbuffer, &bufcomplen, (Bytef *) readbuffer, buflen) ;
if ( retcode != 0 ) {
i = EILSEQ ;
syslog(BBFTPD_ERR,"Error while decompressing %d ",retcode) ;
if ( debug ) {
fprintf(stdout,"**In storetransferfile_rfio : rfio_close(fd) (%s)\n",fd) ;
}
rfio_close(fd) ;
close(ns) ;
exit(i) ;
}
memcpy(readbuffer,compbuffer,buffersizeperstream*1024) ;
lentowrite = bufcomplen ;
} else {
lentowrite = dataonone ;
}
} else {
lentowrite = dataonone ;
}
#else
lentowrite = dataonone ;
#endif
/*
** Write it to the file
*/
lenwrited = 0 ;
while ( lenwrited < lentowrite ) {
if ( debug ) {
fprintf(stdout,"**In storetransferfile_rfio : rfio_write(fd,&readbuffer[lenwrited],lentowrite-lenwrited) (%d,add,%d)\n",fd,lentowrite-lenwrited) ;
}
if ( (retcode = rfio_write(fd,&readbuffer[lenwrited],lentowrite-lenwrited)) < 0 ) {
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 writing file : %s",rfio_serror()) ;
if ( debug ) {
fprintf(stdout,"**In storetransferfile_rfio : rfio_close(fd) (%s)\n",fd) ;
}
rfio_close(fd) ;
if ( i == EDQUOT ||
i == ENOSPC ) {
close(ns) ;
exit(255) ;
} else {
close(ns) ;
exit(i) ;
}
}
lenwrited = lenwrited + retcode ;
}
nbget = nbget+lenwrited ;
}
/*
** All data have been received so send the ACK message
*/
msg = (struct message *) readbuffer ;
msg->code = MSG_ACK ;
msg->msglen = 0 ;
if ( writemessage(ns,readbuffer,MINMESSLEN,sendcontrolto) < 0 ) {
if ( debug ) {
fprintf(stdout,"**In storetransferfile_rfio : rfio_close(fd) (%s)\n",fd) ;
}
rfio_close(fd) ;
syslog(BBFTPD_ERR,"Error sending ACK ") ;
close(ns) ;
exit(ETIMEDOUT) ;
}
toprint64 = nbget ;
syslog(BBFTPD_DEBUG,"Child received %" LONG_LONG_FORMAT " bytes ; end correct ",toprint64) ;
if ( debug ) {
fprintf(stdout,"**In storetransferfile_rfio : rfio_close(fd) (%s)\n",fd) ;
}
}
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)) ;
bbftpd_storeunlink_rfio(filename) ;
sprintf(logmessage,"fork failed : %s ",strerror(errno)) ;
if ( childendinerror == 0 ) {
childendinerror = 1 ;
reply(MSG_BAD,logmessage) ;
}
clean_child() ;
return 1 ;
} else {
*pidfree++ = retcode ;
nbpidchild++ ;
close(recsock) ;
}
}
}
/*
** 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_RECEIVING ;
/*
** Start all children
*/
pidfree = mychildren ;
for (i = 0 ; i<nbpidchild ; i++) {
if ( *pidfree != 0 ) {
kill(*pidfree,SIGHUP) ;
}
pidfree++ ;
}
if (simulation) {
/*
** set unlinkfile = 4 in order to delete the file after
** the simulated transfer
*/
unlinkfile = 4 ;
}
(void) gettimeofday(&tstart, (struct timezone *)0);
return 0 ;
}
syntax highlighted by Code2HTML, v. 0.9.1