📄 ftpdlib.c
字号:
(void) time( &pSlot->timeUsed ); if (pSlot->dataSock != FTPD_SOCK_FREE) { if (pSlot->status & FTPD_PASSIVE) { /* we're being passive. wait for our client to connect to us. */ addrLen = sizeof (struct sockaddr); ftpdDebugMsg ("doing accept for passive fd=%d\n", (int)pSlot->dataSock,0,0,0); if ((newSock = accept (pSlot->dataSock, (struct sockaddr *) &addr, &addrLen)) < 0) { ftpdCmdSend (pSlot, pSlot->cmdSock, 425, "Can't open data connection", 0, 0, 0, 0, 0, 0); ftpdSockFree (&pSlot->dataSock); /* we can't be passive no more */ pSlot->status &= ~FTPD_PASSIVE; return (ERROR); } if (setsockopt (newSock, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof (on)) != 0) { ftpdSockFree (&pSlot->dataSock); return (ERROR); } if (ftpdWindowSize < 0 || ftpdWindowSize > 65536) ftpdWindowSize = FTPD_WINDOW_SIZE; /* set the window size */ if (setsockopt(newSock, SOL_SOCKET, SO_SNDBUF, (char *)&ftpdWindowSize, sizeof (ftpdWindowSize))) printf("Couldn't set the Send Window to 10k\n"); if (setsockopt(newSock, SOL_SOCKET, SO_RCVBUF, (char *)&ftpdWindowSize, sizeof (ftpdWindowSize))) printf("Couldn't set the Send Window to 10k\n"); /* replace the dataSock with our new connection */ (void) close (pSlot->dataSock); pSlot->dataSock = newSock; /* N.B.: we stay passive */ if (ftpdCmdSend (pSlot, pSlot->cmdSock, 150, "Opening %s mode data connection", pSlot->status & FTPD_ASCII_TYPE ? (int) "ASCII" : (int) "BINARY", 0, 0, 0, 0, 0) == ERROR) { (void) close (pSlot->dataSock); return (ERROR); } return (OK); } else { /* reuse the old connection -- it's still useful */ if (ftpdCmdSend (pSlot, pSlot->cmdSock, 125, "Using existing data connection", 0, 0, 0, 0, 0, 0) == ERROR) { ftpdSockFree (&pSlot->dataSock); return (ERROR); } return (OK); } } else { /* Determine address for local end of connection. */ addrLen = sizeof (struct sockaddr); if (getsockname (pSlot->cmdSock, (struct sockaddr *) &addr, &addrLen) < 0) { return (ERROR); } /* Replace control port with default data port. */ addr.sin_port = htons (FTP_DATA_PORT); /* open a new data socket */ if ((pSlot->dataSock = socket (AF_INET, SOCK_STREAM, 0)) < 0) { return (ERROR); } if (setsockopt (pSlot->dataSock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on)) < 0 || bind (pSlot->dataSock, (struct sockaddr *) &addr, sizeof (addr)) < 0) { ftpdSockFree (&pSlot->dataSock); return (ERROR); } /* Set socket address to PORT command values or default. */ bcopy ( (char *)&pSlot->dataAddr, (char *)&addr, sizeof (struct sockaddr_in)); /* try until we get a connection to the client's port */ while (connect (pSlot->dataSock, (struct sockaddr *) &addr, sizeof (addr)) < 0) { if ((errno & 0xffff) == EADDRINUSE && retry < FTPD_WAIT_MAX) { taskDelay (FTPD_WAIT_INTERVAL * sysClkRateGet ()); retry += FTPD_WAIT_INTERVAL; continue; } /* timeout -- we give up */ ftpdCmdSend (pSlot, pSlot->cmdSock, 425, "Can't build data connection", 0, 0, 0, 0, 0, 0); ftpdSockFree (&pSlot->dataSock); return (ERROR); } if (setsockopt (pSlot->dataSock, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof (on)) != 0) { ftpdSockFree (&pSlot->dataSock); return (ERROR); } /* Check for window size validity */ if (ftpdWindowSize < 0 || ftpdWindowSize > 65536) ftpdWindowSize = FTPD_WINDOW_SIZE; /* set the window size */ if (setsockopt(pSlot->dataSock, SOL_SOCKET, SO_SNDBUF, (char *)&ftpdWindowSize, sizeof (ftpdWindowSize))) printf("Couldn't set the Send Window to 10k\n"); if (setsockopt(pSlot->dataSock, SOL_SOCKET, SO_RCVBUF, (char *)&ftpdWindowSize, sizeof (ftpdWindowSize))) printf("Couldn't set the Send Window to 10k\n"); if (ftpdCmdSend (pSlot, pSlot->cmdSock, 150, "Opening %s mode data connection", pSlot->status & FTPD_ASCII_TYPE ? (int) "ASCII" : (int) "BINARY", 0, 0, 0, 0, 0) == ERROR) { ftpdSockFree (&pSlot->dataSock); return (ERROR); } } return (OK); }/******************************************************************************** SEE ALSO:* ftpdDataStreamReceive which is symmetric to this function.*/LOCAL void ftpdDataStreamSend ( FTPD_SESSION_DATA *pSlot, /* pointer to our session slot */ char *fileName /* pointer to the input file stream */ ) { FAST char *pBuf; FAST int netFd; FAST int fileFd; FAST int cnt; int retval = 0; /* get a fresh connection or reuse the old one */ if (ftpdDataConnGet (pSlot) == ERROR) { dataError (pSlot); return; } if ((fileFd = open (fileName, O_RDONLY, 0)) == ERROR) { fileError (pSlot); return; } pBuf = &pSlot->buf [0]; if (pSlot->status & FTPD_ASCII_TYPE) /* ASCII representation */ { FAST FILE * inStream = NULL ; /* buffered input file stream */ FAST FILE * outStream = NULL ; /* buffered output socket stream */ FAST int ch; /* character holder */ if ((inStream = fdopen (fileFd, "r")) == NULL) { fileError (pSlot); return; } if ((outStream = fdopen (pSlot->dataSock, "w")) == NULL) { goto data_err ; } while ((ch = getc (inStream)) != EOF) { pSlot->byteCount++; /* if '\n' is encountered, we prepend a '\r' */ if (ch == '\n') { if (ferror (outStream)) goto data_err ; if (putc ('\r', outStream) == EOF) goto data_err ; taskDelay(0); } if (putc (ch, outStream) == EOF) goto data_err ; /* Abort the file transfer if a shutdown is in progress. */ if (ch == '\n' && ftpsShutdownFlag) goto data_err ; } /* flush it out */ (void) fflush (outStream); if (ferror (inStream)) { /* error in reading the file */ goto file_err ; } if (ferror (outStream)) { /* error in sending the file */ goto data_err ; } fclose (outStream); fclose (inStream); /* everything is okay */ transferOkay (pSlot); return ;data_err: dataError (pSlot); goto _err;file_err: fileError (pSlot);_err: if( outStream != NULL ) fclose (outStream); if( inStream != NULL ) fclose (inStream); return; } else if (pSlot->status & FTPD_BINARY_TYPE) /* BINARY representation */ { netFd = pSlot->dataSock; /* unbuffered block I/O between file and network */ while ((cnt = read (fileFd, pBuf, pSlot->bufSize)) > 0 && (retval = write (netFd, pBuf, cnt)) == cnt) { pSlot->byteCount += cnt; if (ftpsShutdownFlag) { /* Abort the file transfer if a shutdown is in progress. */ cnt = 1; break; } taskDelay(0); } /* cnt should be zero if the transfer ended normally */ if (cnt != 0) { if (cnt < 0) { fileError (pSlot); close( fileFd ); return; } ftpdDebugMsg ("data xfer failed: read %d bytes, wrote %d bytes\n", cnt, retval,0,0); dataError (pSlot); close( fileFd ); return; } transferOkay (pSlot); close( fileFd ); } else unImplementedType (pSlot); /* invalide representation type */ }/******************************************************************************** SEE ALSO:* ftpdDataStreamSend which is symmetric to this function.*/LOCAL STATUS ftpdDataStreamReceive ( FTPD_SESSION_DATA *pSlot, FILE *outStream ) { FAST char *pBuf; FAST int ch; FAST FILE *inStream; FAST int fileFd; FAST int netFd; FAST BOOL dontPutc; FAST int cnt; /* get a fresh data connection or reuse the old one */ if (ftpdDataConnGet (pSlot) == ERROR) goto data_err; pBuf = &pSlot->buf [0]; if (pSlot->status & FTPD_ASCII_TYPE) { /* ASCII representation */ if ((inStream = fdopen (pSlot->dataSock, "r")) == NULL) goto data_err; while ((ch = getc (inStream)) != EOF) { dontPutc = FALSE; pSlot->byteCount++; while (ch == '\r') { if (ferror (outStream)) { fclose (inStream); goto data_err ; } if ((ch = getc (inStream)) != '\n') { (void) putc ('\r', outStream); if (ch == '\0' || ch == EOF) { dontPutc = TRUE; break; } } taskDelay(0); } if (dontPutc == FALSE) (void) putc (ch, outStream); if (ch == '\n' && ftpsShutdownFlag) { fclose (inStream); goto data_err ; } } (void) fflush (outStream); if (ferror (inStream)) { fclose (inStream); goto data_err ; } if (ferror (outStream)) { fclose (inStream); goto file_err ; } fclose (inStream); transferOkay (pSlot); return OK ; } else if (pSlot->status & FTPD_BINARY_TYPE) { fileFd = fileno (outStream); netFd = pSlot->dataSock; while ((cnt = fioRead (netFd, pBuf, pSlot->bufSize)) > 0) { if (write (fileFd, pBuf, cnt) != cnt) goto file_err ; pSlot->byteCount += cnt; if (ftpsShutdownFlag) { cnt = -1; break; } taskDelay(0); } if (cnt < 0) goto data_err ; transferOkay (pSlot); return OK ; } else { unImplementedType (pSlot); return ERROR; }file_err: fileError (pSlot); return ERROR;data_err: dataError (pSlot); return ERROR; }/*********************************************************************************/LOCAL void ftpdSockFree ( int *pSock ) { if (*pSock != FTPD_SOCK_FREE) { (void) close (*pSock); *pSock = FTPD_SOCK_FREE; } }/********************************************************************************* NOTE: we're using EOS as integral part of the pattern and name.*/LOCAL BOOL ftpDirListPattern ( char * pat, char * name ) { FAST char * pPat, *pNext ; const char anyOne = '?' ; const char anyMany = '*' ; pPat = pat ; for(pNext = name ; * pNext != EOS ; pNext ++ ) { if( *pPat == anyOne ) { pPat ++ ; } else if( *pPat == anyMany ) { if ( pNext[0] == '.' ) /* '*' dont match . .. and .xxx */ return FALSE ; if ( toupper(pPat[1]) == toupper(pNext[1]) ) pPat ++ ; else if (toupper(pPat[1]) == toupper(pNext[0]) ) pPat += 2 ; else continue ; } else if( toupper(*pPat) != toupper(*pNext) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -