Remote Operations On Files
Introduction
Download
Installation
Packaging
Client program
API
ftpfs
ftping
About the author
Related links
Introduction
roof stands
for Remote Operations On Files.
It is a
FTP related
set
of
services
compliant
with
RFC959.
It comes with:
- A FTP client program called roof;
- A FTP client API for programs which would like to set up
FTP transactions with a remote server. It is
available as a shared
library called libroof.so;
- A File system called ftpfs;
- A ping program called ftping which looks
like the famous ICMP level ping program but it operates à FTP
protocol level to check if a remote FTP server is up or not.
Its source code is described here.
Download
ROOF can be downloaded from sourceforge
in one of the following three ways:
- Source package (tgz: tar compressed file)
- DEB binary package
- RPM binary
package
Concerning the source package, you can also use a CVS client and enter
the following command under a shell like bash:
$ export
CVSROOT=:pserver:anonymous@roof.cvs.sourceforge.net:/cvsroot/roof
$ cvs checkout roof
You will normally see a new local directory called 'roof' in which are
located the downloaded source files. The subtree looks like:
The include
directory contains the file roof.h in which are defined the services
and data structures of the API.
The lib
directory contains the implementation of the library libroof.so which
is destined to be dynamically linked to the user program.
The man
directory contains the on-line manuals.
The client
directory contains an example of FTP
client based on the API.
The fs
directory contains a file system manager called ftpfs
which mounts a remote file system through the FTP protocol.
Installation
Installation
from the sources with cmake
The installation from the sources supposes that cmake
is installed on your Linux machine.
Unpack the tar compressed file roof-xxx.tgz
into a directory. This will create a sub-directory called roof-xxx with the
source files of the program:
$ tar xvfz
roof-xxx.tgz
Go into the newly created directory:
$ cd roof-xxx
While building the makefiles, you can choose where the files will be
installed with the environment variable CMAKE_INSTALL_PREFIX.
If not defined, the installation defaults to /usr/local.
$ cmake .
-DCMAKE_INSTALL_PREFIX=<path_of_installation>
Then the build is triggered by invoking make:
$ make
And the installation is done specifying the install target:
$ make install
It is possible to trigger a cleanup of the built objects
with the clean
target:
$ make clean
If your PATH
variable is correctly set, ROOF's help can be displayed:
$ roof --help
If your MANPATH
variable is correctly set, ROOF's online manual can be displayed:
$ man 1 roof
$ man 3 roof
$ man 7 roof
Installation
from the sources with a custom script
The installation from the sources supposes that cmake
is installed on your Linux machine.
Unpack the tar compressed file roof-xxx.tgz
into a directory. This will create a sub-directory called roof-xxx with the
source files of the program:
$ tar xvfz
roof-xxx.tgz
Go into the newly created directory:
$ cd roof-xxx
Make sure the file roof_install.sh
has the execute permission:
$ chmod +x
roof_install.sh
Launch the script roof_install.sh
to get the help:
$ ./roof_install.sh
-h
Usage:
roof_install.sh [-d install_root_dir] [-P DEB | RPM] [-B] [-I] [-A] [-h]
-d
:
Installation
directory
(default:
/usr/local)
-P
:
Generate
a
DEB
or
RPM
package
-B
:
Build
the
software
-I
:
Install
the
software
-A
:
Generate
an
archive
of
the
software (sources)
-h
:
this
help
Under root identity, launch the installation by passing '-I' and
optionnaly '-d' to specify an installation directory different
than /usr/local.
For example, for an installation in /usr/local, type:
$ sudo
./roof_install.sh -I
For an installation in '/usr', type;
$ sudo
./roof_install.sh -I -d /usr
If your PATH
variable is correctly set, ROOF's help can be displayed:
$ roof --help
If your MANPATH
variable is correctly set, ROOF's online manual can be displayed:
$ man 1 roof
$ man 3 roof
$ man 7 roof
Installation
from the DEB binary package
The files are installed via the command:
$ sudo dpkg -i
roof-xxx.deb
Installation
from the RPM binary package
The files are installed via the command:
$ sudo rpm -i
roof-xxx.rpm
Packaging
The packaging process supposes that cmake
is installed on your Linux machine.
Generation
of a DEB binary package
Unpack the tar compressed file roof-xxx.tgz
into a directory. This will create a sub-directory called roof-xxx with the
source files of the program:
$ tar xvfz
roof-xxx.tgz
Go into the newly created directory:
$ cd roof-xxx
Make sure the file roof_install.sh
has the execute permission:
$ chmod +x
roof_install.sh
Launch the script roof_install.sh
to get the help:
$ ./roof_install.sh
-h
Usage:
roof_install.sh [-d install_root_dir] [-P DEB | RPM] [-B] [-I] [-A] [-h]
-d
:
Installation
directory
(default:
/usr/local)
-P
:
Generate
a
DEB
or
RPM
package
-B
:
Build
the
software
-I
:
Install
the
software
-A
:
Generate
an
archive
of
the
software (sources)
-h
:
this
help
Under root identity, launch the installation by passing '-P DEB' and
optionnaly '-d' to specify an installation directory different
than /usr/local.
For example, for a package which will be installed in /usr/local, type:
$ sudo
./roof_install.sh -P DEB
For an installation in /usr,
type;
$ sudo
./roof_install.sh -P DEB -d /usr
Generation
of a RPM binary package
Unpack the tar compressed file roof-xxx.tgz
into a directory. This will create a sub-directory called roof-xxx with the
source files of the program:
$ tar xvfz
roof-xxx.tgz
Go into the newly created directory:
$ cd roof-xxx
Make sure the file roof_install.sh
has the execute permission:
$ chmod +x
roof_install.sh
Launch the script roof_install.sh
to get the help:
$ ./roof_install.sh
-h
Usage:
roof_install.sh [-d install_root_dir] [-P DEB | RPM] [-B] [-I] [-A] [-h]
-d
:
Installation
directory
(default:
/usr/local)
-P
:
Generate
a
DEB
or
RPM
package
-B
:
Build
the
software
-I
:
Install
the
software
-A
:
Generate
an
archive
of
the
software (sources)
-h
:
this
help
Under root identity, launch the installation by passing '-P RPM' and
optionnaly '-d' to specify an installation directory different
than /usr/local.
For example, for a package which will be installed in /usr/local, type:
$ sudo
./roof_install.sh -P RPM
For an installation in /usr,
type;
$ sudo
./roof_install.sh -P RPM -d /usr
Generation
of a ZIP tar file
Unpack the tar compressed file roof-xxx.tgz
into a directory. This will create a sub-directory called roof-xxx with the
source files of the program:
$ tar xvfz
roof-xxx.tgz
Go into the newly created directory:
$ cd roof-xxx
Make sure the file roof_install.sh
has the execute permission:
$ chmod +x
roof_install.sh
Launch the script roof_install.sh
to get the help:
$ ./roof_install.sh
-h
Usage:
roof_install.sh [-d install_root_dir] [-P DEB | RPM] [-B] [-I] [-A] [-h]
-d
:
Installation
directory
(default:
/usr/local)
-P
:
Generate
a
DEB
or
RPM
package
-B
:
Build
the
software
-I
:
Install
the
software
-A
:
Generate
an
archive
of
the
software (sources)
-h
:
this
help
Under root identity, launch the installation by passing '-A':
$ sudo
./roof_install.sh -A
Client
program
roof is a FTP client compliant with RFC959.
Usage
roof [ -p port
] [ -H hostname
] [ -L login_name
] [ -P password
] [ -A account
] [ -b
size
] [ -d debug_level
] [ -hV ]
Options
The options are:
-p port
--port=port
Server’s
port
number
(default
is
21).
-H
hostname
--host=hostname
Server’s
host
name.
The
name
can
be
an
ascii
name or a dotted IP
address (default is local host loop back 127.0.0.1).
-L
login_name
--login=login_name
Login
name
for
identification.
-P
password
--passwd=password
Password
for
identification.
-A
account
--acct=account
Account
information
for
identification.
-b size
--bufsz=size
Set
I/O buffer to size bytes (default 4096)
-d
debug_level
--debug=debug_level
Set
the
debug
level
to
debug_level.
The
value
is
a
positive integer value. The bigger the value, the more debug
traces will appear (0 unsets the debug
mode). This is useful to catch the error messages from the
server when a command fails.
-h
--help
Display
the
help
of
the
command
(subset
of
this
man page).
-V
--version
Display
the
version
of
the
software.
Commands
roof accepts a command line with the format:
cmd
param1 param2 param3...
where cmd and paramX are
strings that can be
enclosed with double quotes to take in account blank characters and may
contain the following control characters:
\
Space
\t Horizontal tabulation
\a Bell
\b Backspace
\n New line
\r Carriage return
\f Form feed
\v Vertical tabulation
\" Double quote
\\ Backslash
roof accepts the following commands:
? [
cmd ]
Display
the list of available commands. If followed by a
command name cmd,
it displays the help of this command. This is the same command as help.
ascii Shortcut
for
’type
A
N’
to
set
ASCII
transfer type.
bin Shortcut
for
’type
I’
to
set
image
(binary)
transfer type.
cd
dir
Change current directory
to dir.
cnx [-H
host] [-p port] [-L login] [-P password] [-A account]
Connect to the remote
host. If no
parameters or part of them are passed, the missing one
are
respectively taken from the previous call to cnx and the options
passed to the program (-H,
-p, -L, -P
and -A). Once
the connection is established, the prompt is changed to
reflect the remote host information.
dbg
Display the current debug
level.
dbg
level
Set the current debug
level to level.
dcnx
Disconnect from the remote
host.
dir
Same as ls command.
exit
Quit the program (Same
effect as CTRL D
or quit
command).
get
src_file [ dst_file ]
Transfer src_file
from remote host into dst_file
(default, basename of src_file
in current local directory).
help
[ cmd ]
Display the list of available
commands. If followed by a command name cmd, it displays the help
of this command. This is the same command as ?.
When connected, the help is requested to the remote
server. When disconnected, the help is requested locally. When
connected, use ’!help’ or ’!?’ to request the help locally.
ls [
-l ] [ dir ]
List the content of the
remote directory dir
(current directory by default). If -l
option is passed, details about the size, right
accesses
and access times will be displayed if the server supports it.
mget
file1 [ file2... ]
Transfer all the fileX from
remote host to local host.
mkdir
dir
Make the directory dir on the
remote host.
mput
file1 [ file2... ]
Transfer all the fileX from
local host to remote host.
mv
src_file dst_file
Rename the file src_file
into dst_file
on the remote host.
passive
[
on|
off]
Set Passive (on) or Active (off) mode
(display the the current mode if no parameters)
put
src_file [ dst_file ]
Transfer the file src_file to
the remote host into dst_file
(by default, the same name is
kept).
pwd
Print the name of the
current working directory.
quit
Quit the program (Same
effect as CTRL D
or exit
command).
rm
file_name
Remove the file file_name
on the remote host.
rmdir
dir_name
Remove the directory dir_name on
the remote host.
site
cmd [
par1 par2...]
Launch the custom command cmd on the remote server.
type
[A|E [N|T|C]] [I] [L byte_size ]
Set the transfer
and format types
(A = ASCII, E = EBCDIC, I = Image (binary), L = Local byte size
associated with a size in bytes, N = Non print (default), T
= Telnet format effector, C = carriage control).
There are
two widely used forms for this commands: ’type A N’ for
ASCII type and ’type I’ for binary type. Hence, the
shortcuts ascii
and bin.
up
Go to
the upper directory.
!cmd
Run the command cmd locally
if supported.
Examples
The following example shows a
FTP connection to
the default port 21 on a host called ’remote’ with the
login name ’foo’ and password ’bar’. A
'ls -l' command is launched followed by
a
'get'. Then we disconnect and
reconnect
to the same host to make a directory called ’images’ before
exiting from the program.
$
roof
ftp> cnx -H
remote -L foo -P bar
Connection successful
Remote operating
system is ’UNIX’
foo@remote:21>
ls -l
drwx------
2 foo grp 4096 May 4
2007 VIDEO_WORK
drwx------
3 foo grp 4096 Oct 21 19:03 VIDEO_PERSO
-rwx------
1 foo grp 1718 Oct 28 22:58 qwerty.txt
-rwx------
1 foo grp 63328 Oct 27 19:49 azerty.txt
-rwx------
1 foo grp 198 Apr
9 2007 backup.sh
drwx------
8 foo grp 4096 Oct 30 23:41 cxoffice
drwx------
3 foo grp 4096 Nov 8 08:16
dvd_data
drwx------
4 foo grp 4096 May 31 2007
freeplayer
drwx------ 16 foo
grp 4096 Apr 2 2007
folder
-rw-r--r--
1 foo grp 255999 Nov 30 07:57 saved.odt
foo@remote:21>
get azerty.txt
’azerty.txt’
transfered successfully (63328 bytes)
foo@remote:21>
dcnx
Connection closed
ftp> cnx
Connection successful
Remote operating
system is ’UNIX’
foo@remote:21>
mkdir images
’images’ made
successfully
foo@remote:21>
exit
End of session
$
The following example shows a FTP
connection to the
port 2000 on a host called ’remote’ with the login name
’foo’ and password ’bar’. A ls command is
launched followed by a ls on the file named
"filename with
blanks" which contains blank characters. For the sake of the example,
we use two different methods to match the spaces: the double
quotes and the control
sequence. Then we
disconnect.
$
roof -H remote -L foo -P
bar -p 2000
ftp> cnx
Connection successful
Remote operating system is ’UNIX’
foo@remote:21> ls -l
VIDEO_WORK
VIDEO_PERSO
qwerty.txt
azerty.txt
backup.sh
cxoffice
filename with blanks
dvd_data
foo@remote:21> ls "filename "with\ blanks
filename with blanks
foo@remote:21> dcnx
Connection closed
ftp> exit
End of session
$
API
Services
The API is composed with the following functions:
#include <roof.h>
roof_ctx_t *roof_new(unsigned
int timeout_ms, char *iobuf, unsigned int l_iobuf, void *ctx);
void roof_delete(roof_ctx_t
*pContext);
int roof_open_ctrl(roof_ctx_t
*pContext, const char *host, unsigned int port);
int roof_open_ctrl2(roof_ctx_t
*pContext, const char *host, unsigned int port, unsigned int timeout);
int roof_open_ctrl3(roof_ctx_t
*pContext,
const
char
*host,
unsigned
int
port, unsigned int timeout,
const char **banner);
int roof_close_ctrl(roof_ctx_t
*pContext);
int roof_get_reply(roof_ctx_t
*pContext, const char **reply);
int roof_login(roof_ctx_t
*pContext, const char *login, const char *passwd, const char *account);
int roof_login2(roof_ctx_t *pContext, const
char *login, const char *passwd, const char *account, const char
**banner);
int roof_type(roof_ctx_t
*pContext, unsigned char type, unsigned char form);
int roof_rm(roof_ctx_t
*pContext, const char *filename);
int roof_rmdir(roof_ctx_t
*pContext, const char *dir_name);
int roof_mkdir(roof_ctx_t
*pContext, const char *dir_name);
int roof_mv(roof_ctx_t
*pContext, const char *src, const char *dst);
int roof_syst(roof_ctx_t
*pContext, const char **syst);
int roof_cwd(roof_ctx_t
*pContext, const char *dir_name);
int roof_cdup(roof_ctx_t
*pContext);
int roof_pwd(roof_ctx_t
*pContext, const char **dir_name);
int roof_list(roof_ctx_t
*pContext, const char *dir_name, int (*write_cbk)(roof_ctx_t *ctx,
const char *buf, unsigned int lbuf));
int roof_nlst(roof_ctx_t
*pContext, const char *dir_name, int (*write_cbk)(roof_ctx_t *ctx,
const char *buf, unsigned int lbuf));
int roof_retr(roof_ctx_t
*pContext, const char *src, const char *dst, unsigned int *nb_bytes,
unsigned char type, unsigned char form);
int roof_retr2(roof_ctx_t
*pContext, const char *src, const char *dst, unsigned long long
*nb_bytes,
unsigned char type, unsigned char form, unsigned int progress, int
(*progress_cbk)(roof_ctx_t *ctx, unsigned int progress));
int roof_retr3(roof_ctx_t
*pContext, const char *src, int (*receive)(roof_ctx_t *ctx, char *data,
unsigned int nb, void *private), void *private, unsigned long long
*nb_bytes, unsigned char type, unsigned char form, unsigned int
progress, int (*progress_cbk)(roof_ctx_t *ctx, unsigned int progress));
int roof_stor(roof_ctx_t
*pContext, const char *src, const char *dst, unsigned int *nb_bytes,
unsigned char type, unsigned char form);
int roof_stor2(roof_ctx_t
*pContext, const char *src, const char *dst, unsigned long long
*nb_bytes,
unsigned char type, unsigned char form, unsigned int progress, int
(*progress_cbk)(roof_ctx_t *ctx, unsigned int progress));
int roof_stor3(roof_ctx_t *pContext, int
(*snd)(roof_ctx_t *ctx, int fd, unsigned long long off, void *priv),
const char *dst, void *priv, unsigned long long *nb_bytes, unsigned
char type, unsigned char form, unsigned int progress, int
(*progress_cbk)(roof_ctx_t *ctx, unsigned int progress));
void roof_set_debug_level(roof_ctx_t
*pContext,
int
level,
FILE
*out);
int roof_get_debug_level(roof_ctx_t
*pContext);
int roof_help(roof_ctx_t
*pContext, const char **hlp, const char *format, ...);
int roof_site(roof_ctx_t
*pContext, const char **rsp, const char *format, ...);
int roof_set_data_mode(roof_ctx_t
*pContext, int mode);
int roof_set_routing(roof_ctx_t
*pContext, int routing);
int roof_noop(roof_ctx_t
*pContext);
int roof_quit(roof_ctx_t *pContext);
roof_new
The function roof_new() gets a
context in the ROOF API. It is passed the timeout timeout_ms in
milliseconds to wait for messages
from the server (0 specifies infinite wait), an Input/Output
buffer iobuf, the
length l_iobuf of
this buffer and a pointer on an arbitrary user context. If the
parameter iobuf is
NULL, the buffer is allocated internally by the service with a size of l_iobuf if not 0 or with a
default size. The returned value is a pointer on the
context identifier of type roof_ctx_t.
The
context
identifier
is
passed
to
the
other functions of the API. The
type of this context is:
typedef
struct
{
void
*ctx;
//
User
context
}
roof_ctx_t;
The field ctx
is filled with the value of the last parameter passed to roof_new().
roof_delete
The function roof_delete()
is passed a pointer on a context identifier pContext to
deallocate. It is typically called when the application does not need
to use the ROOF API any more.
roof_open_ctrl
The function roof_open_ctrl()
opens the control connection with a remote host on the TCP port. The host
parameter is a string containing either the DNS name or the IP address
in dotted notation of the remote host. Normally a FTP server
listens on TCP port 21 so the caller can pass the constant
ROOF_DEF_PORT. The return value is a socket descriptor on the
control connection. This socket descriptor is typically used in a call
to select(3) to get
spontaneous messages from the server. Typically, those messages can be
timeout notifications. It is important for the user to catch
those spontaneous messages because a disconnected server will make the
following function calls to the ROOF API fail as the connection is no
more valid. In this situation, the user should call roof_open_ctrl() again
to set up a new control connection and roof_login()
to open a user session. To get the messages from the server, the user
is supposed to call roof_get_reply(). If the
remote server is out of service, this function may last after
several minutes to report a connection
error depending on the configuration of
the underlying stack. To have a better control on the connection time,
it is advised to use roof_open_ctrl2().
roof_open_ctrl2
The function roof_open_ctrl2()
behaves the same as roof_open_ctrl() except that it
is passed the additional timeout
argument which specifies the maximum time
in milliseconds to wait for a server’s connection response.
If set to 0, this function has exactly the same behaviour as roof_open_ctrl()
since the timeout defaults to the unspecified value of the underlying
stack which may be several minutes on some systems.
roof_open_ctrl3
The function roof_open_ctrl3()
behaves
the
same
as
roof_open_ctrl2()
but it is passed an additional argument banner to receive the welcome
banner sent by the server upon the control connection establishment. If
the banner is not needed, the parameter can be set to NULL. The banner
is a standard FTP reply compliant with the format of the
strings received through roof_get_reply().
Be
aware
of
the
fact
that
as the returned pointer is an address in the
internal I/O buffer, the referenced data are no longer valid after a
call to any other ROOF
service. The caller is supposed to copy the data somewhere else if
necessary.
roof_close_ctrl
The function roof_close_ctrl()
closes
the
control
connection
with
the
remote
host.
It is the counter part of roof_open_ctrl().
It is typically called before
ending a
session with the server. It is not
mandatory if the
user calls roof_delete()
to deallocate the session’s context.
roof_get_reply
The function roof_get_reply()
is called to receive a spontaneous message on the
control
connection from the server. It is typically called after a select(3)
has indicated that data are available on the control socket. The
function is passed the address of a pointer. If OK,
the
pointer will be assigned with an address in the I/O buffer of the
context pointing on the message sent by the server. The format of the
message is compliant with RFC 959. Its format is a number of
three digits followed by an arbitrary string. For
exampe,
if the server closes the connection because of an internal timeout, it
may send a message like the following:
421
No
Transfer
Timeout
(45
seconds):
closing
control
connection.
The signification of the beginning digits in the message is described
in RFC 959. The function will
block
at most the timeout in milliseconds passed to roof_new().
Of
course,
if
the
value
passed
was
0, the function will wait
indefinitely if the server does not send any message. Be
aware of
the fact that as the returned pointer is an address in the I/O buffer,
the data it references are no more valid after a call to any other ROOF
service. The caller is supposed to copy the data somewhere else if
necessary.
roof_login
The function roof_login()
opens a user session onto the remote host. It is passed the
login name login,
the
password
passwd
and
the account information account.
If
the
remote
host
accepts
to
open
sessions without login name,
password or account information, the corresponding
parameters can be set to NULL. Typically, the account information are
not needed by most of the FTP servers. This function is typically
called right after roof_open_ctrl().
roof_login2
The function roof_login2()
behaves the same as roof_login()
but it is passed an additional argument banner to receive the welcome
banner sent by the server upon the connection.
If the banner is not needed, the
parameter can be set to NULL. The banner is a standard FTP reply
compliant with the format of the strings received through roof_get_reply(). Be aware of
the fact that as the returned pointer is an address in the internal I/O
buffer, the referenced data are no longer valid after a call to any
other ROOF service. The caller
is supposed to copy the data somewhere else if necessary.
roof_type
The function roof_type()
sets
the type of data to be transfered. The
type
parameter can be either the character ’A’ for
ASCII or ’E’ for EBCDIC or ’I’ for Image
(binary format) or ’L’ for local byte size. Types
’A’ and ’E’ may come along with form set to
’N’ for non print, ’T’ for
telnet format effector or ’C’ for carriage
control (ASA). Type ’I’ is standalone and so, does
not accept any code. Type ’L’ must come along with
form set to the
size of the
bytes. This
value must be a numerical value from 0 to
255.
If not used, form
must be set to 0. When type
and form are set to
0,
the function behaves as if it received ’I’ for type.
roof_rm
The function roof_rm()
removes a file on the remote server. It is passed the file name to
remove in the parameter filename.
roof_rmdir
The function roof_rmdir()
removes a directory on the remote server. It is
passed
the directory name to remove in
the parameter dir_name.
On
most
server
this
command
will
fail
if the target directory is not
empty.
roof_mkdir
The function roof_mkdir()
makes a new directory on the remote server. It is passed the
directory name to create in the parameter dir_name.
roof_mv
The
function roof_mv()
renames a file or directory. The source name is passed in src and the
destination in dst.
roof_syst
The
function roof_syst()
asks the server for its type. Most of the time, the operating system
the server is running on will be returned
into syst.
This pointer is assigned with the address in the context’s I/O
buffer of the string sent back by the server as response. The
format of this string is
described in RFC 959
(SYST command). For example, on some system, the returned string is:
215
UNIX
Type:
L8
(Linux)
The type of the system is the first word right after the first three
digits. As the returned address points into the I/O buffer,
the
pointed data are no more available after a new call
to the
library. A copy must be done by the caller if necessary.
roof_cwd
The function roof_cwd()
changes the current working directory on
the server to the pathname dir_name.
roof_cdup
The
function roof_cdup()
changes the current working directory to the upper one on the server.
If the target server has not a Linux tree-like file system, this
command may fail.
roof_pwd
The function roof_pwd()
returns the name of the current working
directory on the server. The
parameter dir_name
is assigned with the address of the response sent by the server. The
format of this string begins with three digits and then it is followed
by the name of the directory. For
example, the
response can be something like:
257
"/home/foobar"
is
current
directory.
As the returned address points into the I/O buffer, the
pointed
data are no more available after a new call to the library. A copy must
be done by the caller if necessary.
roof_list
The
function roof_list()
displays
the
detailed
list
of
files
in
the
remote directory named dir_name.
If
dir_name
is NULL, the function lists the
remote
current directory (the one
returned by roof_pwd()).
The meaning of "detailed
list"
depends on the remote server’s behaviour. On Linux systems,
this is equivalent to the result of "ls -la" shell call. That is to
say the names of the files are displayed
along with
the access rights, access times, sizes... The display is done through
an invocation of the call back write_cbk
which is passed the ROOF
context ctx, a pointer
on the buffer containing the list of files and the length of the data
in the buffer. The callback may be invoked several times depending on
the amount of data to return and the size of the
I/O buffer
set up at context allocation time with roof_new().
The
callback must return the number of "written" bytes which must be equal
to the parameter lbuf
to be considered successful
and any other value if error. In the
latter situation, errno
must be set accordingly. Be aware of the fact that the buffer passed to
the callback is not NUL terminated: the number of bytes in
the
buffer is lbuf.
roof_nlst
The function roof_nlst() displays
the
short
list
of
files
in
the
remote
directory named dir_name.
If
dir_name
is NULL, the function lists the
remote
current directory (the one
returned by roof_pwd()).
The
meaning
of
"short
list"
depends
on
the remote server’s
behaviour. On Linux systems, this is equivalent to the result of "ls
-a" shell call. That is to say only the
names of the
files are displayed. The display is done through an invocation of the
call back write_cbk
which is passed an arbitary pointer ctx
supposed to contain some user information to
set
up the display, a pointer on the buffer containing the list
of
files and the length of the data in the buffer. The callback may be
invoked several times depending on the amount of data to
return
and the size of the I/O buffer set up at context
allocation
time with roof_new().
The
callback
must
return
the
number
of
"written" bytes which must be
equal to the parameter lbuf
to be considered successful and any other
value if error. In the latter situation, errno
must be set accordingly. Be aware of the fact that the buffer passed to
the callback is not NUL terminated: the number of
bytes in
the buffer is lbuf.
roof_retr
The function roof_retr()
uploads the remote file src
into the local file named dst.
If
dst
is NULL, the basename of the source file is used for the name of the
destination file (i.e. the source file is transfered in the current
local directory). The number of
read bytes is
returned in nb_bytes
parameter. The parameters type
and form
are respectively the transfer type and format: cf. roof_type()
service.
roof_retr2
The function roof_retr2()
behaves the same as roof_retr()
but it takes two additionnal arguments to make the library invoke
the progress_cbk
callback
at
most
every
progress
bytes transfered. This can be useful for graphical applications to
animate a progress bar. This function can also handle large files (more
than 2 GB) as the parameter nb_bytes
is an "unsigned long long".
roof_retr3
The function roof_retr3() behaves the same as roof_retr2() but
instead of a destination file, the content of the
file is passed to the receive callback. The
callback is passed as parameters the roof context ctx, a buffer data of bytes from the
source file, the number of bytes nb in the buffer and an
arbitrary context private
passed
by
the
caller
through
the
private
parameter. receive
is called as many
times as it is necessary to report the number of bytes from the
source file. receive
must return the number of handled bytes. If the return value is not the
same as nb then it is
considered as an error.
roof_stor
The
function roof_stor()
downloads the local file src
into the remote file named dst.
If
dst
is NULL, the name of the source file is used for the name of
the
destination file. The number of read bytes is returned in nb_bytes
parameter. The parameters type
and form
are respectively the transfer type and format:
cf. roof_type()
service.
roof_stor2
The
function roof_stor2()
behaves the same as roof_stor()
but it takes two additionnal
arguments to make the library invoke the progress_cbk
callback at most every progress
bytes transfered. This can be useful for graphical
applications to animate a progress bar. This function can also
handle large files (more than 2 GB) as the parameter nb_bytes is an "unsigned
long long".
roof_stor3
The function roof_stor3() behaves the same as roof_stor2() but instead
of a source file, the callback snd is invoked. The
callback is passed as parameters the roof context ctx, the file
descriptor fd of the data connection where to put the source data, the
offset off in the source stream and an arbitrary context
priv passed by the caller through the priv parameter.
snd is called as many times as it is necessary to get the number of
bytes from the source stream. It must return the
number of handled bytes (0 means EOF). At each call,
off is incremented by the number of bytes returned by the previous
call. So, it is equal to 0 at the first call. snd returns a
negative errno in case of error.
roof_set_debug_level
The function roof_set_debug_level()
sets the debug level to level.
It
is
passed
an
output
stream
out
where to redirect the debug messages. If NULL, it defaults to the
standard output error (stderr). The accepted values
are positive values. 0 means "no debug".
This service is very useful to narrow down communication problems with
the server as all the responses coming from the server are displayed.
The higher the value of the debug level, the more debug information are
displayed.
roof_get_debug_level
The function roof_get_debug_level()
returns the current value of the debug level.
roof_help
The function roof_help()
sends
a
HELP
command
to
the
remote
server and make
the answer pointed by hlp.
The
format
is
"printf-like".
It
may
be
NULL to request a global help
or it describes the command for which the help is requested.
roof_site
The function roof_site()
sends
a
SITE
(i.e.
custom)
command
to
the remote server and make the
answer pointed by rsp.
The
format
is
"printf-like".
It
may
be
NULL or it describes the command
to launch.
roof_set_data_mode
The function roof_set_data_mode()
sets the data connection mode to ROOF_PASSIVE
for passive mode or to ROOF_ACTIVE
for active mode. In passive mode, the data
connection is done by the client (default behaviour). In active
mode, the data connection is done by the server. The passive mode is
advised when firewalls are on the data paths. This service is
typically called before the services involving
a data connection: roof_list(),
roof_nlst(),
roof_retr(),
roof_retr2(),
roof_stor()...
roof_set_routing
The function roof_set_routing() is passed ROOF_GATEWAY to enable the routing
of the network packets through a gateway (default behaviour) and passed
ROOF_NO_GATEWAY to
disable the routing of the network packets
through a gateway. The latter is typically used to avoid the
redirection of the network packets to a default destination when the
target server is not directly connected to the local host (i.e. the
routing table would specify a default gateway address to redirect the
network packets).
roof_noop
The function roof_noop() does not trigger any
action from the remote host except making it send an acknowlegment
message. It may be useful to maintain an activity on the connection to
avoid a disconnection timeout. It may also be used to check
the connection state before any other action.
roof_quit
The function roof_quit() properly closes the connection with the
server. It is typically called before roof_close_ctrl()
or roof_delete().
Return value
The function roof_new()
returns a pointer on the context if OK and NULL on error.
The function roof_open_ctrl()
and roof_open_ctrl2() return the
socket descriptor of the opened control connection or -1 if
error.
The functions roof_close_ctrl(),
roof_get_reply(),
roof_login(),
roof_type(),
roof_rm(),
roof_rmdir(),
roof_mkdir(),
roof_mv(),
roof_syst(),
roof_cwd(),
roof_quit(), roof_cdup(),
roof_pwd(),
roof_list(),
roof_nlst(),
roof_retr(),
roof_retr2(),
roof_retr3(),
roof_stor(),
roof_stor2(),
roof_stor3(),
roof_help(),
roof_site(),
roof_set_data_mode(),
roof_noop()
and roof_set_routing()
return 0 if
OK
and -1 on error.
The function roof_set_debug_level()
returns the previous debug level (>= 0) and -1 on error.
The function roof_get_debug_level()
returns the debug level if OK and -1 on error.
Errors
EIO Input/Output error.
ENOSPC No more free contexts or
I/O buffer too short to receives messages from the server.
EINVAL Missing, invalid or
unexpected parameter.
ETIMEDOUT Timeout during the
communication with the server.
EBUSY Trying to open a control
connection in a session where it is already opened or not closed
properly.
EOPNOTSUPP Command not
supported on local host.
EACCES Trying to launch a
remote command in disconnected state.
EOVERFLOW Size of file too big
for the interface.
EINPROGRESS The connection
could not be established before specified timeout.
EALREADY The connection could
not be established before specified timeout.
Example
The following example shows a
session with a
remote server to display the content of the home directory of the user
"octopus":
#include
<roof.h>
[...]
// Callback to display directory content
int
display_dir(roof_ctx_t *pCtx, const char *buf, unsigned int lbuf)
{
int out_fd = (int)(pCtx->ctx);
int rc;
rc
=
write(out_fd,
buf,
lbuf);
assert(lbuf
==
(unsigned)rc);
//
Return
OK
to
the
library
(number
of "written" bytes)
return
lbuf;
}
[...]
int
ctrl;
roof_ctx_t *pCtx;
int
rc;
char *p;
// Allocate a ROOF context with default values for the I/O buffer
// and 10 seconds for the timeout. The user data is set with
// the output file descriptor
pCtx = roof_new(10000, NULL, 0, (void *)1);
assert(NULL != pCtx);
// Open
the control connection with the server "foobar" on the default port.
ctrl = roof_open_ctrl(pCtx, "foobar",
ROOF_DEF_PORT);
assert(ctrl >= 0);
// Log as user "octopus" with the password "super_vilain"
rc = roof_login(pCtx, "octopus",
"super_vilain", NULL);
assert(0 == rc);
// Display the current working directory on the remote side
rc = roof_pwd(pCtx, &p);
assert(0 == rc);
printf("Current directory is ’%s’0, p);
// Display content of current directory on standard output (fd = 1)
rc = roof_list(pCtx, NULL, display_dir);
assert(0 == rc);
// Close the control connection
rc = roof_close_ctrl(pCtx);
assert(0 == rc);
// Deallocate the session’s context
roof_delete(pCtx);
ftpfs
ftpfs is a file system based on
FTP: it mounts a
remote file system using the FTP protocol. Internally, ftpfs is based
on FUSE
and roof's API. The mounted file system is read only.
Usage
ftpfs [-V -h] [-d level] [-l
log] [-t
ms] [-s
size] [-c
ms] [-I]
[-o owner] [-g group] mpath
host
login
[ passwd
[ account
] ]
ftpfs mounts the target host
on the mount point (directory)
mpath.
The connection to the target host uses
the
login name login,
the password passwd
and eventually the account
information account
(the latter is normally never used). The password
defaults to the login name and the account
defaults
to "/".
Options
-V
Display the version of the
program
-h
Display the help of the
program
-d level
Set
the debug mode to level. Debug messages
are redirected to the log file if '-l' has been specified or stderr by
default. The higher the level is, the more traces you get. The value 0
deactivates the debug mode.
-l log
Activates logging into the
file log.
-t ms
Set the data transfer timeout for the
interactions with the target host to ms
milliseconds. The value defaults to 5000 (5 seconds).
-s
size
Set the size in bytes of the
internal
I/O buffer. The greater it is, the faster the underlying FTP transfers
are supposed to be. The default size of the I/O buffer is 4 KB.
-c ms
Set the connection timeout for the
interactions with the target host to ms milliseconds.
The value defaults to the unspecified
underlying stack one.
-I
Use internal default connection
parameters for login/password
-o owner
Specify the owner of the remote files.
Ignored if it is a local connection. It defaults to the identifier of
the user who mounted the file system.
-g group
Specify the group of
the remote files. Ignored if it is a local connection. It defaults to
the group of the user specified by -o option (if any) or the group of
the user who mounted the file system.
Example
The following example mounts the remote host
’wales’ with the login name ’josey’ and
password ’alone’ on the local directory ’/mnt’.
Then ’ls -l’ is invoked to list the content
of ’/mnt’ which is the content of the home directory
of ’josey’ on the remote machine ’wales’.
’mount’ command is launched to display the list of mounted
file systems. The
remote host is unmounted with the ’umount’ command:
$
sudo ftpfs /mnt wales
josey alone
$ cd /mnt
$ ls -l /mnt
total 0
-r--r--r-- 1 root root 63328 1970-01-01 01:00 garden.sh3d
dr-xr-xr-x 1 root root 4096 1970-01-01 01:00 Applications
-r--r--r-- 1 root root 198 1970-01-01 01:00
backup.sh
dr-xr-xr-x 1 root root 4096 1970-01-01 01:00 DEVS
$ cd /
$ mount
[...]
ftpfs on /mnt type fuse.ftpfs
(rw,nosuid,nodev,default_permissions,allow_other)
$ sudo umount /mnt
$ ls -l /mnt
total 0
$
ftping
ftping is a FTP client which tries to open a control connection
to a remote FTP server. It is useful to check if a remote FTP server is
up and ready to accept connections.
Usage
ftping [-p port] [-d debug_level] [-t timeout] [-h V
n]
[
hostname
]
Options
-p port
--port=port
Specify the TCP port of the remote FTP
server (default is 21).
-d debug_level
--debug=debug_level
Set the debug level to
debug_level. The value is a positive integer value. The bigger
the value, the more debug traces will appear (0
unsets the debug mode).
This is useful to catch the error messages from the server when a
command fails.
-t timeout
--timeout=timeout
Specify the maximum timeout in
milliseconds to wait for an answer from the remote FTP server. By
default, it is an internal value coming from the IP stack.
-h
--help
Display the help of the command (subset
of this man page).
-V
--version
Display the version of the software.
-n
--nogw
Avoid the sending of the connection
tries through a gateway
Examples
The following example shows a FTP connection to the default port 21 on
a host called 'remote'. The FTP server is up as the return code is 0.
$ ftping remote
$ echo $?
0
$
The following example shows a FTP connection to the port
2000 on a host called 'remote'. The remote server is not up on this
port as the return code is not 0 after a maximum wait of 3 seconds
(3000 ms).
$ ftping -t 3000 -p 2000 remote
$ echo $?
1
$
About the
author
The author is an engineer in computer sciences located in France. He is
glad to graciously offer this utility under the GPL open
source
license. He can be contacted through this page or
you can have a look at his WEB
home page.
Related links