예제 #1
0
파일: io_util.c 프로젝트: as2120/ZAchieve
void
FTPSetUploadSocketBufferSize(const FTPCIPtr cip)
{
    /* If dataSocketSBufSize is non-zero, it means you
     * want to explicitly try to set the size of the
     * socket's I/O buffer.
     *
     * If it is zero, it means you want to just use the
     * TCP stack's default value, which is typically
     * between 8 and 64 kB.
     *
     * If you try to set the buffer larger than 64 kB,
     * the TCP stack should try to use RFC 1323 to
     * negotiate "TCP Large Windows" which may yield
     * significant performance gains.
     */
    if ((cip->numUploads == 0) && (cip->dataSocketSBufSize != 0))
    {
        if (cip->hasSITE_STORBUFSIZE == kCommandAvailable)
            (void) FTPCmd(cip, "SITE STORBUFSIZE %lu", (unsigned long) cip->dataSocketSBufSize);
        else if (cip->hasSITE_SBUFSIZ == kCommandAvailable)
            (void) FTPCmd(cip, "SITE SBUFSIZ %lu", (unsigned long) cip->dataSocketSBufSize);
        else if (cip->hasSITE_SBUFSZ == kCommandAvailable)
            (void) FTPCmd(cip, "SITE SBUFSZ %lu", (unsigned long) cip->dataSocketSBufSize);
        /* At least one server implemenation has RBUFSZ but not
         * SBUFSZ and instead uses RBUFSZ for both.
         */
        else if ((cip->hasSITE_SBUFSZ != kCommandAvailable) && (cip->hasSITE_RBUFSZ == kCommandAvailable))
            (void) FTPCmd(cip, "SITE RBUFSZ %lu", (unsigned long) cip->dataSocketSBufSize);
        else if (cip->hasSITE_BUFSIZE == kCommandAvailable)
            (void) FTPCmd(cip, "SITE BUFSIZE %lu", (unsigned long) cip->dataSocketSBufSize);
    }
}	/* FTPSetUploadSocketBufferSize */
예제 #2
0
int
FTPDelete(const FTPCIPtr cip, const char *const pattern, const int recurse, const int doGlob)
{
	FTPLineList fileList;
	FTPLinePtr filePtr;
	char *file;
	int onceResult, batchResult;

	if (cip == NULL)
		return (kErrBadParameter);
	if (strcmp(cip->magic, kLibraryMagic))
		return (kErrBadMagic);

	batchResult = FTPRemoteGlob(cip, &fileList, pattern, doGlob);
	if (batchResult != kNoErr)
		return (batchResult);

	for (batchResult = kNoErr, filePtr = fileList.first;
		filePtr != NULL;
		filePtr = filePtr->next)
	{
		file = filePtr->line;
		if (file == NULL) {
			batchResult = kErrBadLineList;
			cip->errNo = kErrBadLineList;
			break;
		}
		onceResult = FTPCmd(cip, "DELE %s", file);
		if (onceResult < 0) {
			batchResult = onceResult;
			break;
		}
		if (onceResult != 2) {
			if (recurse != kRecursiveYes) {
				batchResult = kErrDELEFailed;
				cip->errNo = kErrDELEFailed;
			} else {
				onceResult = FTPCmd(cip, "RMD %s", file); 	
				if (onceResult < 0) {
					batchResult = onceResult;
					break;
				}
				if (onceResult != 2) {
					onceResult = FTPRmdirRecursive(cip, file);
					if (onceResult < 0) {
						batchResult = kErrRMDFailed;
						cip->errNo = kErrRMDFailed;
					}
				}
			}
		}
	}
	DisposeLineListContents(&fileList);
	return (batchResult);
}	/* FTPDelete */
예제 #3
0
int
FTPUmask(const FTPCIPtr cip, const char *const umsk)
{
	if (cip == NULL)
		return (kErrBadParameter);
	if (strcmp(cip->magic, kLibraryMagic))
		return (kErrBadMagic);
	if ((umsk == NULL) || (umsk[0] == '\0'))
		return (kErrBadParameter);
	if (FTPCmd(cip, "SITE UMASK %s", umsk) == 2)
		return (kNoErr);
	cip->errNo = kErrUmaskFailed;
	return (kErrUmaskFailed);
}	/* FTPUmask */
예제 #4
0
int
FTPChmod(const FTPCIPtr cip, const char *const pattern, const char *const mode, const int doGlob)
{
	FTPLineList fileList;
	FTPLinePtr filePtr;
	char *file;
	int onceResult, batchResult;

	if (cip == NULL)
		return (kErrBadParameter);
	if (strcmp(cip->magic, kLibraryMagic))
		return (kErrBadMagic);

	batchResult = FTPRemoteGlob(cip, &fileList, pattern, doGlob);
	if (batchResult != kNoErr)
		return (batchResult);

	for (batchResult = kNoErr, filePtr = fileList.first;
		filePtr != NULL;
		filePtr = filePtr->next)
	{
		file = filePtr->line;
		if (file == NULL) {
			batchResult = kErrBadLineList;
			cip->errNo = kErrBadLineList;
			break;
		}
		onceResult = FTPCmd(cip, "SITE CHMOD %s %s", mode, file); 	
		if (onceResult < 0) {
			batchResult = onceResult;
			break;
		}
		if (onceResult != 2) {
			batchResult = kErrChmodFailed;
			cip->errNo = kErrChmodFailed;
		}
	}
	DisposeLineListContents(&fileList);
	return (batchResult);
}	/* FTPChmod */
예제 #5
0
/********************************************************
* function:CreateListenSocket
* purpose:create listen socket (let it choose the port) & start the socket listening
* return:   FTP_SUCCEED 成功 ,        FTP_FAIL 失败
*
********************************************************/
int CFTPClient::CreateListenSocket ( void )
{
    struct sockaddr_in  sockAddr;

    /* 分配套接口 */
    if ( ( m_hListenSocket = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
    {
        perror( "socket()" );
        return -1;
    }


    if( m_iPassive ==1 )
    { 
        //被动模式  
        char sRemote[50];
        if(FTPCmd(PASV, 0, sRemote, 50)!=0 ) return -1;
        char *pTmp;
        for(int i=0; i<3; i++)
        {
            pTmp=strchr(sRemote, ',' );
            if(pTmp==NULL)return -1;
            *pTmp='.';
        }
        pTmp=strchr(sRemote, ',' );
        if(pTmp==NULL)return -1;
        *pTmp=0;
        unsigned int iPortTmp=atoi(++pTmp);
        pTmp=strchr(pTmp, ',' );
        if(pTmp==NULL)return -1;
        iPortTmp=iPortTmp*256+atoi(++pTmp);
        unsigned long lRemote = inet_addr( sRemote );

        sockAddr.sin_family = AF_INET;
        sockAddr.sin_port = htons( iPortTmp ); 
        sockAddr.sin_addr.s_addr  = lRemote;

        if (
            connect
                (
                    m_hListenSocket,
                    reinterpret_cast < struct sockaddr * > (&sockAddr),
                    sizeof(sockAddr)
                ) < 0 )
        {
            close( m_hListenSocket );
            perror( "connect()" );
            return -1;
        }

        return 0;
        

    }

    
    /* Let the system assign a socket address                */
    sockAddr.sin_family = AF_INET;
    sockAddr.sin_port = htons( 0 ); /* htons() is just a reminder.*/
    sockAddr.sin_addr.s_addr = INADDR_ANY;
    
    /* Bind the socket       */
    if (
        bind
            (
                m_hListenSocket,
                reinterpret_cast < struct sockaddr * > (&sockAddr),
                sizeof(sockAddr)
            ) )
    {
        close( m_hListenSocket );
        perror( "bind()" );
        return -1;
    }

    int tmpint = fcntl( m_hListenSocket, F_GETFL, 0 );

    if ( fcntl( m_hListenSocket, F_SETFL, tmpint | O_NONBLOCK ) < 0 )
    {
        close( m_hListenSocket );
        perror( "fcntl" );
        return -1;
    }

    /* Listen for the FTP server connection */
    if ( listen( m_hListenSocket, 3 ) )
    {
        close( m_hListenSocket );
        perror( "listen()" );
        return -1;
    }

    /* Ask the server to connect to the port monitored by the listener socket*/
    #if defined( _AIX ) || defined( __linux__ )

    socklen_t   iLength = sizeof( sockAddr );
    #else
    int         iLength = sizeof( sockAddr );
    #endif

    /* 发送PORT命令 */
    /* Get port number */
    if (
        getsockname
            (
                m_hListenSocket,
                reinterpret_cast < struct sockaddr * > (&sockAddr),
                &iLength
            ) < 0 )
    {
        close( m_hListenSocket );
        printf( "getsockname" );
        return -1;
    }

    int iPort = sockAddr.sin_port;

    /* Get local ip address  */
    if (
        getsockname
            (
                m_hControlChannel,
                reinterpret_cast < struct sockaddr * > (&sockAddr),
                &iLength
            ) < 0 )
    {
        close( m_hListenSocket );
        printf( "getsockname" );
        return -1;
    }

    char    strCmd[128];

    //PORT h1,h2,h3,h4,p1,p2
    //where h1 is the high order 8 bits of the internet host  address.
    if ( m_IsBigOrder == 1 )
    {
        sprintf
        (
            strCmd,
            "PORT %d,%d,%d,%d,%d,%d\r\n",
            ( sockAddr.sin_addr.s_addr >> 24 ) & 0x000000ff,
            ( sockAddr.sin_addr.s_addr >> 16 ) & 0x000000ff,
            ( sockAddr.sin_addr.s_addr >> 8 ) & 0x000000ff,
            ( sockAddr.sin_addr.s_addr ) & 0x000000ff,
            iPort >> 8,
            iPort & 0xFF
        );
    }
예제 #6
0
int
FTPGetFileToMemory(
	const FTPCIPtr cip,
	const char *const file,
	char *memBuf,
	const size_t maxNumberOfBytesToWriteToMemBuf,
	size_t *const numberOfBytesWrittenToMemBuf,
	const longest_int startPoint,
	const int deleteflag
	)
{
	int tmpResult;
	volatile int result;
	int atEOF;
	longest_int expectedSize;
	size_t ntoread;
	read_return_t nread;
	size_t numberOfBytesLeftInMemBuf;
#if !defined(NO_SIGNALS)
	volatile FTPSigProc osigpipe;
	volatile FTPCIPtr vcip;
	int sj;
#endif	/* NO_SIGNALS */

	result = kNoErr;
	atEOF = 1;
	cip->usingTAR = 0;
	numberOfBytesLeftInMemBuf = maxNumberOfBytesToWriteToMemBuf;
	if (numberOfBytesWrittenToMemBuf != NULL)
		*numberOfBytesWrittenToMemBuf = 0;
		
	if ((file == NULL) || (file[0] == '\0') || (memBuf == NULL) || (maxNumberOfBytesToWriteToMemBuf == 0)) {
		return (kErrBadParameter);
	}
	
	FTPCheckForRestartModeAvailability(cip); 
	if ((startPoint != 0) && (cip->hasREST == kCommandNotAvailable)) {
		cip->errNo = kErrRESTNotAvailable;
		return (cip->errNo);
	}

	(void) FTPFileSize(cip, file, &expectedSize, kTypeBinary);
	if ((expectedSize != (longest_int) 0) && (startPoint > expectedSize)) {
		/* Don't go to all the trouble of downloading nothing. */
		if (deleteflag == kDeleteYes)
			(void) FTPDelete(cip, file, kRecursiveNo, kGlobNo);
		return (kNoErr);
	}

	if ((cip->numDownloads == 0) && (cip->dataSocketRBufSize != 0)) {
		/* If dataSocketSBufSize is non-zero, it means you
		 * want to explicitly try to set the size of the
		 * socket's I/O buffer.
		 *
		 * If it is zero, it means you want to just use the
		 * TCP stack's default value, which is typically
		 * between 8 and 64 kB.
		 *
		 * If you try to set the buffer larger than 64 kB,
		 * the TCP stack should try to use RFC 1323 to
		 * negotiate "TCP Large Windows" which may yield
		 * significant performance gains.
		 */
		if (cip->hasSITE_RETRBUFSIZE == kCommandAvailable)
			(void) FTPCmd(cip, "SITE RETRBUFSIZE %lu", (unsigned long) cip->dataSocketRBufSize);
		else if (cip->hasSITE_RBUFSIZ == kCommandAvailable)
			(void) FTPCmd(cip, "SITE RBUFSIZ %lu", (unsigned long) cip->dataSocketRBufSize);
		else if (cip->hasSITE_RBUFSZ == kCommandAvailable)
			(void) FTPCmd(cip, "SITE RBUFSZ %lu", (unsigned long) cip->dataSocketRBufSize);
		else if (cip->hasSITE_BUFSIZE == kCommandAvailable)
			(void) FTPCmd(cip, "SITE BUFSIZE %lu", (unsigned long) cip->dataSocketSBufSize);
	}

#ifdef NO_SIGNALS
#else	/* NO_SIGNALS */
	vcip = cip;
	osigpipe = (volatile FTPSigProc) signal(SIGPIPE, BrokenData);

	gGotBrokenData = 0;
	gCanBrokenDataJmp = 0;

#ifdef HAVE_SIGSETJMP
	sj = sigsetjmp(gBrokenDataJmp, 1);
#else
	sj = setjmp(gBrokenDataJmp);
#endif	/* HAVE_SIGSETJMP */

	if (sj != 0) {
		(void) signal(SIGPIPE, (FTPSigProc) osigpipe);
		FTPShutdownHost(vcip);
		vcip->errNo = kErrRemoteHostClosedConnection;
		return(vcip->errNo);
	}
	gCanBrokenDataJmp = 1;
#endif	/* NO_SIGNALS */

	tmpResult = FTPStartDataCmd(cip, kNetReading, kTypeBinary, startPoint, "RETR %s", file);

	if (tmpResult < 0) {
		result = tmpResult;
		if (result == kErrGeneric)
			result = kErrRETRFailed;
		cip->errNo = result;
#if !defined(NO_SIGNALS)
		(void) signal(SIGPIPE, (FTPSigProc) osigpipe);
#endif	/* NO_SIGNALS */
		return (result);
	}

	if ((startPoint != 0) && (cip->startPoint == 0)) {
		/* Remote could not or would not set the start offset
		 * to what we wanted.
		 */
		cip->errNo = kErrSetStartPoint;
#if !defined(NO_SIGNALS)
		(void) signal(SIGPIPE, (FTPSigProc) osigpipe);
#endif	/* NO_SIGNALS */
		return (cip->errNo);
	}

	FTPInitIOTimer(cip);
	cip->expectedSize = expectedSize;
	cip->lname = NULL;	/* could be NULL */
	cip->rname = file;
	FTPStartIOTimer(cip);

	/* Binary */
	for (;;) {
		if (! WaitForRemoteInput(cip)) {	/* could set cancelXfer */
			cip->errNo = result = kErrDataTimedOut;
			FTPLogError(cip, kDontPerror, "Remote read timed out.\n");
			break;
		}
		if (cip->cancelXfer > 0) {
			FTPAbortDataTransfer(cip);
			result = cip->errNo = kErrDataTransferAborted;
			break;
		}

		ntoread = numberOfBytesLeftInMemBuf;
		if (ntoread > cip->bufSize)
			ntoread = cip->bufSize;	/* Break it up into blocks. */
			
#ifdef NO_SIGNALS
		nread = (read_return_t) SRead(cip->dataSocket, memBuf, ntoread, (int) cip->xferTimeout, kFullBufferNotRequired|kNoFirstSelect);
		if (nread == kTimeoutErr) {
			cip->errNo = result = kErrDataTimedOut;
			FTPLogError(cip, kDontPerror, "Remote read timed out.\n");
			break;
		} else if (nread < 0) {
			if (errno == EPIPE) {
				result = cip->errNo = kErrSocketReadFailed;
				errno = EPIPE;
				FTPLogError(cip, kDoPerror, "Lost data connection to remote host.\n");
			} else if (errno == EINTR) {
				continue;
			} else {
				FTPLogError(cip, kDoPerror, "Remote read failed.\n");
				result = kErrSocketReadFailed;
				cip->errNo = kErrSocketReadFailed;
			}
			break;
		} else if (nread == 0) {
			break;
		}
#else			
		gCanBrokenDataJmp = 1;
		if (cip->xferTimeout > 0)
			(void) alarm(cip->xferTimeout);
		nread = read(cip->dataSocket, memBuf, (read_size_t) ntoread);
		if (nread < 0) {
			if ((gGotBrokenData != 0) || (errno == EPIPE)) {
				result = cip->errNo = kErrSocketReadFailed;
				errno = EPIPE;
				FTPLogError(cip, kDoPerror, "Lost data connection to remote host.\n");
			} else if (errno == EINTR) {
				continue;
			} else {
				result = cip->errNo = kErrSocketReadFailed;
				FTPLogError(cip, kDoPerror, "Remote read failed.\n");
			}
			(void) shutdown(cip->dataSocket, 2);
			break;
		} else if (nread == 0) {
			/* At EOF. */
			break;
		}
		gCanBrokenDataJmp = 0;
#endif	/* NO_SIGNALS */

		memBuf += nread;
		if (numberOfBytesWrittenToMemBuf != NULL)
			*numberOfBytesWrittenToMemBuf += (size_t) nread;
		cip->bytesTransferred += (longest_int) nread;
		FTPUpdateIOTimer(cip);
		
		if ((size_t) nread > numberOfBytesLeftInMemBuf) {
			/* assertion failure */
			result = cip->errNo = kErrBugInLibrary;
			break;
		}
		
		numberOfBytesLeftInMemBuf -= nread;
		if (numberOfBytesLeftInMemBuf == 0) {
			/* Done (but maybe not at EOF of remote file). */
			atEOF = 0;
			if ((cip->bytesTransferred + startPoint) == expectedSize)
				atEOF = 1;
			break;
		}
	}

#if !defined(NO_SIGNALS)
	if (cip->xferTimeout > 0)
		(void) alarm(0);
	gCanBrokenDataJmp = 0;
#endif	/* NO_SIGNALS */

	/* If there hasn't been an error, and you limited
	* the number of bytes, we need to abort the
	* remaining data.
	*/
	if ((result == kNoErr) && (atEOF == 0)) {
		FTPAbortDataTransfer(cip);
		tmpResult = FTPEndDataCmd(cip, 1);
		if ((tmpResult < 0) && (result == 0) && (tmpResult != kErrDataTransferFailed)) {
			result = kErrRETRFailed;
			cip->errNo = kErrRETRFailed;
		}
	} else {
		tmpResult = FTPEndDataCmd(cip, 1);
		if ((tmpResult < 0) && (result == 0)) {
			result = kErrRETRFailed;
			cip->errNo = kErrRETRFailed;
		}
	}

	FTPStopIOTimer(cip);
#if !defined(NO_SIGNALS)
	(void) signal(SIGPIPE, (FTPSigProc) osigpipe);
#endif	/* NO_SIGNALS */

	if (result == kNoErr) {
		cip->numDownloads++;

		if (deleteflag == kDeleteYes) {
			result = FTPDelete(cip, file, kRecursiveNo, kGlobNo);
		}
	}

	return (result);
}	/* FTPGetOneF */