Существуют ли способы выполнения вызовов типа opendir(), readdir() через SSH / SFTP?

#ssh #sftp #openssh #dirent.h

#ssh #sftp #openssh #dirent.h

Вопрос:

У меня есть фрагмент кода, который считывает каталог для файлов для обработки. В настоящее время я использую для этого методы dirent.h,opendir(), readdir(). Мне сказали, что мне нужно сделать то же самое, только теперь это каталог на удаленной машине с доступом SSH / SFTP.

Единственный способ (который я могу придумать) сделать то же самое, ничего не меняя в системе, кроме моего исходного кода, — это запустить команду «ssh user@host ls», проанализировать и обработать на основе результатов анализаторов.

Реальный вопрос здесь в том, существуют ли способы выполнения opendir(), readdir() (или чего-то подобного) через SSH / SFTP?

Ответ №1:

Самый простой способ, если вы используете Linux или Mac OS X (или некоторые BSD), — использовать sshfs для подключения к файловой системе. Тогда большинство вызовов файловой системы будут просто работать напрямую, без изменений.

В противном случае вы можете обратиться к источнику sshfs для получения подсказок о том, как это работает.

Ответ №2:

Да, у SFTP есть протокол для этого. Прочитайте самый последний документ здесь: http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer /

Комментарии:

1. Реализовано ли это где-нибудь?

2. Меня беспокоит, что OpenSSH, похоже, не имеет стабильного API или какой-либо документации по API, за исключением замечаний в коде.

3. sshfs просто запускает ssh как отдельный процесс и использует необработанный SFTP по каналу, устраняя необходимость в стабильном API

4. OpenSSH реализует сетевой протокол, а не API — стандартного SSH API не существует. sshfs — это одна из альтернатив, в противном случае вам нужно использовать клиентскую библиотеку SFTP.

Ответ №3:

Начиная с OpenSSH 5.1, существует ограниченная реализация для этого. Он не полностью реализует стандарт File XFER. Поэтому я не могу проверить наличие таких вещей, как типы файлов, но я могу отсканировать сами имена файлов… Используя код «sftp.c» в исходном коде OpenSSH, я просто собрал adhoc main(), который можно было изменять по мере необходимости… Я надеюсь, что на этот вопрос можно будет более вдумчиво ответить позже.

 /* Username is a NULL terminated string
   Host is a NULL terminated string indicating remote IP */
void setup_args(arglist *args, char *username, char *host)
{
        // Arg init allocation
        memset(args, '', sizeof(*args));
        args->list = NULL;

        // Arg setup
        addargs(args, "%s", "/usr/bin/ssh");
        addargs(args, "%s", "-oForwardX11 no");
        addargs(args, "%s", "-oForwardAgent no");
        addargs(args, "%s", "-oPermitLocalCommand no");
        addargs(args, "%s", "-oClearAllForwardings yes");
        addargs(args, "%s%s", "-l", username);
        addargs(args, "%s", "-oProtocol 2");
        addargs(args, "%s", "-s");
        addargs(args, "%s", host);
        addargs(args, "%s", "sftp");
}
void run_program()
{
        // Setup connection parameters.
        int in, out; // The IO file descriptors.
        arglist args;
        setup_args(amp;args, "chenz", "172.16.22.128");
        connect_to_server("/usr/bin/ssh", args.list, amp;in, amp;out);
        freeargs(amp;args);

        // Create connection
        struct sftp_conn *conn;
        conn = do_init(in, out, copy_buffer_len, num_requests);
        if (conn == NULL)
                fatal("Couldn't initialise connection to server");

        //Get the current directory
        char *pwd;
        pwd = do_realpath(conn, ".");
        printf("PWD: %sn", pwd);
        if (pwd == NULL)
                fatal("Need cwd");

        SFTP_DIRENT** dirent;
        do_readdir(conn, "/home/chenz", amp;dirent);
        int i = 0;
        while (dirent[i] != 0) {
                printf("filename: %sn", dirent[i]->filename);
                printf("longname: %sn", dirent[i]->longname);
                printf("attrib:n", dirent[i]->a);
                i  ;
        }

        // Clean up file descriptors
        close(in);
        close(out);

        // Wait for kill signal and exit
        while (waitpid(sshpid, NULL, 0) == -1)
                if (errno != EINTR)
                        fatal("Couldn't wait for ssh process: %s",
                            strerror(errno));

        //exit(err == 0 ? 0 : 1);
        exit(0);
 }