URL
https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk
Subversion Repositories openrisc_me
Compare Revisions
- This comparison shows the changes necessary to convert path
/openrisc/trunk/rtos/ecos-2.0/packages/net/ftpclient/v2_0
- from Rev 27 to Rev 174
- ↔ Reverse comparison
Rev 27 → Rev 174
/cdl/ftpclient.cdl
0,0 → 1,109
#==================================================================== |
# |
# ftpclient.cdl |
# |
# SNMP library configuration data |
# |
# ==================================================================== |
#####ECOSGPLCOPYRIGHTBEGIN#### |
## ------------------------------------------- |
## This file is part of eCos, the Embedded Configurable Operating System. |
## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
## |
## eCos 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 or (at your option) any later version. |
## |
## eCos 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 eCos; if not, write to the Free Software Foundation, Inc., |
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
## |
## As a special exception, if other files instantiate templates or use macros |
## or inline functions from this file, or you compile this file and link it |
## with other works to produce a work based on this file, this file does not |
## by itself cause the resulting work to be covered by the GNU General Public |
## License. However the source code for this file must still be made available |
## in accordance with section (3) of the GNU General Public License. |
## |
## This exception does not invalidate any other reasons why a work based on |
## this file might be covered by the GNU General Public License. |
## |
## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
## at http://sources.redhat.com/ecos/ecos-license/ |
## ------------------------------------------- |
#####ECOSGPLCOPYRIGHTEND#### |
# ==================================================================== |
######DESCRIPTIONBEGIN#### |
# |
# Author(s): andrew.lunn@ascom.ch |
# Original data: andrew.lunn@ascom.ch |
# Contributors: |
# Date: 2001-11-04 |
# |
#####DESCRIPTIONEND#### |
# |
# ==================================================================== |
|
cdl_package CYGPKG_NET_FTPCLIENT { |
display "FTP client" |
parent CYGPKG_NET |
requires CYGPKG_IO |
requires { 0 != CYGINT_ISO_STRING_STRFUNCS } |
requires { 0 != CYGINT_ISO_STRING_MEMFUNCS } |
requires { 0 != CYGINT_ISO_STDLIB_STRCONV } |
requires { 0 != CYGINT_ISO_STDIO_FORMATTED_IO } |
requires { 0 != CYGINT_ISO_STRING_STRFUNCS } |
requires { 0 != CYGINT_ISO_ERRNO } |
requires { 0 != CYGINT_ISO_ERRNO_CODES } |
requires { 0 != CYGINT_ISO_CTYPE } |
requires CYGPKG_NET |
description " |
FTP client support. Provides ftp_put and ftp_get to put a file |
onto a remote FTP server and get a file from a remote server. |
Only binary more is supported." |
doc ref/net-ftpclient.html |
|
compile ftpclient.c |
|
cdl_component CYGPKG_NET_FTPCLIENT_OPTIONS { |
display "FTP client build options" |
flavor none |
no_define |
|
cdl_option CYGPKG_NET_FTPCLIENT_CFLAGS_ADD { |
display "Additional compiler flags" |
flavor data |
no_define |
default_value { "-D_KERNEL -D__ECOS" } |
description " |
This option modifies the set of compiler flags for |
building the FTP client package. These flags are used |
in addition to the set of global flags." |
} |
|
cdl_option CYGPKG_NET_FTPCLIENT_CFLAGS_REMOVE { |
display "Suppressed compiler flags" |
flavor data |
no_define |
default_value { "" } |
description " |
This option modifies the set of compiler flags for |
building the FTP client package. These flags are removed from |
the set of global flags if present." |
} |
} |
cdl_option CYGPKG_NET_FTPCLIENT_TESTS { |
display "FTP Client tests" |
flavor data |
no_define |
calculated { "tests/ftpclient1.c"} |
description " |
This option specifies the set of tests for the ftpclient package." |
} |
} |
|
/tests/ftpclient1.c
0,0 → 1,164
//========================================================================== |
// |
// tests/dns1.c |
// |
// Simple test of DNS client support |
// |
//========================================================================== |
//####ECOSGPLCOPYRIGHTBEGIN#### |
// ------------------------------------------- |
// This file is part of eCos, the Embedded Configurable Operating System. |
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
// |
// eCos 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 or (at your option) any later version. |
// |
// eCos 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 eCos; if not, write to the Free Software Foundation, Inc., |
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
// |
// As a special exception, if other files instantiate templates or use macros |
// or inline functions from this file, or you compile this file and link it |
// with other works to produce a work based on this file, this file does not |
// by itself cause the resulting work to be covered by the GNU General Public |
// License. However the source code for this file must still be made available |
// in accordance with section (3) of the GNU General Public License. |
// |
// This exception does not invalidate any other reasons why a work based on |
// this file might be covered by the GNU General Public License. |
// |
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
// at http://sources.redhat.com/ecos/ecos-license/ |
// ------------------------------------------- |
//####ECOSGPLCOPYRIGHTEND#### |
//========================================================================== |
//#####DESCRIPTIONBEGIN#### |
// |
// Author(s): andrew.lunn |
// Contributors: andrew.lunn, jskov |
// Date: 2001-09-18 |
// Purpose: |
// Description: Test FTPClient functions. Note that the _XXX defines below |
// control what addresses the test uses. These must be |
// changed to match the particular testing network in which |
// the test is to be run. |
// |
//####DESCRIPTIONEND#### |
// |
//========================================================================== |
|
#include <network.h> |
#include <ftpclient.h> |
#include <cyg/infra/testcase.h> |
|
#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000) |
static char stack[STACK_SIZE]; |
static cyg_thread thread_data; |
static cyg_handle_t thread_handle; |
|
#define __string(_x) #_x |
#define __xstring(_x) __string(_x) |
|
#define _FTP_SRV __xstring(172.16.19.254) // farmnet dns0 address |
|
#define FTPBUFSIZE (1024 * 64) |
char ftpbuf[FTPBUFSIZE]; |
char ftpbuf1[FTPBUFSIZE]; |
|
void |
ftp_test(cyg_addrword_t p) |
{ |
int ret; |
|
CYG_TEST_INIT(); |
|
init_all_network_interfaces(); |
|
CYG_TEST_INFO("Getting /etc/passwd from %s\n" _FTP_SRV); |
ret = ftp_get(_FTP_SRV,"anonymous","ftpclient1", |
"/etc/passwd",ftpbuf,FTPBUFSIZE, |
ftpclient_printf); |
|
if (ret > 0) { |
diag_printf("PASS:< %s bytes received>\n",ret); |
} else { |
diag_printf("FAIL:< ftp_get returned %d>\n",ret); |
} |
|
CYG_TEST_INFO("Putting passwd file back in /incoming/passwd\n"); |
ret = ftp_put(_FTP_SRV,"anonymous","ftpclient1", |
"/incoming/passwd",ftpbuf,ret, |
ftpclient_printf); |
|
if (ret > 0) { |
diag_printf("PASS:\n"); |
} else { |
diag_printf("FAIL:< ftp_get returned %d>\n",ret); |
} |
|
CYG_TEST_INFO("Reading back /incoming/passwd\n"); |
ret = ftp_get(_FTP_SRV,"anonymous","ftpclient1", |
"/incoming/passwd",ftpbuf1,FTPBUFSIZE, |
ftpclient_printf); |
|
if (ret > 0) { |
diag_printf("PASS:< %s bytes received>\n",ret); |
} else { |
diag_printf("FAIL:< ftp_get returned %d>\n",ret); |
} |
|
CYG_TEST_PASS_FAIL(!memcmp(ftpbuf,ftpbuf1,ret),"Transfer integrity"); |
|
CYG_TEST_INFO("ftp_Get'ing with a bad username\n"); |
ret = ftp_get(_FTP_SRV,"nosuchuser","ftpclient1", |
"/incoming/passwd",ftpbuf1,FTPBUFSIZE, |
ftpclient_printf); |
CYG_TEST_PASS_FAIL(ret==FTP_BADUSER,"Bad Username"); |
|
CYG_TEST_INFO("ftp_get'ting with a bad passwd\n"); |
ret = ftp_get(_FTP_SRV,"nobody","ftpclient1", |
"/incoming/passwd",ftpbuf1,FTPBUFSIZE, |
ftpclient_printf); |
CYG_TEST_PASS_FAIL(ret==FTP_BADUSER,"Bad passwd"); |
|
CYG_TEST_INFO("ftp_get'ing from a with a bad passwd\n"); |
ret = ftp_get(_FTP_SRV,"nobody","ftpclient1", |
"/incoming/passwd",ftpbuf1,FTPBUFSIZE, |
ftpclient_printf); |
CYG_TEST_PASS_FAIL(ret==FTP_BADUSER,"Bad passwd"); |
|
CYG_TEST_INFO("ftp_get'ing from a bad server\n"); |
ret = ftp_get("127.0.0.1","nobody","ftpclient1", |
"/incoming/passwd",ftpbuf1,FTPBUFSIZE, |
ftpclient_printf); |
CYG_TEST_PASS_FAIL(ret==FTP_NOSUCHHOST,"Bad server"); |
|
CYG_TEST_INFO("ftp_get'ing a file which is too big"); |
ret = ftp_get(_FTP_SRV,"nobody","ftpclient1", |
"/incoming/passwd",ftpbuf,2, |
ftpclient_printf); |
CYG_TEST_PASS_FAIL(ret==FTP_TOOBIG,"File too big"); |
} |
|
void |
cyg_start(void) |
{ |
/* Create a main thread, so we can run the scheduler and have time 'pass' */ |
cyg_thread_create(10, // Priority - just a number |
ftp_test, // entry |
0, // entry parameter |
"FTP test", // Name |
&stack[0], // Stack |
STACK_SIZE, // Size |
&thread_handle, // Handle |
&thread_data // Thread data structure |
); |
cyg_thread_resume(thread_handle); /* Start it */ |
cyg_scheduler_start(); |
} |
/include/ftpclient.h
0,0 → 1,106
#ifndef CYGONCE_NET_FTPCLIENT_FTPCLIENT_H |
#define CYGONCE_NET_FTPCLIENT_FTPCLIENT_H |
|
//========================================================================== |
// |
// ftpclient.h |
// |
// A simple FTP client |
// |
//========================================================================== |
//####ECOSGPLCOPYRIGHTBEGIN#### |
// ------------------------------------------- |
// This file is part of eCos, the Embedded Configurable Operating System. |
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
// |
// eCos 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 or (at your option) any later version. |
// |
// eCos 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 eCos; if not, write to the Free Software Foundation, Inc., |
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
// |
// As a special exception, if other files instantiate templates or use macros |
// or inline functions from this file, or you compile this file and link it |
// with other works to produce a work based on this file, this file does not |
// by itself cause the resulting work to be covered by the GNU General Public |
// License. However the source code for this file must still be made available |
// in accordance with section (3) of the GNU General Public License. |
// |
// This exception does not invalidate any other reasons why a work based on |
// this file might be covered by the GNU General Public License. |
// |
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
// at http://sources.redhat.com/ecos/ecos-license/ |
// ------------------------------------------- |
//####ECOSGPLCOPYRIGHTEND#### |
//========================================================================== |
//#####DESCRIPTIONBEGIN#### |
// |
// Author(s): andrew.lunn@ascom.ch |
// Contributors: andrew.lunn@ascom.ch |
// Date: 2001-11-4 |
// Purpose: |
// Description: |
// |
//####DESCRIPTIONEND#### |
// |
//========================================================================== |
|
typedef void (*ftp_printf_t)(unsigned error, const char *, ...); |
|
/* Use the FTP protocol to retrieve a file from a server. Only binary |
mode is supported. The filename can include a directory name. Only |
use unix style / not M$'s \. The file is placed into buf. buf has |
maximum size buf_size. If the file is bigger than this, the |
transfer fails and FTP_TOOBIG is returned. Other error codes as |
listed below can also be returned. If the transfer is succseful the |
number of bytes received is returned. */ |
|
int ftp_get(char * hostname, |
char * username, |
char * passwd, |
char * filename, |
char * buf, |
unsigned buf_size, |
ftp_printf_t ftp_printf); |
|
/*Use the FTP protocol to send a file from a server. Only binary mode |
is supported. The filename can include a directory name. Only use |
unix style / not M$'s \. The contents of buf is placed into the file |
on the server. If an error occurs one of the codes as listed below |
will be returned. If the transfer is succseful zero is returned.*/ |
|
int ftp_put(char * hostname, |
char * username, |
char * passwd, |
char * filename, |
char * buf, |
unsigned buf_size, |
ftp_printf_t ftp_printf); |
|
/*ftp_get() and ftp_put take the name of a function to call to print |
out diagnostic and error messages. This is a sample implementation |
which can be used if you don't want to implement the function |
yourself. error will be true when the message to print is an error |
message. Otherwise the message is diagnostic, eg the commands sent |
and received from the server.*/ |
|
void ftpclient_printf(unsigned error, const char *fmt, ...); |
|
/* Error codes */ |
|
#define FTP_BAD -2 /* Catch all, socket errors etc. */ |
#define FTP_NOSUCHHOST -3 /* The server does not exist. */ |
#define FTP_BADUSER -4 /* Username/Password failed */ |
#define FTP_TOOBIG -5 /* Out of buffer space or disk space */ |
#define FTP_BADFILENAME -6 /* The file does not exist */ |
|
#endif CYGONCE_NET_FTPCLIENT_FTPCLIENT |
|
/doc/ftpclient.sgml
0,0 → 1,117
<!-- {{{ Banner --> |
|
<!-- =============================================================== --> |
<!-- --> |
<!-- ftpclient.sgml --> |
<!-- --> |
<!-- eCos TCP/IP Stacks --> |
<!-- --> |
<!-- =============================================================== --> |
<!-- ####COPYRIGHTBEGIN#### --> |
<!-- --> |
<!-- =============================================================== --> |
<!-- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. --> |
<!-- This material may be distributed only subject to the terms --> |
<!-- and conditions set forth in the Open Publication License, v1.0 --> |
<!-- or later (the latest version is presently available at --> |
<!-- http://www.opencontent.org/openpub/) --> |
<!-- Distribution of the work or derivative of the work in any --> |
<!-- standard (paper) book form is prohibited unless prior --> |
<!-- permission obtained from the copyright holder --> |
<!-- =============================================================== --> |
<!-- --> |
<!-- ####COPYRIGHTEND#### --> |
<!-- =============================================================== --> |
<!-- #####DESCRIPTIONBEGIN#### --> |
<!-- --> |
<!-- ####DESCRIPTIONEND#### --> |
<!-- =============================================================== --> |
|
<!-- }}} --> |
|
<PART ID="net-ftpclient"> |
<TITLE>FTP Client for eCos TCP/IP Stack</TITLE> |
<PARTINTRO> |
<PARA> |
The ftpclient package provides an FTP (File Transfer Protocol) client |
for use with the TCP/IP stack in eCos. |
</PARA> |
</PARTINTRO> |
<CHAPTER id="net-ftpclient-features"> |
<TITLE>FTP Client Features</TITLE> |
<SECT1 id="net-ftpclient-features-api"> |
<TITLE>FTP Client API</TITLE> |
<para> |
This package implements an FTP client. The API is in include file |
<filename>install/include/ftpclient.h</filename> and it can be used thus: |
<programlisting> |
#include <network.h> |
#include <ftpclient.h> |
</programlisting> |
It looks like this: |
</para> |
<sect2 id="net-ftpclient-features-api-get"> |
<title>ftp_get</title> |
<programlisting> |
int ftp_get(char * hostname, |
char * username, |
char * passwd, |
char * filename, |
char * buf, |
unsigned buf_size, |
ftp_printf_t ftp_printf); |
</programlisting> |
<para> |
Use the FTP protocol to retrieve a file from a server. Only binary |
mode is supported. The filename can include a directory name. Only |
use unix style ‘/’ file separators, |
not ‘\’. |
The file is placed into <parameter>buf</parameter>. |
<parameter>buf</parameter> has maximum size <parameter>buf_size</parameter>. |
If the file is bigger than this, the |
transfer fails and <errorcode>FTP_TOOBIG</errorcode> is returned. |
Other error codes listed in the header can also be returned. |
If the transfer is successful the number of bytes received is returned. |
</para> |
</sect2> |
<sect2 id="net-ftpclient-features-api-put"> |
<title>ftp_put</title> |
<programlisting> |
int ftp_put(char * hostname, |
char * username, |
char * passwd, |
char * filename, |
char * buf, |
unsigned buf_size, |
ftp_printf_t ftp_printf); |
</programlisting> |
<para> |
Use the FTP protocol to send a file to a server. |
Only binary |
mode is supported. The filename can include a directory name. Only |
use unix style ‘/’ file separators, |
not ‘\’. |
The contents of <parameter>buf</parameter> are placed into the file on the |
server. If an error occurs one of the codes listed will be returned. If the |
transfer is successful zero is returned. |
</para> |
</sect2> |
<sect2 id="net-ftpclient-features-api-printf"> |
<title>ftpclient_printf</title> |
<programlisting> |
void ftpclient_printf(unsigned error, const char *fmt, ...); |
</programlisting> |
<para> |
<function>ftp_get()</function> and <function>ftp_put</function> |
take a pointer to a function to use for printing |
out diagnostic and error messages. This is a sample implementation |
which can be used if you don't want to implement the function |
yourself. |
<parameter>error</parameter> will be true when the message to print is an |
error message. Otherwise the message is diagnostic, eg. the commands sent |
and received from the server. |
</para> |
</sect2> |
</SECT1> |
</CHAPTER> |
</PART> |
/src/ftpclient.c
0,0 → 1,694
//========================================================================== |
// |
// ftpclient.c |
// |
// A simple FTP client |
// |
//========================================================================== |
//####ECOSGPLCOPYRIGHTBEGIN#### |
// ------------------------------------------- |
// This file is part of eCos, the Embedded Configurable Operating System. |
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
// Copyright (C) 2002 Andrew Lunn. |
// |
// eCos 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 or (at your option) any later version. |
// |
// eCos 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 eCos; if not, write to the Free Software Foundation, Inc., |
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
// |
// As a special exception, if other files instantiate templates or use macros |
// or inline functions from this file, or you compile this file and link it |
// with other works to produce a work based on this file, this file does not |
// by itself cause the resulting work to be covered by the GNU General Public |
// License. However the source code for this file must still be made available |
// in accordance with section (3) of the GNU General Public License. |
// |
// This exception does not invalidate any other reasons why a work based on |
// this file might be covered by the GNU General Public License. |
// |
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
// at http://sources.redhat.com/ecos/ecos-license/ |
// ------------------------------------------- |
//####ECOSGPLCOPYRIGHTEND#### |
//========================================================================== |
//#####DESCRIPTIONBEGIN#### |
// |
// Author(s): andrew.lunn@ascom.ch |
// Contributors: andrew.lunn@ascom.ch |
// Date: 2001-11-4 |
// Purpose: |
// Description: |
// |
//####DESCRIPTIONEND#### |
// |
//========================================================================== |
|
#include <pkgconf/system.h> |
|
#include <network.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <sys/socket.h> |
#include <netinet/in.h> |
#include <arpa/inet.h> |
#include <ctype.h> |
#include "ftpclient.h" |
|
/* Build one command to send to the FTP server */ |
static int |
build_cmd(char *buf, |
unsigned bufsize, |
char *cmd, |
char *arg1) |
{ |
int cnt; |
|
if (arg1) { |
cnt = snprintf(buf,bufsize,"%s %s\r\n",cmd,arg1); |
} else { |
cnt = snprintf(buf,bufsize,"%s\r\n",cmd); |
} |
|
if (cnt < bufsize) |
return 1; |
|
return 0; |
} |
|
|
/* Read one line from the server, being careful not to overrun the |
buffer. If we do reach the end of the buffer, discard the rest of |
the line. */ |
static int |
get_line(int s, char *buf, unsigned buf_size,ftp_printf_t ftp_printf) { |
|
int eol = 0; |
int cnt = 0; |
int ret; |
char c; |
|
while(!eol) { |
ret = read(s,&c,1); |
|
if (ret != 1) { |
ftp_printf(1,"read %s\n",strerror(errno)); |
return FTP_BAD; |
} |
|
if (c == '\n') { |
eol = 1; |
continue; |
} |
|
if (cnt < buf_size) { |
buf[cnt++] = c; |
} |
} |
if (cnt < buf_size) { |
buf[cnt++] = '\0'; |
} else { |
buf[buf_size -1] = '\0'; |
} |
return 0; |
} |
|
/* Read the reply from the server and return the MSB from the return |
code. This gives us a basic idea if the command failed/worked. The |
reply can be spread over multiple lines. When this happens the line |
will start with a - to indicate there is more*/ |
static int |
get_reply(int s,ftp_printf_t ftp_printf) { |
|
char buf[BUFSIZ]; |
int more = 0; |
int ret; |
int first_line=1; |
int code=0; |
|
do { |
|
if ((ret=get_line(s,buf,sizeof(buf),ftp_printf)) < 0) { |
return(ret); |
} |
|
ftp_printf(0,"FTP: %s\n",buf); |
|
if (first_line) { |
code = strtoul(buf,NULL,0); |
first_line=0; |
more = (buf[3] == '-'); |
} else { |
if (isdigit(buf[0]) && isdigit(buf[1]) && isdigit(buf[2]) && |
(code == strtoul(buf,NULL,0)) && |
buf[3]==' ') { |
more=0; |
} else { |
more =1; |
} |
} |
} while (more); |
|
return (buf[0] - '0'); |
} |
|
/* Send a command to the server */ |
static int |
send_cmd(int s,char * msgbuf,ftp_printf_t ftp_printf) { |
|
int len; |
int slen = strlen(msgbuf); |
|
if ((len = write(s,msgbuf,slen)) != slen) { |
if (slen < 0) { |
ftp_printf(1,"write %s\n",strerror(errno)); |
return FTP_BAD; |
} else { |
ftp_printf(1,"write truncasted!\n"); |
return FTP_BAD; |
} |
} |
return 1; |
} |
|
/* Send a complete command to the server and receive the reply. Return the |
MSB of the reply code. */ |
static int |
command(char * cmd, |
char * arg, |
int s, |
char *msgbuf, |
int msgbuflen, |
ftp_printf_t ftp_printf) { |
|
int err; |
|
if (!build_cmd(msgbuf,msgbuflen,cmd,arg)) { |
ftp_printf(1,"FTP: %s command to long\n",cmd); |
return FTP_BAD; |
} |
|
ftp_printf(0,"FTP: Sending %s command\n",cmd); |
|
if ((err=send_cmd(s,msgbuf,ftp_printf)) < 0) { |
return(err); |
} |
|
return (get_reply(s,ftp_printf)); |
} |
|
/* Open a socket and connect it to the server. Also print out the |
address of the server for debug purposes.*/ |
|
static int |
connect_to_server(char *hostname, |
struct sockaddr_in * local, |
ftp_printf_t ftp_printf) |
{ |
struct sockaddr_in host; |
struct servent *sent; |
#ifdef CYGPKG_NS_DNS |
struct hostent *hp=NULL; |
#endif |
int s, len; |
|
s = socket(AF_INET, SOCK_STREAM, 0); |
if (s < 0) { |
ftp_printf(1,"socket: %s\n",strerror(errno)); |
return FTP_BAD; |
} |
|
sent = getservbyname("ftp", "tcp"); |
if (sent == (struct servent *)0) { |
ftp_printf(1,"FTP: unknown serivice\n"); |
close(s); |
return FTP_BAD; |
} |
|
#ifdef CYGPKG_NS_DNS |
hp = gethostbyname(hostname); |
|
|
if (hp) { /* try name first */ |
host.sin_family = hp->h_addrtype; |
bcopy(hp->h_addr, &host.sin_addr, hp->h_length); |
} else |
#endif |
{ /* maybe it's a numeric address ?*/ |
host.sin_family = AF_INET; |
|
if (inet_aton(hostname,&host.sin_addr) == 0) { |
ftp_printf(1,"host not found: %s\n", hostname); |
close (s); |
return FTP_NOSUCHHOST; |
} |
} |
|
host.sin_port = sent->s_port; |
|
if (connect(s, (struct sockaddr *)&host, sizeof(host)) < 0) { |
ftp_printf(1,"FTP Connect failed: %s\n",strerror(errno)); |
close (s); |
return FTP_NOSUCHHOST; |
} |
|
len = sizeof(struct sockaddr_in); |
if (getsockname(s, (struct sockaddr *)local, &len) < 0) { |
ftp_printf(1,"getsockname failed %s\n",strerror(errno)); |
close(s); |
return FTP_BAD; |
} |
ftp_printf(0,"FTP: Connected to %s.%d\n", |
inet_ntoa(host.sin_addr), ntohs(host.sin_port)); |
|
return (s); |
} |
|
/* Perform a login to the server. Pass the username and password and |
put the connection into binary mode. This assumes a passwd is |
always needed. Is this true? */ |
|
static int |
login(char * username, |
char *passwd, |
int s, |
char *msgbuf, |
unsigned msgbuflen, |
ftp_printf_t ftp_printf) { |
|
int ret; |
|
ret = command("USER",username,s,msgbuf,msgbuflen,ftp_printf); |
if (ret != 3) { |
ftp_printf(1,"FTP: User %s not accepted\n",username); |
return (FTP_BADUSER); |
} |
|
ret = command("PASS",passwd,s,msgbuf,msgbuflen,ftp_printf); |
if (ret < 0) { |
return (ret); |
} |
if (ret != 2) { |
ftp_printf(1,"FTP: Login failed for User %s\n",username); |
return (FTP_BADUSER); |
} |
|
ftp_printf(0,"FTP: Login sucessfull\n"); |
|
ret = command("TYPE","I",s,msgbuf,msgbuflen,ftp_printf); |
if (ret < 0) { |
return (ret); |
} |
if (ret != 2) { |
ftp_printf(1,"FTP: TYPE failed!\n"); |
return (FTP_BAD); |
} |
return (ret); |
} |
|
|
/* Open a data socket. This is a client socket, i.e. its listening |
waiting for the FTP server to connect to it. Once the socket has been |
opened send the port command to the server so the server knows which |
port we are listening on.*/ |
static int |
opendatasock(int ctrl_s, |
struct sockaddr_in ctrl, |
char *msgbuf, |
unsigned msgbuflen, |
ftp_printf_t ftp_printf) { |
|
struct sockaddr_in local; |
socklen_t len; |
int on = 1; |
char buf[4*6+1]; |
char *a, *p; |
int ret; |
int s; |
|
s = socket(AF_INET, SOCK_STREAM, 0); |
if (s < 0) { |
ftp_printf(1,"socket: %s\n",strerror(errno)); |
return FTP_BAD; |
} |
|
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { |
ftp_printf(1,"setsockopt: %s\n",strerror(errno)); |
close(s); |
return FTP_BAD; |
} |
|
local = ctrl; |
local.sin_family = AF_INET; |
local.sin_port = 0; |
if (bind(s,(struct sockaddr *)&local,sizeof(local)) < 0) { |
ftp_printf(1,"bind: %s\n",strerror(errno)); |
close(s); |
return FTP_BAD; |
} |
|
len = sizeof(local); |
if (getsockname(s,(struct sockaddr *)&local,&len) < 0) { |
ftp_printf(1,"getsockname: %s\n",strerror(errno)); |
close(s); |
return FTP_BAD; |
} |
|
if (listen(s, 1) < 0) { |
ftp_printf(1,"listen: %s\n",strerror(errno)); |
close(s); |
return FTP_BAD; |
} |
|
#define BtoI(b) (((int)b)&0xff) |
a = (char *)&local.sin_addr; |
p = (char *)&local.sin_port; |
sprintf(buf,"%d,%d,%d,%d,%d,%d", |
BtoI(a[0]),BtoI(a[1]),BtoI(a[2]),BtoI(a[3]), |
BtoI(p[0]),BtoI(p[1])); |
|
ret = command("PORT",buf,ctrl_s,msgbuf,msgbuflen,ftp_printf); |
if (ret < 0) { |
close(s); |
return (ret); |
} |
|
if (ret != 2) { |
ftp_printf(1,"FTP: PORT failed!\n"); |
close(s); |
return (FTP_BAD); |
} |
return (s); |
} |
|
/* Receive the file into the buffer and close the data socket |
afterwards */ |
static int |
receive_file(int data_s, char *buf, int buf_size,ftp_printf_t ftp_printf) |
{ |
int remaining = buf_size; |
int finished = 0; |
int total_size=0; |
char *bufp = buf; |
int len; |
int s; |
|
s = accept(data_s,NULL,0); |
if (s<0) { |
ftp_printf(1,"listen: %s\n",strerror(errno)); |
return FTP_BAD; |
} |
|
do { |
len = read(s,bufp,remaining); |
if (len < 0) { |
ftp_printf(1,"read: %s\n",strerror(errno)); |
close(s); |
return FTP_BAD; |
} |
|
if (len == 0) { |
finished = 1; |
} else { |
total_size += len; |
remaining -= len; |
bufp += len; |
|
if (total_size == buf_size) { |
ftp_printf(1,"FTP: File too big!\n"); |
close(s); |
return FTP_TOOBIG; |
} |
} |
} while (!finished); |
|
close(s); |
return total_size; |
} |
|
/* Receive the file into the buffer and close the socket afterwards*/ |
static int |
send_file(int data_s, char *buf, int buf_size,ftp_printf_t ftp_printf) |
{ |
int remaining=buf_size; |
int finished = 0; |
char * bufp = buf; |
int len; |
int s; |
|
s = accept(data_s,NULL,0); |
if (s<0) { |
ftp_printf(1,"listen: %s\n",strerror(errno)); |
return FTP_BAD; |
} |
|
do { |
len = write(s,bufp,remaining); |
if (len < 0) { |
ftp_printf(1,"write: %s\n",strerror(errno)); |
close(s); |
return FTP_BAD; |
} |
|
if (len == remaining) { |
finished = 1; |
} else { |
remaining -= len; |
bufp += len; |
} |
} while (!finished); |
|
close(s); |
return 0; |
} |
|
/* All done, say bye, bye */ |
static int quit(int s, |
char *msgbuf, |
unsigned msgbuflen, |
ftp_printf_t ftp_printf) { |
|
int ret; |
|
ret = command("QUIT",NULL,s,msgbuf,msgbuflen,ftp_printf); |
if (ret < 0) { |
return (ret); |
} |
if (ret != 2) { |
ftp_printf(1,"FTP: Quit failed!\n"); |
return (FTP_BAD); |
} |
|
ftp_printf(0,"FTP: Connection closed\n"); |
return (0); |
} |
|
/* Get a file from an FTP server. Hostname is the name/IP address of |
the server. username is the username used to connect to the server |
with. Passwd is the password used to authentificate the |
username. filename is the name of the file to receive. It should be |
the full pathname of the file. buf is a pointer to a buffer the |
contents of the file should be placed in and buf_size is the size |
of the buffer. If the file is bigger than the buffer, buf_size |
bytes will be retrieved and an error code returned. ftp_printf is a |
function to be called to perform printing. On success the number of |
bytes received is returned. On error a negative value is returned |
indicating the type of error. */ |
|
int ftp_get(char * hostname, |
char * username, |
char * passwd, |
char * filename, |
char * buf, |
unsigned buf_size, |
ftp_printf_t ftp_printf) |
{ |
|
struct sockaddr_in local; |
char msgbuf[256]; |
int s,data_s; |
int bytes; |
int ret; |
|
s = connect_to_server(hostname,&local,ftp_printf); |
if (s < 0) { |
return (s); |
} |
|
/* Read the welcome message from the server */ |
if (get_reply(s,ftp_printf) != 2) { |
ftp_printf(0,"FTP: Server refused connection\n"); |
close(s); |
return FTP_BAD; |
} |
|
ret = login(username,passwd,s,msgbuf,sizeof(msgbuf),ftp_printf); |
if (ret < 0) { |
close(s); |
return (ret); |
} |
|
/* We are now logged in and ready to transfer the file. Open the |
data socket ready to receive the file. It also build the PORT |
command ready to send */ |
data_s = opendatasock(s,local,msgbuf,sizeof(msgbuf),ftp_printf); |
if (data_s < 0) { |
close (s); |
return (data_s); |
} |
|
/* Ask for the file */ |
ret = command("RETR",filename,s,msgbuf,sizeof(msgbuf),ftp_printf); |
if (ret < 0) { |
close(s); |
close(data_s); |
return (ret); |
} |
|
if (ret != 1) { |
ftp_printf(0,"FTP: RETR failed!\n"); |
close (data_s); |
close(s); |
return (FTP_BADFILENAME); |
} |
|
if ((bytes=receive_file(data_s,buf,buf_size,ftp_printf)) < 0) { |
ftp_printf(0,"FTP: Receiving file failed\n"); |
close (data_s); |
close(s); |
return (bytes); |
} |
|
if (get_reply(s,ftp_printf) != 2) { |
ftp_printf(0,"FTP: Transfer failed!\n"); |
close (data_s); |
close(s); |
return (FTP_BAD); |
} |
|
ret = quit(s,msgbuf,sizeof(msgbuf),ftp_printf); |
if (ret < 0) { |
close(s); |
close(data_s); |
return (ret); |
} |
|
close (data_s); |
close(s); |
return bytes; |
} |
|
/* Put a file on an FTP server. Hostname is the name/IP address of the |
server. username is the username used to connect to the server |
with. Passwd is the password used to authentificate the |
username. filename is the name of the file to receive. It should be |
the full pathname of the file. buf is a pointer to a buffer the |
contents of the file should be placed in and buf_size is the size |
of the buffer. ftp_printf is a function to be called to perform |
printing. On success 0 is returned. On error a negative value is |
returned indicating the type of error. */ |
|
int ftp_put(char * hostname, |
char * username, |
char * passwd, |
char * filename, |
char * buf, |
unsigned buf_size, |
ftp_printf_t ftp_printf) |
{ |
|
struct sockaddr_in local; |
char msgbuf[256]; |
int s,data_s; |
int ret; |
|
s = connect_to_server(hostname,&local,ftp_printf); |
if (s < 0) { |
return (s); |
} |
|
/* Read the welcome message from the server */ |
if (get_reply(s,ftp_printf) != 2) { |
ftp_printf(1,"FTP: Server refused connection\n"); |
close(s); |
return FTP_BAD; |
} |
|
ret = login(username,passwd,s,msgbuf,sizeof(msgbuf),ftp_printf); |
if (ret < 0) { |
close(s); |
return (ret); |
} |
|
/* We are now logged in and ready to transfer the file. Open the |
data socket ready to receive the file. It also build the PORT |
command ready to send */ |
data_s = opendatasock(s,local,msgbuf,sizeof(msgbuf),ftp_printf); |
if (data_s < 0) { |
close (s); |
return (data_s); |
} |
|
/* Ask for the file */ |
ret = command("STOR",filename,s,msgbuf,sizeof(msgbuf),ftp_printf); |
if (ret < 0) { |
close(s); |
close(data_s); |
return (ret); |
} |
|
if (ret != 1) { |
ftp_printf(1,"FTP: STOR failed!\n"); |
close (data_s); |
close(s); |
return (FTP_BADFILENAME); |
} |
|
if ((ret = send_file(data_s,buf,buf_size,ftp_printf)) < 0) { |
ftp_printf(1,"FTP: Sending file failed\n"); |
close (data_s); |
close(s); |
return (ret); |
} |
|
if (get_reply(s,ftp_printf) != 2) { |
ftp_printf(1,"FTP: Transfer failed!\n"); |
close (data_s); |
close(s); |
return (FTP_BAD); |
} |
|
ret = quit(s,msgbuf,sizeof(msgbuf),ftp_printf); |
if (ret < 0) { |
close(s); |
close(data_s); |
return (ret); |
} |
|
close (data_s); |
close(s); |
return 0; |
} |
|
/* An example ftp_printf function. This uses the standard eCos diag |
output device for outputting error and diagnostic messages. The |
function take one addition parameter to the normal printf function. The |
first parameter indicates when the message is an error message when |
true. This can be used to filter errors from diagnostic output. In |
this example the error parameter is ignored and everything printed. */ |
|
void ftpclient_printf(unsigned error, const char *fmt, ...) |
{ |
va_list ap; |
|
va_start(ap, fmt); |
diag_vprintf( fmt, ap); |
va_end(ap); |
} |
/ChangeLog
0,0 → 1,57
2003-02-24 Jonathan Larmour <jifl@eCosCentric.com> |
|
* cdl/ftpclient.cdl: Add doc link. |
|
2002-08-06 Andrew Lunn <andrew.lunn@ascom.ch> |
|
* src/ftpclient.c: Send "quit" not "quit " to keep some servers |
happy. Also deal with multi line replies correctly. |
|
2002-02-22 Hugo Tyson <hmt@redhat.com> |
|
* doc/ftpclient.sgml: New file. Document it. |
|
2001-12-04 Andrew Lunn <andrew.lunn@ascom.ch> |
|
* src/ftpclient.c: Allow it to compile! |
|
2001-11-04 Andrew Lunn <andrew.lunn@ascom.ch> |
|
* First version. Implements an FTP client which can get and put |
files on a server. |
|
//=========================================================================== |
//####ECOSGPLCOPYRIGHTBEGIN#### |
// ------------------------------------------- |
// This file is part of eCos, the Embedded Configurable Operating System. |
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
// |
// eCos 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 or (at your option) any later version. |
// |
// eCos 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 eCos; if not, write to the Free Software Foundation, Inc., |
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
// |
// As a special exception, if other files instantiate templates or use macros |
// or inline functions from this file, or you compile this file and link it |
// with other works to produce a work based on this file, this file does not |
// by itself cause the resulting work to be covered by the GNU General Public |
// License. However the source code for this file must still be made available |
// in accordance with section (3) of the GNU General Public License. |
// |
// This exception does not invalidate any other reasons why a work based on |
// this file might be covered by the GNU General Public License. |
// |
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
// at http://sources.redhat.com/ecos/ecos-license/ |
// ------------------------------------------- |
//####ECOSGPLCOPYRIGHTEND#### |
//=========================================================================== |
|