24 #if defined(__unix__) || defined(__VMS)
39 #include <sys/types.h>
43 #include <sys/types.h>
44 #include <sys/socket.h>
45 #include <netinet/in.h>
47 #include <arpa/inet.h>
67 #define BUILDING_LIBRARY
71 #define SETSOCKOPT_OPTVAL_TYPE (const char *)
73 #define SETSOCKOPT_OPTVAL_TYPE (void *)
76 #define FTPLIB_BUFSIZ 8192
77 #define ACCEPT_TIMEOUT 10
79 #define FTPLIB_CONTROL 0
81 #define FTPLIB_WRITE 2
83 #if !defined FTPLIB_DEFMODE
84 #define FTPLIB_DEFMODE FTPLIB_PASSIVE
88 #include <android/log.h>
89 #define perror(M) __android_log_write(ANDROID_LOG_DEBUG, "perror_ftplib", M)
90 #define lllog(M) __android_log_write(ANDROID_LOG_DEBUG, "ftplib", M)
92 #define lllog(M) fprintf(stderr, M);
95 void *
mymemccpy(
void *dst,
const void *src,
int c,
size_t n)
99 const char* p_end = p + n;
103 if (ch == c || p >= p_end)
break;
106 if (ch == c || p >= p_end)
break;
109 if (ch == c || p >= p_end)
break;
112 if (ch == c || p >= p_end)
break;
116 if (p >= p_end && ch != c)
144 static char *version =
145 "ftplib Release 3.1-1 9/16/00, copyright 1996-2000 Thomas Pfau";
150 #if defined(__unix__) || defined(VMS)
151 #define net_read read
152 #define net_write write
153 #define net_close close
154 #elif defined(_WIN32)
155 #define net_read(x,y,z) recv(x,y,z,0)
156 #define net_write(x,y,z) send(x,y,z,0)
157 #define net_close closesocket
160 #if defined(NEED_MEMCCPY)
164 void *memccpy(
void *dest,
const void *src,
int c,
size_t n)
167 const unsigned char *ip=src;
168 unsigned char *op=dest;
172 if ((*op++ = *ip++) == c)
181 #if defined(NEED_STRDUP)
185 char *strdup(
const char *src)
187 int l = strlen(src) + 1;
217 rv = select(ctl->
handle+1, rfd, wfd,
NULL, &tv);
268 if (strcmp(bp,
"\r\n") == 0)
320 char *ubp = buf, *nbp;
326 for (x=0; x < len; x++)
328 if ((*ubp ==
'\n') && (lc !=
'\r'))
338 printf(
"net_write(1) returned %d, errno = %d\n", w, errno);
353 printf(
"net_write(2) returned %d, errno = %d\n", w, errno);
358 nbp[nb++] = lc = *ubp++;
364 w = (int)net_write(nData->
handle, nbp, nb);
368 printf(
"net_write(3) returned %d, errno = %d\n", w, errno);
386 perror(
"Control socket read failed");
390 fprintf(stderr,
"%s",nControl->
response);
393 strncpy(match,nControl->
response,3);
400 perror(
"Control socket read failed");
404 fprintf(stderr,
"%s",nControl->
response);
406 while (strncmp(nControl->
response,match,4));
419 WORD wVersionRequested;
422 wVersionRequested = MAKEWORD(1,1);
423 if ((err = WSAStartup(wVersionRequested,&wsadata)) != 0)
425 fprintf(stderr,
"Network failed to start: %d\n",err);
446 int sControl, stat, flags, oldflags;
447 struct sockaddr_in sin;
457 memset(&sin,0,
sizeof(sin));
458 sin.sin_family = AF_INET;
459 lhost = strdup(host);
460 pnum = strchr(lhost,
':');
463 #if defined(VMS) || defined(ANDROID)
464 sin.sin_port = htons(21);
466 if ((pse = getservbyname(
"ftp",
"tcp")) ==
NULL)
468 perror(
"getservbyname");
471 sin.sin_port = pse->s_port;
478 sin.sin_port = htons(atoi(pnum));
481 pse = getservbyname(pnum,
"tcp");
482 sin.sin_port = pse->s_port;
485 if ((sin.sin_addr.s_addr = inet_addr(lhost)) == -1)
487 if ((phe = gethostbyname(lhost)) ==
NULL)
489 perror(
"gethostbyname");
493 memcpy((
char *)&sin.sin_addr, phe->h_addr, phe->h_length);
498 sControl = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
505 if ( setsockopt(sControl,SOL_SOCKET,SO_REUSEADDR,
508 perror(
"setsockopt");
514 if (connect(sControl, (
struct sockaddr *)&sin,
sizeof(sin)) == -1)
522 flags = fcntl( sControl, F_GETFL,0);
524 fcntl( sControl, F_SETFL, O_NONBLOCK|flags);
526 stat=connect( sControl, (
struct sockaddr *)&sin,
sizeof(sin));
529 if (errno != EWOULDBLOCK && errno != EINPROGRESS)
538 FD_SET( sControl, &wr);
543 stat = select(sControl+1, 0, &wr, 0, &tv);
555 printf(
"connected\n");
558 fcntl( sControl, F_SETFL, oldflags);
561 ctrl = calloc(1,
sizeof(
netbuf));
628 nControl->
idletime.tv_sec = v / 1000;
629 nControl->
idletime.tv_usec = (v % 1000) * 1000;
633 nControl->
idlearg = (
void *) val;
658 fprintf(stderr,
"%s\n",cmd);
659 if ((strlen(cmd) + 3) >
sizeof(buf))
661 sprintf(buf,
"%s\r\n",cmd);
662 if (net_write(nControl->
handle,buf,strlen(buf)) <= 0)
679 if (((strlen(user) + 7) >
sizeof(tempbuf)) ||
680 ((strlen(pass) + 7) >
sizeof(tempbuf)))
682 sprintf(tempbuf,
"USER %s",user);
689 sprintf(tempbuf,
"PASS %s",pass);
703 struct sockaddr_in in;
705 struct linger lng = { 0, 0 };
717 sprintf(nControl->
response,
"Invalid direction %d\n", dir);
722 sprintf(nControl->
response,
"Invalid mode %c\n", mode);
729 sin.in.sin_family = AF_INET;
732 cp = strchr(nControl->
response,
'(');
736 sscanf(cp,
"%u,%u,%u,%u,%u,%u",&v[2],&v[3],&v[4],&v[5],&v[0],&v[1]);
737 sin.sa.sa_data[2] = v[2];
738 sin.sa.sa_data[3] = v[3];
739 sin.sa.sa_data[4] = v[4];
740 sin.sa.sa_data[5] = v[5];
741 sin.sa.sa_data[0] = v[0];
742 sin.sa.sa_data[1] = v[1];
746 if (getsockname(nControl->
handle, &sin.sa, &l) < 0)
748 perror(
"getsockname");
752 sData = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
758 if (setsockopt(sData,SOL_SOCKET,SO_REUSEADDR,
761 perror(
"setsockopt");
765 if (setsockopt(sData,SOL_SOCKET,SO_LINGER,
768 perror(
"setsockopt");
774 if (connect(sData, &sin.sa,
sizeof(sin.sa)) == -1)
784 if (bind(sData, &sin.sa,
sizeof(sin)) == -1)
790 if (listen(sData, 1) < 0)
796 if (getsockname(sData, &sin.sa, &l) < 0)
798 sprintf(buf,
"PORT %d,%d,%d,%d,%d,%d",
799 (
unsigned char) sin.sa.sa_data[2],
800 (
unsigned char) sin.sa.sa_data[3],
801 (
unsigned char) sin.sa.sa_data[4],
802 (
unsigned char) sin.sa.sa_data[5],
803 (
unsigned char) sin.sa.sa_data[0],
804 (
unsigned char) sin.sa.sa_data[1]);
811 ctrl = calloc(1,
sizeof(
netbuf));
850 struct sockaddr addr;
858 FD_SET(nControl->
handle, &mask);
859 FD_SET(nData->
handle, &mask);
865 if (i < nData->handle)
867 i = select(i+1, &mask,
NULL,
NULL, &tv);
870 strncpy(nControl->
response, strerror(errno),
878 strcpy(nControl->
response,
"timed out waiting for connection");
885 if (FD_ISSET(nData->
handle, &mask))
888 sData = accept(nData->
handle, &addr, &l);
898 strncpy(nControl->
response, strerror(i),
904 else if (FD_ISSET(nControl->
handle, &mask))
925 if ((path ==
NULL) &&
929 "Missing path argument for file transfer\n");
932 sprintf(buf,
"TYPE %c", mode);
954 sprintf(nControl->
response,
"Invalid open type %d\n", typ);
959 int i = (int)strlen(buf);
961 if ((strlen(path) + i) >=
sizeof(buf))
963 strcpy(&buf[i],path);
973 (*nData)->ctrl = nControl;
974 nControl->
data = *nData;
1003 i = (int)net_read(nData->
handle, buf, max);
1034 i = (int)net_write(nData->
handle, buf, len);
1066 shutdown(nData->
handle,2);
1067 net_close(nData->
handle);
1082 net_close(nData->
handle);
1098 if ((strlen(cmd) + 7) >
sizeof(buf))
1100 sprintf(buf,
"SITE %s",cmd);
1123 while ((--l) && (*s !=
' '))
1138 if ((strlen(path) + 6) >
sizeof(buf))
1140 sprintf(buf,
"MKD %s",path);
1155 if ((strlen(path) + 6) >
sizeof(buf))
1157 sprintf(buf,
"CWD %s",path);
1184 if ((strlen(path) + 6) >
sizeof(buf))
1186 sprintf(buf,
"RMD %s",path);
1204 s = strchr(nControl->
response,
'"');
1208 while ((--l) && (*s) && (*s !=
'"'))
1219 static int FtpXfer(
const char *localfile,
const char *path,
1220 netbuf *nControl,
int typ,
int mode)
1227 int writeResult = 0;
1229 if (localfile !=
NULL)
1236 local = fopen(localfile, ac);
1239 strncpy(nControl->
response, strerror(errno),
1246 if (!
FtpAccess(path, typ, mode, nControl, &nData))
1252 if ((c =
FtpWrite(dbuf, l, nData)) < l)
1255 printf(
"short write: passed %d, wrote %d\n", l, c);
1264 if (writeResult <= 0)
1266 perror(
"localstore write");
1274 if (localfile !=
NULL)
1285 GLOBALDEF
int FtpNlst(
const char *outputfile,
const char *path,
1296 GLOBALDEF
int FtpDir(
const char *outputfile,
const char *path,
netbuf *nControl)
1311 if ((strlen(path) + 7) >
sizeof(cmd))
1313 sprintf(cmd,
"TYPE %c", mode);
1316 sprintf(cmd,
"SIZE %s",path);
1321 if (sscanf(nControl->
response,
"%d %d", &resp, &sz) == 2)
1339 if ((strlen(path) + 7) >
sizeof(buf))
1341 sprintf(buf,
"MDTM %s",path);
1345 strncpy(dt, &nControl->
response[4], max);
1354 GLOBALDEF
int FtpGet(
const char *outputfile,
const char *path,
1355 char mode,
netbuf *nControl)
1365 GLOBALDEF
int FtpPut(
const char *inputfile,
const char *path,
char mode,
1380 if (((strlen(src) + 7) >
sizeof(cmd)) ||
1381 ((strlen(dst) + 7) >
sizeof(cmd)))
1383 sprintf(cmd,
"RNFR %s",src);
1386 sprintf(cmd,
"RNTO %s",dst);
1401 if ((strlen(fnm) + 7) >
sizeof(cmd))
1403 sprintf(cmd,
"DELE %s",fnm);
1419 net_close(nControl->
handle);
static int FtpOpenPort(netbuf *nControl, netbuf **nData, int mode, int dir)
GLOBALDEF int FtpCDUp(netbuf *nControl)
GLOBALDEF int FtpRead(void *buf, int max, netbuf *nData)
int(* FtpCallbackWriter)(netbuf *nControl, const void *buffer, size_t size, void *arg)
GLOBALDEF int FtpClose(netbuf *nData)
#define FTPLIB_CALLBACK_WRITER
GLOBALDEF int FtpMkdir(const char *path, netbuf *nControl)
#define FTPLIB_DIR_VERBOSE
GLOBALDEF int FtpChdir(const char *path, netbuf *nControl)
#define FTPLIB_CALLBACK_WRITERARG
GLOBALDEF int FtpSite(const char *cmd, netbuf *nControl)
FtpCallbackWriter writercb
GLOBALDEF void FtpInit(void)
GLOBALDEF int FtpConnect(const char *host, netbuf **nControl)
GLOBALDEF int FtpOptions(int opt, long val, netbuf *nControl)
GLOBALDEF int FtpLogin(const char *user, const char *pass, netbuf *nControl)
static int readline(char *buf, int max, netbuf *ctl)
GLOBALDEF void FtpQuit(netbuf *nControl)
GLOBALDEF int FtpDelete(const char *fnm, netbuf *nControl)
GLOBALDEF int FtpModDate(const char *path, char *dt, int max, netbuf *nControl)
static int readresp(char c, netbuf *nControl)
GLOBALDEF int FtpWrite(void *buf, int len, netbuf *nData)
GLOBALDEF int FtpPwd(char *path, int max, netbuf *nControl)
#define SETSOCKOPT_OPTVAL_TYPE
#define FTPLIB_FILE_WRITE
GLOBALDEF int FtpGet(const char *outputfile, const char *path, char mode, netbuf *nControl)
GLOBALDEF int ftplib_debug
static int FtpXfer(const char *localfile, const char *path, netbuf *nControl, int typ, int mode)
GLOBALDEF int FtpDir(const char *outputfile, const char *path, netbuf *nControl)
GLOBALDEF int FtpRmdir(const char *path, netbuf *nControl)
static int FtpSendCmd(const char *cmd, char expresp, netbuf *nControl)
GLOBALDEF int FtpPut(const char *inputfile, const char *path, char mode, netbuf *nControl)
static int writeline(char *buf, int len, netbuf *nData)
GLOBALDEF int FtpAccess(const char *path, int typ, int mode, netbuf *nControl, netbuf **nData)
GLOBALDEF int FtpSize(const char *path, int *size, char mode, netbuf *nControl)
GLOBALDEF int FtpSysType(char *buf, int max, netbuf *nControl)
void * mymemccpy(void *dst, const void *src, int c, size_t n)
GLOBALDEF int FtpRename(const char *src, const char *dst, netbuf *nControl)
int(* FtpCallback)(netbuf *nControl, int xfered, void *arg)
static int socket_wait(netbuf *ctl)
#define FTPLIB_CALLBACKARG
GLOBALDEF int FtpNlst(const char *outputfile, const char *path, netbuf *nControl)
GLOBALDEF char * FtpLastResponse(netbuf *nControl)
static int FtpAcceptConnection(netbuf *nData, netbuf *nControl)
#define FTPLIB_CALLBACKBYTES