Created libssh2_sftp_readdir_ex() and updated LIBSSH2_APINO to 200706151200

This commit is contained in:
James Housley 2007-06-15 17:22:49 +00:00
parent ca616cea36
commit 0742a972c1
7 changed files with 200 additions and 155 deletions

View File

@ -1,3 +1,9 @@
2007-07-15 James Housley <jim@thehousleys.net>
* Add libssh2_sftp_readdir_ex(), this function if passed the
extra parameters will be used to store the full directory
entry as provided by the server. Updated LIBSSH2_APINO to
200706151200 for this change.
2007-07-12 James Housley <jim@thehousleys.net> 2007-07-12 James Housley <jim@thehousleys.net>
* libssh2_publickey_shutdown(), libssh2_session_free() changed * libssh2_publickey_shutdown(), libssh2_session_free() changed

3
NEWS
View File

@ -1,5 +1,8 @@
Version Version
------------ ------------
Added libssh2_sftp_readdir_ex() and updated LIBSSH2_APINO to
200706151200 (James Housley)
Converted all of the libssh2 code to be able to work in non-blocking Converted all of the libssh2 code to be able to work in non-blocking
mode. This included some public API changes, listed below (James Housley) mode. This included some public API changes, listed below (James Housley)
Changed function return values: Changed function return values:

View File

@ -1,12 +1,15 @@
.\" $Id: libssh2_sftp_readdir.3,v 1.8 2007/06/13 16:41:33 jehousley Exp $ .\" $Id: libssh2_sftp_readdir.3,v 1.9 2007/06/15 17:22:49 jehousley Exp $
.\" .\"
.TH libssh2_sftp_readdir 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual" .TH libssh2_sftp_readdir_ex 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual"
.SH NAME .SH NAME
libssh2_sftp_readdir - read directory data from an SFTP handle libssh2_sftp_readdir_ex - read directory data from an SFTP handle
.SH SYNOPSIS .SH SYNOPSIS
#include <libssh2.h> #include <libssh2.h>
#include <libssh2_sftp.h> #include <libssh2_sftp.h>
int
libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size_t buffer_maxlen, char *longentry, size_t longentry_maxlen, LIBSSH2_SFTP_ATTRIBUTES *attrs);
int int
libssh2_sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size_t buffer_maxlen, LIBSSH2_SFTP_ATTRIBUTES *attrs); libssh2_sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size_t buffer_maxlen, LIBSSH2_SFTP_ATTRIBUTES *attrs);
@ -21,6 +24,13 @@ libssh2_sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size_t buffer_ma
filename is longer than the space provided by buffer_maxlen it will be filename is longer than the space provided by buffer_maxlen it will be
truncated to fit. truncated to fit.
\fIlongentry\fP - is a pointer to a pre-allocated buffer of at least
\fIlongentry_maxlen\fP bytes to read data into.
\fIlongentry_maxlen\fP - is the length of longentry in bytes. If the length
of the full directory entry is longer than the space provided by
longentry_maxlen it will be truncated to fit.
\fIattrs\fP - is a pointer to LIBSSH2_SFTP_ATTRIBUTES storage to populate \fIattrs\fP - is a pointer to LIBSSH2_SFTP_ATTRIBUTES storage to populate
statbuf style data into. statbuf style data into.

View File

@ -1,5 +1,5 @@
/* /*
* $Id: sftpdir.c,v 1.5 2007/06/06 12:34:09 jehousley Exp $ * $Id: sftpdir.c,v 1.6 2007/06/15 17:22:49 jehousley Exp $
* *
* Sample doing an SFTP directory listing. * Sample doing an SFTP directory listing.
* *
@ -37,177 +37,182 @@
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
unsigned long hostaddr; unsigned long hostaddr;
int sock, i, auth_pw = 1; int sock, i, auth_pw = 1;
struct sockaddr_in sin; struct sockaddr_in sin;
const char *fingerprint; const char *fingerprint;
LIBSSH2_SESSION *session; LIBSSH2_SESSION *session;
char *username=(char *)"username"; char *username=(char *)"username";
char *password=(char *)"password"; char *password=(char *)"password";
char *sftppath=(char *)"/tmp/secretdir"; char *sftppath=(char *)"/tmp/secretdir";
int rc; int rc;
LIBSSH2_SFTP *sftp_session; LIBSSH2_SFTP *sftp_session;
LIBSSH2_SFTP_HANDLE *sftp_handle; LIBSSH2_SFTP_HANDLE *sftp_handle;
#ifdef WIN32 #ifdef WIN32
WSADATA wsadata; WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata); WSAStartup(WINSOCK_VERSION, &wsadata);
#endif #endif
if (argc > 1) { if (argc > 1) {
hostaddr = inet_addr(argv[1]); hostaddr = inet_addr(argv[1]);
} else { } else {
hostaddr = htonl(0x7F000001); hostaddr = htonl(0x7F000001);
} }
if(argc > 2) { if(argc > 2) {
username = argv[2]; username = argv[2];
} }
if(argc > 3) { if(argc > 3) {
password = argv[3]; password = argv[3];
} }
if(argc > 4) { if(argc > 4) {
sftppath = argv[4]; sftppath = argv[4];
} }
/* /*
* The application code is responsible for creating the socket * The application code is responsible for creating the socket
* and establishing the connection * and establishing the connection
*/ */
sock = socket(AF_INET, SOCK_STREAM, 0); sock = socket(AF_INET, SOCK_STREAM, 0);
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
sin.sin_port = htons(22); sin.sin_port = htons(22);
sin.sin_addr.s_addr = hostaddr; sin.sin_addr.s_addr = hostaddr;
if (connect(sock, (struct sockaddr*)(&sin), if (connect(sock, (struct sockaddr*)(&sin),
sizeof(struct sockaddr_in)) != 0) { sizeof(struct sockaddr_in)) != 0) {
fprintf(stderr, "failed to connect!\n"); fprintf(stderr, "failed to connect!\n");
return -1; return -1;
} }
/* Create a session instance /* Create a session instance
*/ */
session = libssh2_session_init(); session = libssh2_session_init();
if(!session) if(!session)
return -1; return -1;
/* ... start it up. This will trade welcome banners, exchange keys, /* ... start it up. This will trade welcome banners, exchange keys,
* and setup crypto, compression, and MAC layers * and setup crypto, compression, and MAC layers
*/ */
rc = libssh2_session_startup(session, sock); rc = libssh2_session_startup(session, sock);
if(rc) { if(rc) {
fprintf(stderr, "Failure establishing SSH session: %d\n", rc); fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
return -1; return -1;
} }
/* At this point we havn't yet authenticated. The first thing to do /* At this point we havn't yet authenticated. The first thing to do
* is check the hostkey's fingerprint against our known hosts Your app * is check the hostkey's fingerprint against our known hosts Your app
* may have it hard coded, may go to a file, may present it to the * may have it hard coded, may go to a file, may present it to the
* user, that's your call * user, that's your call
*/ */
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5); fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
printf("Fingerprint: "); printf("Fingerprint: ");
for(i = 0; i < 16; i++) { for(i = 0; i < 16; i++) {
printf("%02X ", (unsigned char)fingerprint[i]); printf("%02X ", (unsigned char)fingerprint[i]);
} }
printf("\n"); printf("\n");
if (auth_pw) { if (auth_pw) {
/* We could authenticate via password */ /* We could authenticate via password */
if (libssh2_userauth_password(session, username, password)) { if ((i = libssh2_userauth_password(session, username, password))) {
printf("Authentication by password failed.\n"); printf("Authentication by password failed.\n");
goto shutdown; goto shutdown;
} }
} else { } else {
/* Or by public key */ /* Or by public key */
if (libssh2_userauth_publickey_fromfile(session, username, if (libssh2_userauth_publickey_fromfile(session, username,
"/home/username/.ssh/id_rsa.pub", "/home/username/.ssh/id_rsa.pub",
"/home/username/.ssh/id_rsa", "/home/username/.ssh/id_rsa",
password)) { password)) {
printf("\tAuthentication by public key failed\n"); printf("\tAuthentication by public key failed\n");
goto shutdown; goto shutdown;
} }
} }
fprintf(stderr, "libssh2_sftp_init()!\n"); fprintf(stderr, "libssh2_sftp_init()!\n");
sftp_session = libssh2_sftp_init(session); sftp_session = libssh2_sftp_init(session);
if (!sftp_session) { if (!sftp_session) {
fprintf(stderr, "Unable to init SFTP session\n"); fprintf(stderr, "Unable to init SFTP session\n");
goto shutdown; goto shutdown;
} }
/* Since we have not set non-blocking, tell libssh2 we are blocking */ /* Since we have not set non-blocking, tell libssh2 we are blocking */
libssh2_session_set_blocking(session, 1); libssh2_session_set_blocking(session, 1);
fprintf(stderr, "libssh2_sftp_opendir()!\n"); fprintf(stderr, "libssh2_sftp_opendir()!\n");
/* Request a dir listing via SFTP */ /* Request a dir listing via SFTP */
sftp_handle = libssh2_sftp_opendir(sftp_session, sftppath); sftp_handle = libssh2_sftp_opendir(sftp_session, sftppath);
if (!sftp_handle) { if (!sftp_handle) {
fprintf(stderr, "Unable to open dir with SFTP\n"); fprintf(stderr, "Unable to open dir with SFTP\n");
goto shutdown; goto shutdown;
} }
fprintf(stderr, "libssh2_sftp_opendir() is done, now receive listing!\n"); fprintf(stderr, "libssh2_sftp_opendir() is done, now receive listing!\n");
do { do {
char mem[512]; char mem[512];
LIBSSH2_SFTP_ATTRIBUTES attrs; char longentry[512];
LIBSSH2_SFTP_ATTRIBUTES attrs;
/* loop until we fail */ /* loop until we fail */
rc = libssh2_sftp_readdir(sftp_handle, mem, sizeof(mem), rc = libssh2_sftp_readdir_ex(sftp_handle, mem, sizeof(mem),
&attrs); longentry, sizeof(longentry), &attrs);
if(rc > 0) { if(rc > 0) {
/* rc is the length of the file name in the mem /* rc is the length of the file name in the mem
buffer */ buffer */
if(attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) { if (longentry[0] != '\0') {
/* this should check what permissions it printf("%s\n", longentry);
is and print the output accordingly */ } else {
printf("--fix----- "); if(attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
} /* this should check what permissions it
else { is and print the output accordingly */
printf("---------- "); printf("--fix----- ");
} }
else {
printf("---------- ");
}
if(attrs.flags & LIBSSH2_SFTP_ATTR_UIDGID) { if(attrs.flags & LIBSSH2_SFTP_ATTR_UIDGID) {
printf("%4ld %4ld ", attrs.uid, attrs.gid); printf("%4ld %4ld ", attrs.uid, attrs.gid);
} }
else { else {
printf(" - - "); printf(" - - ");
} }
if(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) { if(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) {
/* attrs.filesize is an uint64_t according to /* attrs.filesize is an uint64_t according to
the docs but there is no really good and the docs but there is no really good and
portable 64bit type for C before C99, and portable 64bit type for C before C99, and
correspondingly there was no good printf() correspondingly there was no good printf()
option for it... */ option for it... */
printf("%8lld ", attrs.filesize); printf("%8lld ", attrs.filesize);
} }
printf("%s\n", mem); printf("%s\n", mem);
} }
else }
break; else
break;
} while (1); } while (1);
libssh2_sftp_closedir(sftp_handle); libssh2_sftp_closedir(sftp_handle);
libssh2_sftp_shutdown(sftp_session); libssh2_sftp_shutdown(sftp_session);
shutdown: shutdown:
libssh2_session_disconnect(session, "Normal Shutdown, Thank you for playing"); libssh2_session_disconnect(session, "Normal Shutdown, Thank you for playing");
libssh2_session_free(session); libssh2_session_free(session);
#ifdef WIN32 #ifdef WIN32
Sleep(1000); Sleep(1000);
closesocket(sock); closesocket(sock);
#else #else
sleep(1); sleep(1);
close(sock); close(sock);
#endif #endif
printf("all done\n"); printf("all done\n");
return 0; return 0;
} }

View File

@ -77,7 +77,7 @@ typedef long long libssh2_int64_t;
#endif #endif
#define LIBSSH2_VERSION "0.15-CVS" #define LIBSSH2_VERSION "0.15-CVS"
#define LIBSSH2_APINO 200706012030 #define LIBSSH2_APINO 200706151200
/* Part of every banner, user specified or not */ /* Part of every banner, user specified or not */
#define LIBSSH2_SSH_BANNER "SSH-2.0-libssh2_" LIBSSH2_VERSION #define LIBSSH2_SSH_BANNER "SSH-2.0-libssh2_" LIBSSH2_VERSION

View File

@ -193,8 +193,11 @@ LIBSSH2_API LIBSSH2_SFTP_HANDLE *libssh2_sftp_open_ex(LIBSSH2_SFTP *sftp, const
LIBSSH2_API ssize_t libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size_t buffer_maxlen); LIBSSH2_API ssize_t libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size_t buffer_maxlen);
LIBSSH2_API int libssh2_sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, LIBSSH2_API int libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size_t buffer_maxlen,
size_t buffer_maxlen, LIBSSH2_SFTP_ATTRIBUTES *attrs); char *longentry, size_t longentry_maxlen,
LIBSSH2_SFTP_ATTRIBUTES *attrs);
#define libssh2_sftp_readdir(handle, buffer, buffer_maxlen, attrs) \
libssh2_sftp_readdir_ex((handle), (buffer), (buffer_maxlen), NULL, 0, (attrs))
LIBSSH2_API ssize_t libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer, size_t count); LIBSSH2_API ssize_t libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer, size_t count);

View File

@ -995,14 +995,15 @@ LIBSSH2_API ssize_t libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
/* {{{ libssh2_sftp_readdir /* {{{ libssh2_sftp_readdir
* Read from an SFTP directory handle * Read from an SFTP directory handle
*/ */
LIBSSH2_API int libssh2_sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size_t buffer_maxlen, LIBSSH2_API int libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size_t buffer_maxlen,
LIBSSH2_SFTP_ATTRIBUTES *attrs) char *longentry, size_t longentry_maxlen,
LIBSSH2_SFTP_ATTRIBUTES *attrs)
{ {
LIBSSH2_SFTP *sftp = handle->sftp; LIBSSH2_SFTP *sftp = handle->sftp;
LIBSSH2_CHANNEL *channel = sftp->channel; LIBSSH2_CHANNEL *channel = sftp->channel;
LIBSSH2_SESSION *session = channel->session; LIBSSH2_SESSION *session = channel->session;
LIBSSH2_SFTP_ATTRIBUTES attrs_dummy; LIBSSH2_SFTP_ATTRIBUTES attrs_dummy;
unsigned long data_len, request_id, filename_len, num_names; unsigned long data_len, request_id, filename_len, longentry_len, num_names;
/* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */ /* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */
ssize_t packet_len = handle->handle_len + 13; ssize_t packet_len = handle->handle_len + 13;
unsigned char *packet, *s, *data; unsigned char *packet, *s, *data;
@ -1031,8 +1032,25 @@ LIBSSH2_API int libssh2_sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
buffer[filename_len] = '\0'; buffer[filename_len] = '\0';
} }
/* Skip longname */ if ((longentry == NULL) || (longentry_maxlen == 0)) {
s += 4 + libssh2_ntohu32(s); /* Skip longname */
s += 4 + libssh2_ntohu32(s);
} else {
unsigned long real_longentry_len = libssh2_ntohu32(s);
longentry_len = real_longentry_len;
s += 4;
if (longentry_len > longentry_maxlen) {
longentry_len = longentry_maxlen;
}
memcpy(longentry, s, longentry_len);
s += real_longentry_len;
/* The longentry is not null terminated, make it so if possible */
if (longentry_len < longentry_maxlen) {
longentry[longentry_len] = '\0';
}
}
if (attrs) { if (attrs) {
memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
@ -1044,7 +1062,7 @@ LIBSSH2_API int libssh2_sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
LIBSSH2_FREE(session, handle->u.dir.names_packet); LIBSSH2_FREE(session, handle->u.dir.names_packet);
} }
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "libssh2_sftp_readdir() return %d", filename_len); _libssh2_debug(session, LIBSSH2_DBG_SFTP, "libssh2_sftp_readdir_ex() return %d", filename_len);
return filename_len; return filename_len;
} }
@ -1159,7 +1177,7 @@ LIBSSH2_API int libssh2_sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
sftp->readdir_state = libssh2_NB_state_idle; sftp->readdir_state = libssh2_NB_state_idle;
/* Be lazy, just use the name popping mechanism from the start of the function */ /* Be lazy, just use the name popping mechanism from the start of the function */
return libssh2_sftp_readdir(handle, buffer, buffer_maxlen, attrs); return libssh2_sftp_readdir_ex(handle, buffer, buffer_maxlen, longentry, longentry_maxlen, attrs);
} }
/* }}} */ /* }}} */