aboutsummaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
author√Čric Bischoff <eric@bureau-cornavin.com>2010-08-27 11:11:08 +0200
committerAndreas Schneider <asn@cynapses.org>2010-08-27 11:11:08 +0200
commitba9f5b7d95b072cc2c3208e49704a51c78ac4c2c (patch)
tree2303ab7584411c708aac3d83c03ab95be676bfe2 /doc
parent11a5383604c66a4553a202184d78df2328450521 (diff)
downloadlibssh-ba9f5b7d95b072cc2c3208e49704a51c78ac4c2c.tar.gz
libssh-ba9f5b7d95b072cc2c3208e49704a51c78ac4c2c.tar.xz
libssh-ba9f5b7d95b072cc2c3208e49704a51c78ac4c2c.zip
doc: Improved the tutorial.
Diffstat (limited to 'doc')
-rw-r--r--doc/introduction.dox6
-rw-r--r--doc/scp.dox7
-rw-r--r--doc/sftp.dox317
-rw-r--r--doc/tbd.dox27
4 files changed, 350 insertions, 7 deletions
diff --git a/doc/introduction.dox b/doc/introduction.dox
index 53878248..9026a9d1 100644
--- a/doc/introduction.dox
+++ b/doc/introduction.dox
@@ -14,6 +14,10 @@ libssh is a Free Software / Open Source project. The libssh library
is distributed under LGPL license. The libssh project has nothing to do with
"libssh2", which is a completly different and independant project.
+libssh can run on top of either libgcrypt (http://directory.fsf.org/project/libgcrypt/)
+or libcrypto (http://www.openssl.org/docs/crypto/crypto.html), two general-purpose
+cryptographic libraries.
+
This tutorial concentrates for its main part on the "client" side of libssh.
To learn how to accept incoming SSH connexions (how to write a SSH server),
you'll have to jump to the end of this document.
@@ -35,6 +39,8 @@ Table of contents:
@subpage sftp
+@subpage scp
+
@subpage tbd
*/
diff --git a/doc/scp.dox b/doc/scp.dox
new file mode 100644
index 00000000..811b51fd
--- /dev/null
+++ b/doc/scp.dox
@@ -0,0 +1,7 @@
+/**
+@page scp Chapter 6: The SCP subsystem
+@section scp_subsystem The SCP subsystem
+
+*** To be written ***
+
+*/
diff --git a/doc/sftp.dox b/doc/sftp.dox
index 1aca34de..6f9bcde7 100644
--- a/doc/sftp.dox
+++ b/doc/sftp.dox
@@ -25,6 +25,9 @@ that you can do with local files:
- create symbolic links
- get information about mounted filesystems.
+The current implemented version of the SFTP protocol is version 3. All functions
+aren't implemented yet, but the most important are.
+
@subsection sftp_section Opening and closing a SFTP session
@@ -35,8 +38,7 @@ The function sftp_new() creates a new SFTP session. The function sftp_init()
initializes it. The function sftp_free() deletes it.
As you see, all the SFTP-related functions start with the "sftp_" prefix
-instead of the usual "ssh_" prefix. In case of a problem, you use
-sftp_get_error() instead of ssh_get_error() to get the English error message.
+instead of the usual "ssh_" prefix.
The example below shows how to use these functions:
@@ -71,18 +73,323 @@ int sftp_helloworld(ssh_session session)
@endcode
+@subsection sftp_errors Analyzing SFTP errors
+
+In case of a problem, the function sftp_get_error() returns a SFTP-specific
+error number, in addition to the regular SSH error number returned by
+ssh_get_error_number().
+
+Possible errors are:
+ - SSH_FX_OK: no error
+ - SSH_FX_EOF: end-of-file encountered
+ - SSH_FX_NO_SUCH_FILE: file does not exist
+ - SSH_FX_PERMISSION_DENIED: permission denied
+ - SSH_FX_FAILURE: generic failure
+ - SSH_FX_BAD_MESSAGE: garbage received from server
+ - SSH_FX_NO_CONNECTION: no connection has been set up
+ - SSH_FX_CONNECTION_LOST: there was a connection, but we lost it
+ - SSH_FX_OP_UNSUPPORTED: operation not supported by libssh yet
+ - SSH_FX_INVALID_HANDLE: invalid file handle
+ - SSH_FX_NO_SUCH_PATH: no such file or directory path exists
+ - SSH_FX_FILE_ALREADY_EXISTS: an attempt to create an already existing file or directory has been made
+ - SSH_FX_WRITE_PROTECT: write-protected filesystem
+ - SSH_FX_NO_MEDIA: no media was in remote drive
+
+
@subsection sftp_mkdir Creating a directory
-*** To be written ***
+The function sftp_mkdir() tahes the "SFTP session" we juste created as
+its first argument. It also needs the name of the file to create, and the
+desired permissions. The permissions are the same as for the usual mkdir()
+function. To get a comprehensive list of the available permissions, use the
+"man 2 stat" command. The desired permissions are combined with the remote
+user's mask to determine the effective permissions.
+
+The code below creates a directory named "helloworld" in the current directory that
+can be read and written only by its owner:
+
+@code
+#include <libssh/sftp.h>
+#include <sys/stat.h>
+
+int sftp_helloworld(ssh_session session, sftp_session sftp)
+{
+ int rc;
+
+ rc = sftp_mkdir(sftp, "helloworld", S_IRWXU);
+ if (rc != SSH_OK)
+ {
+ if (sftp_get_error(sftp) != SSH_FX_FILE_ALREADY_EXISTS)
+ {
+ fprintf(stderr, "Can't create directory: %s\n", ssh_get_error(session));
+ return rc;
+ }
+ }
+
+ ...
+
+ return SSH_OK;
+}
+@endcode
+
+Unlike its equivalent in the SCP subsystem, this function does NOT change the
+current directory to the newly created subdirectory.
@subsection sftp_write Copying a file to the remote computer
-*** To be written ***
+You handle the contents of a remote file just like you would do with a
+local file: you open the file in a given mode, move the file pointer in it,
+read or write data, and close the file.
+
+The sftp_open() function is very similar to the regular open() function,
+excepted that it returns a file handle of type sftp_file. This file handle
+is then used by the other file manipulation functions and remains valid
+until you close the remote file with sftp_close().
+
+The example below creates a new file named "helloworld.txt" in the
+newly created "helloworld" directory. If the file already exists, it will
+be truncated. It then writes the famous "Hello, World!" sentence to the
+file, followed by a new line character. Finally, the file is closed:
+
+@code
+#include <libssh/sftp.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+int sftp_helloworld(ssh_session session, sftp_session sftp)
+{
+ int access_type = O_WRONLY | O_CREAT | O_TRUNC;
+ sftp_file file;
+ const char *helloworld = "Hello, World!\n";
+ int length = strlen(helloworld);
+ int rc, nwritten;
+
+ ...
+
+ file = sftp_open(sftp, "helloworld/helloworld.txt", access_type, S_IRWXU);
+ if (file == NULL)
+ {
+ fprintf(stderr, "Can't open file for writing: %s\n", ssh_get_error(session));
+ return SSH_ERROR;
+ }
+
+ nwritten = sftp_write(file, helloworld, length);
+ if (nwritten != length)
+ {
+ fprintf(stderr, "Can't write data to file: %s\n", ssh_get_error(session));
+ sftp_close(file);
+ return SSH_ERROR;
+ }
+
+ rc = sftp_close(file);
+ if (rc != SSH_OK)
+ {
+ fprintf(stderr, "Can't close the written file: %s\n", ssh_get_error(session));
+ return rc;
+ }
+
+ return SSH_OK;
+}
+@endcode
@subsection sftp_read Reading a file from the remote computer
-*** To be written ***
+The nice thing with reading a file over the network through SFTP is that it
+can be done both in a synchronous way or an asynchronous way. If you read the file
+asynchronously, your program can do something else while it waits for the
+results to come.
+
+Synchronous read is done with sftp_read().
+
+The following example prints the contents of remote file "/etc/profile". For
+each 1024 bytes of information read, it waits until the end of the read operation:
+
+@code
+int sftp_read_sync(ssh_session session, sftp_session sftp)
+{
+ int access_type;
+ sftp_file file;
+ char buffer[1024];
+ int nbytes, rc;
+
+ access_type = O_RDONLY;
+ file = sftp_open(sftp, "/etc/profile", access_type, 0);
+ if (file == NULL)
+ {
+ fprintf(stderr, "Can't open file for reading: %s\n", ssh_get_error(session));
+ return SSH_ERROR;
+ }
+
+ nbytes = sftp_read(file, buffer, sizeof(buffer));
+ while (nbytes > 0)
+ {
+ if (write(1, buffer, nbytes) != nbytes)
+ {
+ sftp_close(file);
+ return SSH_ERROR;
+ }
+ nbytes = sftp_read(file, buffer, sizeof(buffer));
+ }
+
+ if (nbytes < 0)
+ {
+ fprintf(stderr, "Error while reading file: %s\n", ssh_get_error(session));
+ sftp_close(file);
+ return SSH_ERROR;
+ }
+
+ rc = sftp_close(file);
+ if (rc != SSH_OK)
+ {
+ fprintf(stderr, "Can't close the read file: %s\n", ssh_get_error(session));
+ return rc;
+ }
+
+ return SSH_OK;
+}
+@endcode
+
+Asynchronous read is done in two steps, first sftp_async_read_begin(), which
+returns a "request handle", and then sftp_async_read(), which uses that request handle.
+If the file has been opened in nonblocking mode, then sftp_async_read()
+might return SSH_AGAIN, which means that the request hasn't completed yet
+and that the function should be called again later on. Otherwise,
+sftp_async_read() waits for the data to come. To open a file in nonblocking mode,
+call sftp_file_set_nonblocking() right after you opened it. Default is blocking mode.
+
+The example below reads a very big file in asynchronous, nonblocking, mode. Each
+time the data are not ready yet, a counter is incrementer.
+
+@code
+int sftp_read_async(ssh_session session, sftp_session sftp)
+{
+ int access_type;
+ sftp_file file;
+ char buffer[1024];
+ int async_request;
+ int nbytes;
+ long counter;
+ int rc;
+
+ access_type = O_RDONLY;
+ file = sftp_open(sftp, "some_very_big_file", access_type, 0);
+ if (file == NULL)
+ {
+ fprintf(stderr, "Can't open file for reading: %s\n", ssh_get_error(session));
+ return SSH_ERROR;
+ }
+ sftp_file_set_nonblocking(file);
+
+ async_request = sftp_async_read_begin(file, sizeof(buffer));
+ counter = 0L;
+ usleep(10000);
+ if (async_request >= 0)
+ nbytes = sftp_async_read(file, buffer, sizeof(buffer), async_request);
+ else nbytes = -1;
+ while (nbytes > 0 || nbytes == SSH_AGAIN)
+ {
+ if (nbytes > 0)
+ {
+ write(1, buffer, nbytes);
+ async_request = sftp_async_read_begin(file, sizeof(buffer));
+ }
+ else counter++;
+ usleep(10000);
+ if (async_request >= 0)
+ nbytes = sftp_async_read(file, buffer, sizeof(buffer), async_request);
+ else nbytes = -1;
+ }
+
+ if (nbytes < 0)
+ {
+ fprintf(stderr, "Error while reading file: %s\n", ssh_get_error(session));
+ sftp_close(file);
+ return SSH_ERROR;
+ }
+
+ printf("The counter has reached value: %ld\n", counter);
+
+ rc = sftp_close(file);
+ if (rc != SSH_OK)
+ {
+ fprintf(stderr, "Can't close the read file: %s\n", ssh_get_error(session));
+ return rc;
+ }
+
+ return SSH_OK;
+}
+@endcode
+
+@subsection sftp_ls Listing the contents of a directory
+
+The functions sftp_opendir(), sftp_readdir(), sftp_dir_eof(),
+and sftp_closedir() enable to list the contents of a directory.
+They use a new handle_type, "sftp_dir", which gives access to the
+directory being read.
+
+In addition, sftp_readdir() returns a "sftp_attributes" which is a pointer
+to a structure with informations about a directory entry:
+ - name: the name of the file or directory
+ - size: its size in bytes
+ - etc.
+
+sftp_readdir() might return NULL under two conditions:
+ - when the end of the directory has been met
+ - when an error occured
+
+To tell the difference, call sftp_dir_eof().
+
+The attributes must be freed with sftp_attributes_free() when no longer
+needed.
+
+The following example reads the contents of some remote directory:
+
+@code
+int sftp_list_dir(ssh_session session, sftp_session sftp)
+{
+ sftp_dir dir;
+ sftp_attributes attributes;
+ int rc;
+
+ dir = sftp_opendir(sftp, "/var/log");
+ if (!dir)
+ {
+ fprintf(stderr, "Directory not opened: %s\n", ssh_get_error(session));
+ return SSH_ERROR;
+ }
+
+ printf("Name Size Perms Owner\tGroup\n");
+
+ while ((attributes = sftp_readdir(sftp, dir)) != NULL)
+ {
+ printf("%-22s %10llu %.8o %s(%d)\t%s(%d)\n",
+ attributes->name,
+ (long long unsigned int) attributes->size,
+ attributes->permissions,
+ attributes->owner,
+ attributes->uid,
+ attributes->group,
+ attributes->gid);
+
+ sftp_attributes_free(attributes);
+ }
+
+ if (!sftp_dir_eof(dir))
+ {
+ fprintf(stderr, "Can't list directory: %s\n", ssh_get_error(session));
+ sftp_closedir(dir);
+ return SSH_ERROR;
+ }
+
+ rc = sftp_closedir(dir);
+ if (rc != SSH_OK)
+ {
+ fprintf(stderr, "Can't close directory: %s\n", ssh_get_error(session));
+ return rc;
+ }
+}
+@endcode
*/
diff --git a/doc/tbd.dox b/doc/tbd.dox
index ed4e8825..4ee5ab84 100644
--- a/doc/tbd.dox
+++ b/doc/tbd.dox
@@ -1,8 +1,31 @@
/**
@page tbd To be done
-@section scp_subsystem The SCP subsystem
+@section errors Handling the errors
+
+When some function returns an error code, it's always possible to get an
+english message describing the problem.
+
+The function ssh_get_error() returns a pointer to the static error buffer.
+
+ssh_error_code() returns the error code number : SSH_NO_ERROR,
+SSH_REQUEST_DENIED, SSH_INVALID_REQUEST, SSH_CONNECTION_LOST, SSH_FATAL,
+or SSH_INVALID_DATA. SSH_REQUEST_DENIED means the ssh server refused your
+request, but the situation is recoverable. The others mean something happened
+to the connection (some encryption problems, server problems, ...).
+SSH_INVALID_REQUEST means the library got some garbage from server, but
+might be recoverable. SSH_FATAL means the connection has an important
+problem and isn't probably recoverable.
+
+Most of time, the error returned are SSH_FATAL, but some functions
+(generaly the ssh_request_xxx ones) may fail because of server denying request.
+In these cases, SSH_REQUEST_DENIED is returned.
+
+ssh_get_error() and ssh_get_error_code() take a ssh_session as a parameter.
+That's for thread safety, error messages that can be attached to a session
+aren't static anymore. Any error that happens during ssh_options_xxx()
+or ssh_connect() (i.e., outside of any session) can be retrieved by
+giving NULL as argument.
-*** To be written ***
@section threads Working with threads