OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /or1k/trunk/ecos-2.0/packages/net/ftpclient
    from Rev 1254 to Rev 1765
    Reverse comparison

Rev 1254 → Rev 1765

/v2_0/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."
}
}
 
/v2_0/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();
}
/v2_0/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
 
/v2_0/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 &lt;network.h&gt;
#include &lt;ftpclient.h&gt;
</programlisting>
It looks like this:
</para>
<sect2 id="net-ftpclient-features-api-get">
<title>ftp_get</title>
<programlisting>
int ftp_get(char &ast; hostname,
char &ast; username,
char &ast; passwd,
char &ast; filename,
char &ast; 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 &lsquo;/&rsquo; file separators,
not &lsquo;\&rsquo;.
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 &ast; hostname,
char &ast; username,
char &ast; passwd,
char &ast; filename,
char &ast; 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 &lsquo;/&rsquo; file separators,
not &lsquo;\&rsquo;.
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>
v2_0/doc/ftpclient.sgml Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: v2_0/ChangeLog =================================================================== --- v2_0/ChangeLog (nonexistent) +++ v2_0/ChangeLog (revision 1765) @@ -0,0 +1,57 @@ +2003-02-24 Jonathan Larmour + + * cdl/ftpclient.cdl: Add doc link. + +2002-08-06 Andrew Lunn + + * src/ftpclient.c: Send "quit" not "quit " to keep some servers + happy. Also deal with multi line replies correctly. + +2002-02-22 Hugo Tyson + + * doc/ftpclient.sgml: New file. Document it. + +2001-12-04 Andrew Lunn + + * src/ftpclient.c: Allow it to compile! + +2001-11-04 Andrew Lunn + + * 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#### +//=========================================================================== + Index: v2_0/src/ftpclient.c =================================================================== --- v2_0/src/ftpclient.c (nonexistent) +++ v2_0/src/ftpclient.c (revision 1765) @@ -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 + +#include +#include +#include +#include +#include +#include +#include +#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); +}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.