Blame examples/samplesftp.c

Packit Service 31306d
/*
Packit Service 31306d
Copyright 2003-2009 Aris Adamantiadis
Packit Service 31306d
Packit Service 31306d
This file is part of the SSH Library
Packit Service 31306d
Packit Service 31306d
You are free to copy this file, modify it in any way, consider it being public
Packit Service 31306d
domain. This does not apply to the rest of the library though, but it is
Packit Service 31306d
allowed to cut-and-paste working code from this file to any license of
Packit Service 31306d
program.
Packit Service 31306d
The goal is to show the API in action. It's not a reference on how terminal
Packit Service 31306d
clients must be made or how a client should react.
Packit Service 31306d
*/
Packit Service 31306d
Packit Service 31306d
#include "config.h"
Packit Service 31306d
Packit Service 31306d
#include <sys/statvfs.h>
Packit Service 31306d
#include <stdio.h>
Packit Service 31306d
#include <errno.h>
Packit Service 31306d
#include <fcntl.h>
Packit Service 31306d
#include <stdlib.h>
Packit Service 31306d
#include <string.h>
Packit Service 31306d
#ifdef HAVE_UNISTD_H
Packit Service 31306d
#include <unistd.h>
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
#include <libssh/libssh.h>
Packit Service 31306d
#include <libssh/sftp.h>
Packit Service 31306d
Packit Service 31306d
#include "examples_common.h"
Packit Service 31306d
#ifdef WITH_SFTP
Packit Service 31306d
Packit Service 31306d
static int verbosity;
Packit Service 31306d
static char *destination;
Packit Service 31306d
Packit Service 31306d
#define DATALEN 65536
Packit Service 31306d
Packit Service 31306d
static void do_sftp(ssh_session session) {
Packit Service 31306d
    sftp_session sftp = sftp_new(session);
Packit Service 31306d
    sftp_dir dir;
Packit Service 31306d
    sftp_attributes file;
Packit Service 31306d
    sftp_statvfs_t sftpstatvfs;
Packit Service 31306d
    struct statvfs sysstatvfs;
Packit Service 31306d
    sftp_file fichier;
Packit Service 31306d
    sftp_file to;
Packit Service 31306d
    int len = 1;
Packit Service 31306d
    unsigned int i;
Packit Service 31306d
    char data[DATALEN] = {0};
Packit Service 31306d
    char *lnk;
Packit Service 31306d
Packit Service 31306d
    unsigned int count;
Packit Service 31306d
Packit Service 31306d
    if (!sftp) {
Packit Service 31306d
        fprintf(stderr, "sftp error initialising channel: %s\n",
Packit Service 31306d
                ssh_get_error(session));
Packit Service 31306d
        goto end;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (sftp_init(sftp)) {
Packit Service 31306d
        fprintf(stderr, "error initialising sftp: %s\n",
Packit Service 31306d
                ssh_get_error(session));
Packit Service 31306d
        goto end;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    printf("Additional SFTP extensions provided by the server:\n");
Packit Service 31306d
    count = sftp_extensions_get_count(sftp);
Packit Service 31306d
    for (i = 0; i < count; i++) {
Packit Service 31306d
        printf("\t%s, version: %s\n",
Packit Service 31306d
               sftp_extensions_get_name(sftp, i),
Packit Service 31306d
               sftp_extensions_get_data(sftp, i));
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* test symlink and readlink */
Packit Service 31306d
    if (sftp_symlink(sftp, "/tmp/this_is_the_link",
Packit Service 31306d
                     "/tmp/sftp_symlink_test") < 0)
Packit Service 31306d
    {
Packit Service 31306d
        fprintf(stderr, "Could not create link (%s)\n",
Packit Service 31306d
                ssh_get_error(session));
Packit Service 31306d
        goto end;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    lnk = sftp_readlink(sftp, "/tmp/sftp_symlink_test");
Packit Service 31306d
    if (lnk == NULL) {
Packit Service 31306d
        fprintf(stderr, "Could not read link (%s)\n", ssh_get_error(session));
Packit Service 31306d
        goto end;
Packit Service 31306d
    }
Packit Service 31306d
    printf("readlink /tmp/sftp_symlink_test: %s\n", lnk);
Packit Service 31306d
Packit Service 31306d
    sftp_unlink(sftp, "/tmp/sftp_symlink_test");
Packit Service 31306d
Packit Service 31306d
    if (sftp_extension_supported(sftp, "statvfs@openssh.com", "2")) {
Packit Service 31306d
        sftpstatvfs = sftp_statvfs(sftp, "/tmp");
Packit Service 31306d
        if (sftpstatvfs == NULL) {
Packit Service 31306d
            fprintf(stderr, "statvfs failed (%s)\n", ssh_get_error(session));
Packit Service 31306d
            goto end;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        printf("sftp statvfs:\n"
Packit Service 31306d
               "\tfile system block size: %llu\n"
Packit Service 31306d
               "\tfundamental fs block size: %llu\n"
Packit Service 31306d
               "\tnumber of blocks (unit f_frsize): %llu\n"
Packit Service 31306d
               "\tfree blocks in file system: %llu\n"
Packit Service 31306d
               "\tfree blocks for non-root: %llu\n"
Packit Service 31306d
               "\ttotal file inodes: %llu\n"
Packit Service 31306d
               "\tfree file inodes: %llu\n"
Packit Service 31306d
               "\tfree file inodes for to non-root: %llu\n"
Packit Service 31306d
               "\tfile system id: %llu\n"
Packit Service 31306d
               "\tbit mask of f_flag values: %llu\n"
Packit Service 31306d
               "\tmaximum filename length: %llu\n",
Packit Service 31306d
               (unsigned long long) sftpstatvfs->f_bsize,
Packit Service 31306d
               (unsigned long long) sftpstatvfs->f_frsize,
Packit Service 31306d
               (unsigned long long) sftpstatvfs->f_blocks,
Packit Service 31306d
               (unsigned long long) sftpstatvfs->f_bfree,
Packit Service 31306d
               (unsigned long long) sftpstatvfs->f_bavail,
Packit Service 31306d
               (unsigned long long) sftpstatvfs->f_files,
Packit Service 31306d
               (unsigned long long) sftpstatvfs->f_ffree,
Packit Service 31306d
               (unsigned long long) sftpstatvfs->f_favail,
Packit Service 31306d
               (unsigned long long) sftpstatvfs->f_fsid,
Packit Service 31306d
               (unsigned long long) sftpstatvfs->f_flag,
Packit Service 31306d
               (unsigned long long) sftpstatvfs->f_namemax);
Packit Service 31306d
Packit Service 31306d
        sftp_statvfs_free(sftpstatvfs);
Packit Service 31306d
Packit Service 31306d
        if (statvfs("/tmp", &sysstatvfs) < 0) {
Packit Service 31306d
            fprintf(stderr, "statvfs failed (%s)\n", strerror(errno));
Packit Service 31306d
            goto end;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        printf("sys statvfs:\n"
Packit Service 31306d
               "\tfile system block size: %llu\n"
Packit Service 31306d
               "\tfundamental fs block size: %llu\n"
Packit Service 31306d
               "\tnumber of blocks (unit f_frsize): %llu\n"
Packit Service 31306d
               "\tfree blocks in file system: %llu\n"
Packit Service 31306d
               "\tfree blocks for non-root: %llu\n"
Packit Service 31306d
               "\ttotal file inodes: %llu\n"
Packit Service 31306d
               "\tfree file inodes: %llu\n"
Packit Service 31306d
               "\tfree file inodes for to non-root: %llu\n"
Packit Service 31306d
               "\tfile system id: %llu\n"
Packit Service 31306d
               "\tbit mask of f_flag values: %llu\n"
Packit Service 31306d
               "\tmaximum filename length: %llu\n",
Packit Service 31306d
               (unsigned long long) sysstatvfs.f_bsize,
Packit Service 31306d
               (unsigned long long) sysstatvfs.f_frsize,
Packit Service 31306d
               (unsigned long long) sysstatvfs.f_blocks,
Packit Service 31306d
               (unsigned long long) sysstatvfs.f_bfree,
Packit Service 31306d
               (unsigned long long) sysstatvfs.f_bavail,
Packit Service 31306d
               (unsigned long long) sysstatvfs.f_files,
Packit Service 31306d
               (unsigned long long) sysstatvfs.f_ffree,
Packit Service 31306d
               (unsigned long long) sysstatvfs.f_favail,
Packit Service 31306d
               (unsigned long long) sysstatvfs.f_fsid,
Packit Service 31306d
               (unsigned long long) sysstatvfs.f_flag,
Packit Service 31306d
               (unsigned long long) sysstatvfs.f_namemax);
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* the connection is made */
Packit Service 31306d
    /* opening a directory */
Packit Service 31306d
    dir = sftp_opendir(sftp, "./");
Packit Service 31306d
    if (!dir) {
Packit Service 31306d
        fprintf(stderr, "Directory not opened(%s)\n", ssh_get_error(session));
Packit Service 31306d
        goto end;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* reading the whole directory, file by file */
Packit Service 31306d
    while ((file = sftp_readdir(sftp, dir))) {
Packit Service 31306d
        fprintf(stderr, "%30s(%.8o) : %s(%.5d) %s(%.5d) : %.10llu bytes\n",
Packit Service 31306d
                file->name,
Packit Service 31306d
                file->permissions,
Packit Service 31306d
                file->owner,
Packit Service 31306d
                file->uid,
Packit Service 31306d
                file->group,
Packit Service 31306d
                file->gid,
Packit Service 31306d
                (long long unsigned int) file->size);
Packit Service 31306d
        sftp_attributes_free(file);
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* when file = NULL, an error has occured OR the directory listing is end of
Packit Service 31306d
     * file */
Packit Service 31306d
    if (!sftp_dir_eof(dir)) {
Packit Service 31306d
        fprintf(stderr, "Error: %s\n", ssh_get_error(session));
Packit Service 31306d
        goto end;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (sftp_closedir(dir)) {
Packit Service 31306d
        fprintf(stderr, "Error: %s\n", ssh_get_error(session));
Packit Service 31306d
        goto end;
Packit Service 31306d
    }
Packit Service 31306d
    /* this will open a file and copy it into your /home directory */
Packit Service 31306d
    /* the small buffer size was intended to stress the library. of course, you
Packit Service 31306d
     * can use a buffer till 20kbytes without problem */
Packit Service 31306d
Packit Service 31306d
    fichier = sftp_open(sftp, "/usr/bin/ssh", O_RDONLY, 0);
Packit Service 31306d
    if (!fichier) {
Packit Service 31306d
        fprintf(stderr, "Error opening /usr/bin/ssh: %s\n",
Packit Service 31306d
                ssh_get_error(session));
Packit Service 31306d
        goto end;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* open a file for writing... */
Packit Service 31306d
    to = sftp_open(sftp, "ssh-copy", O_WRONLY | O_CREAT, 0700);
Packit Service 31306d
    if (!to) {
Packit Service 31306d
        fprintf(stderr, "Error opening ssh-copy for writing: %s\n",
Packit Service 31306d
                ssh_get_error(session));
Packit Service 31306d
        sftp_close(fichier);
Packit Service 31306d
        goto end;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    while ((len = sftp_read(fichier, data, 4096)) > 0) {
Packit Service 31306d
        if (sftp_write(to, data, len) != len) {
Packit Service 31306d
            fprintf(stderr, "Error writing %d bytes: %s\n",
Packit Service 31306d
                    len, ssh_get_error(session));
Packit Service 31306d
            sftp_close(to);
Packit Service 31306d
            sftp_close(fichier);
Packit Service 31306d
            goto end;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    printf("finished\n");
Packit Service 31306d
    if (len < 0) {
Packit Service 31306d
        fprintf(stderr, "Error reading file: %s\n", ssh_get_error(session));
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    sftp_close(fichier);
Packit Service 31306d
    sftp_close(to);
Packit Service 31306d
    printf("fichiers ferm\n");
Packit Service 31306d
    to = sftp_open(sftp, "/tmp/grosfichier", O_WRONLY|O_CREAT, 0644);
Packit Service 31306d
Packit Service 31306d
    for (i = 0; i < 1000; ++i) {
Packit Service 31306d
        len = sftp_write(to, data, DATALEN);
Packit Service 31306d
        printf("wrote %d bytes\n", len);
Packit Service 31306d
        if (len != DATALEN) {
Packit Service 31306d
            printf("chunk %d : %d (%s)\n", i, len, ssh_get_error(session));
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    sftp_close(to);
Packit Service 31306d
end:
Packit Service 31306d
    /* close the sftp session */
Packit Service 31306d
    sftp_free(sftp);
Packit Service 31306d
    printf("sftp session terminated\n");
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static void usage(const char *argv0) {
Packit Service 31306d
    fprintf(stderr, "Usage : %s [-v] remotehost\n"
Packit Service 31306d
            "sample sftp test client - libssh-%s\n"
Packit Service 31306d
            "Options :\n"
Packit Service 31306d
            "  -v : increase log verbosity\n",
Packit Service 31306d
            argv0,
Packit Service 31306d
            ssh_version(0));
Packit Service 31306d
    exit(0);
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static int opts(int argc, char **argv) {
Packit Service 31306d
    int i;
Packit Service 31306d
Packit Service 31306d
    while ((i = getopt(argc, argv, "v")) != -1) {
Packit Service 31306d
        switch(i) {
Packit Service 31306d
        case 'v':
Packit Service 31306d
            verbosity++;
Packit Service 31306d
            break;
Packit Service 31306d
        default:
Packit Service 31306d
            fprintf(stderr, "unknown option %c\n", optopt);
Packit Service 31306d
            usage(argv[0]);
Packit Service 31306d
            return -1;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    destination = argv[optind];
Packit Service 31306d
    if (destination == NULL) {
Packit Service 31306d
        usage(argv[0]);
Packit Service 31306d
        return -1;
Packit Service 31306d
    }
Packit Service 31306d
    return 0;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
int main(int argc, char **argv) {
Packit Service 31306d
    ssh_session session;
Packit Service 31306d
Packit Service 31306d
    if (opts(argc, argv) < 0) {
Packit Service 31306d
        return EXIT_FAILURE;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    session = connect_ssh(destination, NULL, verbosity);
Packit Service 31306d
    if (session == NULL) {
Packit Service 31306d
        return EXIT_FAILURE;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    do_sftp(session);
Packit Service 31306d
    ssh_disconnect(session);
Packit Service 31306d
    ssh_free(session);
Packit Service 31306d
    return 0;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
#endif