Blame examples/samplesftp.c

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