# FTP-Lite Manual

Version 0.4, 27 August 2004

## Table of Contents

- Front Matter
- Introduction
- Installation
- Examples
- Reference

## Front Matter

The FTP-Lite Library is copyright (C) 2004 Douglas Thain and the University of Notre Dame.

This product includes software developed by and/or derived from the Globus Project (http://www.globus.org/) to which the U.S. Government retains certain rights.

This program is released under the GNU General Public License. See the file COPYING for details.

This software comes with no warranty and no guarantee of support. Questions, bug reports, and patches may be sent to condor-admin@cs.wisc.edu. We will address such inquiries as time and resources permit.

## Introduction

FTP-Lite is a library for accessing FTP servers from UNIX C programs.

It is designed to be simple, correct, and easily debuggable. In particular, FTP-Lite presents an FTP service in terms of UNIX abstractions. Errors are return in standard `errno` values. Data streams are presented as `FILE` objects. All procedures perform blocking I/O.

The library may be built as-is in order to communicate with ordinary name/password or anonymous FTP servers. However, if the Globus Toolkit is available, it will also perform GSI authentication with your proxy certificate.

FTP-Lite provides perfectly reasonable performance for simple clients that access one file at a time. For clients that need to manage multiple servers at once, we heartily recommend the FTP implementation found in the Globus Toolkit. It uses a variety of techniques, such as multiple data streams and non-blocking interfaces, for achieving high performance and multi-server access.

This library was designed specifically to be used with the Pluggable File System, which presents network storage devices as UNIX file systems. You are welcome to use it for other purposes, according to the terms set out in the GNU Library General Public License.

## Installation

Download the FTP-Lite source package from the web page. Unpack the archive like so:

    % gunzip ftp_lite-0.0.tar.gz
    % tar xvf ftp_lite-0.0.tar

Decide on a place to install FTP-Lite. If you have the Globus and SSL libraries, figure out where they are installed, and feed the information to `configure`:

    % cd ftp_lite-0.0
    % ./configure --prefix /install/dir --with-globus-path /path/to/globus --with-ssl-path /path/to/ssl

(At UW-Madison, the appropriate invocation would be:)

    % cd ftp_lite-0.0
    % ./configure --prefix ~/ftp_lite --with-globus-path /p/condor/workspaces/globus --with-ssl-path /p/condor/workspaces/ssl

Finally, build and install the library:

    % make
    % make install

To build a program using FTP-Lite, change your compile and link options like so:

    CCFLAGS += -I/install/dir/include
    LDFLAGS += -L/install/dir/lib -lftp_lite

## Examples

For examples of using the library, we recommend that you begin by examining the code for the simple programs `ftp_lite_test` and `ftp_lite_copy`. A complete description of every function may be found in the reference section below. Here is a brief example to get you started.

A program using the library must first include `ftp_lite.h`:

    #include "ftp_lite.h"

To open a server, call `ftp_lite_open` with a server name, port number, and a stream on which to send debugging messages. For no debugging, leave the third argument null. On success, this function returns a pointer to a server.

    struct ftp_server *s;

    s = ftp_lite_open( "ftp.cs.wisc.edu", FTP_LITE_DEFAULT_PORT, stderr );
    if(!s) {
    	perror("couldn't open server");
    	return 0;
    }

You must authenticate yourself to the server before accessing any data. Three sorts of authentication are currently provided: anonymous, userpass, and Globus. For example, to authenticate with a username and password:

    success = ftp_lite_auth_userpass(server,"fred","secret");
    if(!success) {
    	perror("couldn't log in");
    	return 0;
    }

For convenience, FTP-Lite provides a single procedure which tries the various authentication methods, possible requesting information from the console. Most users will find it easiest to replace the above two steps with :

    s = ftp_lite_open_and_auth( "ftp.cs.wisc.edu", stderr );
    if(!s) {
    	perror("couldn't open server");
    	return 0;
    }

To retrieve a file, call `ftp_lite_get` with the server pointer, a path name, and the offset at which to begin. On success, it returns a `FILE` object.

    FILE *f;

    f = ftp_lite_get( s, "README", 0 );
    if(!f) {
    	perror("couldn't get file");
    	return 0;
    }

You may read from this stream pointer using any of the standard UNIX I/O operations, such as `fscanf`, `fread`, and so on. For convenience, FTP-Lite provides a function `ftp_lite_stream_to_stream` that will copy one whole file pointer into another. So, to display this file, you might do this:

    length = ftp_lite_stream_to_stream( f, stdout );
    if(length<0) {
    	perror("couldn't transfer data");
    	return 0;
    }

When done reading data, you must close the stream and inform the server that you are done:

    fclose(f);
    ftp_lite_done(s);

To close the connection to the server completely:

    ftp_lite_close(s);

## Reference

This section lists all of the public functions in the FTP-Lite library.

Unless noted otherwise, all functions return true (non-zero) on success or false (zero) on failure. In addition, every function sets `errno` appropriately on a failure. Tools for handling error values can be found in the UNIX man pages for `errno`, `strerror`, and `perror`. Nearly every error value is a possible result of any function.

Some error values are inacurrate, due to weaknesses in the FTP protocol itself. For example, the FTP error 550 is represented as the errno `EEXIST`. However, a brief poll of servers shows that many return the same error value for errors that should be distinct, such as "no such file", and "file already exists." So, be careful.

If the library is returning unexpected results, we recommend that you debug the code by passing `stderr` as the debugging argument to `ftp_lite_open`. This will show a low of events in the protocol, and is invaluable in revealing unexpected events.

So, here are the procedures in the library:

- ftp_lite_auth_anonymous

  int ftp_lite_auth_anonymous( struct ftp_lite_server *s );

  Attempt to log in anonymously to an already-opened server.

- ftp_lite_auth_globus

  int ftp_lite_auth_globus( struct ftp_lite_server *s );

  Attempt to log in with Globus credentials to an already-opened server. The caller must have already established a proxy certificate with `grid-proxy-init` or a similar tool.

- ftp_lite_auth_userpass

  int ftp_lite_auth_userpass( struct ftp_lite_server *s, const char *user, const char *password );

  Attempt to log in with this name and password. This mechanism sends names and passwords in the clear and should be deprecated in favor of Globus authentication.

- ftp_lite_change_dir

  int ftp_lite_change_dir( struct ftp_lite_server *s, const char *dir );

  Change the current working directory to that given.

- ftp_lite_close

  void ftp_lite_close( struct ftp_lite_server *server );

  Close this open server. Once a connection is closed, the server pointer is no longer valid.

- ftp_lite_delete int

  int ftp_lite_delete( struct ftp_lite_server *s, const char *path );

  Delete a file.

- ftp_lite_delete_dir

  int ftp_lite_delete_dir( struct ftp_lite_server *s, const char *dir );

  Delete a directory. Most servers will not permit the deletion of a directory that is not empty.

- ftp_lite_done

  int ftp_lite_done( struct ftp_lite_server *s );

  Signal that a data transfer is complete. This must be called before any other functions are invoked.

- ftp_lite_get

  FILE * ftp_lite_get( struct ftp_lite_server *s, const char *path, off_t offset );

  Retrieve a file beginning from this offset. On success, returns a stream pointer. On failure, returns null. After reading to the end of the stream, you must call `fclose` and `ftp_lite_done`.

- ftp_lite_list

  FILE * ftp_lite_list( struct ftp_lite_server *s, const char *path );

  Retrieve the list of names contained in this directory. On success, return a stream pointer which will provide the list of newline-terminated names. On failure, returns null. After reading to the end of the stream, you must call `fclose` and `ftp_lite_done`.

- ftp_lite_login

  int ftp_lite_login( const char *prompt, char *name, int namelen, char *pass, int passlen );

  Display a prompt on the console and ask the user to enter a name and password. `name` and `pass` are filled in up to the lengths given.

- ftp_lite_make_dir

  int ftp_lite_make_dir( struct ftp_lite_server *s, const char *dir );

  Create a directory.

- ftp_lite_nop

  int ftp_lite_nop( struct ftp_lite_server *s );

  Send a no-operation command to the server. This command is useful for determining if a connection is still alive.

- ftp_lite_open

  struct ftp_lite_server * ftp_lite_open( const char *host, int port, FILE *log );

  Connect to a server on the given host and port. The third argument gives a stream which is used for debugging information. On success, return an opaque pointer to a server. On failure, return null. The appropriate port depends on the authentication method to be used. For Globus authentication, connect to `FTP_LITE_GSS_DEFAULT_PORT`. For anonymous and userpass authentication, connect to `FTP_LITE_DEFAULT_PORT`.

- ftp_lite_open_and_auth

  struct ftp_lite_server * ftp_lite_open_and_auth( const char *host, FILE *log );

  Connect to a server, but try all available ports and authentication methods. The second argument gives a stream to be used for debugging. On success, return an opaque pointer to a server. On failure, return null.

- ftp_lite_put

  FILE * ftp_lite_put( struct ftp_lite_server *s, const char *path, off_t offset, size_t size );

  Transmit a file to a server. On success, returns a stream to be written to. On failure, returns null. After writing all data to the stream, you must call `fclose` and `ftp_lite_done`. `offset` controls the point at which writing will begin in the target file. If `size` is `FTP_LITE_WHOLE_FILE`, then the target file will be truncated when the stream is closed. A variety of FTP commands may be used to implement a put, and not all severs will support all combinations of `offset` and `size`.

- ftp_lite_rename

  int ftp_lite_rename( struct ftp_lite_server *s, const char *oldname, const char *newname );

  Move the file `oldname` in `newname`.

- ftp_lite_size

  size_t ftp_lite_size( struct ftp_lite_server *s, const char *path );

  Return the number of bytes stored in this file. On failure, returns -1.

- ftp_lite_stream_to_buffer

  int ftp_lite_stream_to_buffer( FILE *input, char **buffer );

  Copy the contents of this stream into a memory buffer. On success, returns the number of bytes copied. On failure, returns -1. `input` must be a stream opened for reading, and `buffer` must be a pointer to an uninitialized `char *`. Space for the buffer will be allocated with `malloc`. The caller becomes responsible for freeing the buffer when done.

- ftp_lite_stream_to_stream

  int ftp_lite_stream_to_stream( FILE *input, FILE *output );

  Copy the contents of one stream into another. On success, returns the number of bytes copied. On failure, returns -1.

- ftp_lite_third_party_transfer

  int ftp_lite_third_party_transfer( struct ftp_lite_server *source, const char *source_file, struct ftp_lite_server *target, const char *target_file );

  Performs a third-party transfer between two servers. Each server must already be opened and authenticated. There are a large number of reasons for which a third party transfer might fail. We recommend you use this feature with the debugging stream enabled.