SFTP added.
This commit is contained in:
parent
767e09969c
commit
232bbc0c53
5 changed files with 272 additions and 25 deletions
|
@ -30,9 +30,11 @@
|
|||
#include "common.h"
|
||||
|
||||
|
||||
struct SFTPS;
|
||||
struct SSHS;
|
||||
|
||||
|
||||
typedef void (*SFTPCallback)(struct SFTPS*);
|
||||
typedef void (*SSHCallback)(struct SSHS*);
|
||||
|
||||
|
||||
|
@ -48,11 +50,35 @@ typedef struct SSHS {
|
|||
} SSHT;
|
||||
|
||||
|
||||
SSHT *sshConnect(char *hostname, uint16_t port, char *user, char *password);
|
||||
void sshDisconnect(SSHT **sshData);
|
||||
int sshExecute(SSHT *sshData, char *command, char **output);
|
||||
void sshShutdown(void);
|
||||
void sshStartup(void);
|
||||
typedef struct SFTPS {
|
||||
SSHT *sshData;
|
||||
FILE *local;
|
||||
LIBSSH2_SFTP *session;
|
||||
LIBSSH2_SFTP_HANDLE *handle;
|
||||
char buffer[102400];
|
||||
char *ptr;
|
||||
uint64_t fileSize;
|
||||
uint64_t fileSent;
|
||||
size_t nread;
|
||||
char *source;
|
||||
char *target;
|
||||
char *title;
|
||||
gboolean uploading;
|
||||
gboolean readMore;
|
||||
gboolean finished;
|
||||
gboolean success;
|
||||
GtkWidget *status;
|
||||
SFTPCallback callback;
|
||||
} SFTPT;
|
||||
|
||||
|
||||
SSHT *sshConnect(char *hostname, uint16_t port, char *user, char *password);
|
||||
void sshDisconnect(SSHT **sshData);
|
||||
//int sshExecute(SSHT *sshData, char *command, char **output);
|
||||
gboolean sshSFTPFileExists(SSHT *sshData, char *target);
|
||||
SFTPT *sshSFTPSend(char *title, SSHT *sshData, char *source, char *target, SFTPCallback callback);
|
||||
void sshShutdown(void);
|
||||
void sshStartup(void);
|
||||
|
||||
|
||||
#endif // SSH_H
|
||||
|
|
|
@ -47,9 +47,11 @@ char *utilFileBasename(char *path);
|
|||
gboolean utilFileCopy(char *from, char *to);
|
||||
gboolean utilFileExists(char *filename);
|
||||
gboolean utilFileOpen(WindowDataT *self, char *extension, char *what);
|
||||
char *utilFilePath(char *filename);
|
||||
char *utilFileRemoveExtension(char *filename);
|
||||
gboolean utilFileSaveAs(WindowDataT *self, char *extension, char *what);
|
||||
gboolean utilFileSaveOtherAs(WindowDataT *self, char *extension, char *what, char **filename);
|
||||
size_t utilFileSize(char *filename);
|
||||
GtkWidget *utilFindChildWidget(GtkWidget *parent, const gchar *name);
|
||||
char *utilGetToken(char *input, char *delimit, char *openblock, char *closeblock);
|
||||
WindowDataT *utilGetWindowData(GtkWidget *window);
|
||||
|
|
|
@ -937,6 +937,7 @@ EVENT void menuProjectBuildCookRecipes(GtkWidget *object, gpointer userData) {
|
|||
|
||||
|
||||
EVENT void menuProjectBuildBuild(GtkWidget *object, gpointer userData) {
|
||||
//***TODO***
|
||||
}
|
||||
|
||||
|
||||
|
|
216
src/ssh.c
216
src/ssh.c
|
@ -28,6 +28,7 @@
|
|||
#include "ssh.h"
|
||||
#include "utils.h"
|
||||
#include "array.h"
|
||||
#include "messages.h"
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -38,14 +39,16 @@ closesocket(data->sock);
|
|||
#endif
|
||||
|
||||
|
||||
static SSHT **_activeSSHs = NULL;
|
||||
static char *_output = NULL;
|
||||
static int _outputLen = 0;
|
||||
static char *_buffer = NULL;
|
||||
static int _bufferLen = 0;
|
||||
static SFTPT **_activeSFTPs = NULL;
|
||||
static SSHT **_activeSSHs = NULL;
|
||||
static char *_output = NULL;
|
||||
static int _outputLen = 0;
|
||||
static char *_buffer = NULL;
|
||||
static int _bufferLen = 0;
|
||||
|
||||
|
||||
gboolean sshUpdate(gpointer userData); // Not static
|
||||
gboolean sshSFTPUpdate(gpointer userData); // Not static
|
||||
static int sshWaitSocket(int socket_fd, LIBSSH2_SESSION *session);
|
||||
|
||||
|
||||
|
@ -58,13 +61,13 @@ SSHT *sshConnect(char *hostname, uint16_t port, char *user, char *password) {
|
|||
|
||||
hostent = gethostbyname(hostname);
|
||||
if (hostent == NULL) {
|
||||
debug("gethostbyname() failed.\n");
|
||||
message(MSG_SEVERE, "gethostbyname() failed.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hostaddr = inet_addr(inet_ntoa(*(struct in_addr*)*(hostent->h_addr_list)));
|
||||
if (hostaddr == (in_addr_t)-1) {
|
||||
debug("inet_addr() failed.\n");
|
||||
message(MSG_SEVERE, "inet_addr() failed.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -77,7 +80,7 @@ SSHT *sshConnect(char *hostname, uint16_t port, char *user, char *password) {
|
|||
sin.sin_port = htons(port);
|
||||
sin.sin_addr.s_addr = hostaddr;
|
||||
if (connect(data->sock, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)) != 0) {
|
||||
debug("connect() failed: %d\n", errno);
|
||||
message(MSG_ERROR, "connect() failed: %d\n", errno);
|
||||
DEL(data);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -94,7 +97,7 @@ SSHT *sshConnect(char *hostname, uint16_t port, char *user, char *password) {
|
|||
while ((rc = libssh2_session_handshake(data->session, data->sock)) == LIBSSH2_ERROR_EAGAIN)
|
||||
;
|
||||
if (rc) {
|
||||
debug("Failure establishing SSH session: %d\n", rc);
|
||||
message(MSG_ERROR, "Failure establishing SSH session: %d\n", rc);
|
||||
libssh2_session_free(data->session);
|
||||
socketclose(data->sock);
|
||||
DEL(data);
|
||||
|
@ -104,7 +107,7 @@ SSHT *sshConnect(char *hostname, uint16_t port, char *user, char *password) {
|
|||
while ((rc = libssh2_userauth_password(data->session, user, password)) == LIBSSH2_ERROR_EAGAIN)
|
||||
;
|
||||
if (rc) {
|
||||
debug("Failure authenticating SSH session: %d\n", rc);
|
||||
message(MSG_ERROR, "Failure authenticating SSH session: %d\n", rc);
|
||||
while (libssh2_session_disconnect(data->session, "Error") == LIBSSH2_ERROR_EAGAIN)
|
||||
;
|
||||
libssh2_session_free(data->session);
|
||||
|
@ -129,6 +132,7 @@ void sshDisconnect(SSHT **sshData) {
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
int sshExecute(SSHT *sshData, char *command, char **output) {
|
||||
int rc;
|
||||
int exitcode = 127;
|
||||
|
@ -201,18 +205,207 @@ SSHT *sshExecuteVerbose(SSHT *sshData, char *title, char *command, SSHCallback c
|
|||
return NULL;
|
||||
}
|
||||
|
||||
//***TODO*** SSH Progress Dialog Here
|
||||
// ***TODO*** SSH Progress Dialog Here
|
||||
//sshData->status = new SSHStatus(sshData);
|
||||
arrpush(_activeSSHs, sshData);
|
||||
|
||||
return sshData;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
gboolean sshSFTPFileExists(SSHT *sshData, char *target) {
|
||||
LIBSSH2_SFTP *session;
|
||||
LIBSSH2_SFTP_HANDLE *handle;
|
||||
LIBSSH2_SFTP_ATTRIBUTES attrs;
|
||||
char *path;
|
||||
char *file;
|
||||
char buffer[512];
|
||||
int rc;
|
||||
gboolean result = FALSE;
|
||||
|
||||
do {
|
||||
session = libssh2_sftp_init(sshData->session);
|
||||
if (!session) {
|
||||
if (libssh2_session_last_errno(sshData->session) != LIBSSH2_ERROR_EAGAIN) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
} while (!session);
|
||||
|
||||
path = utilFilePath(target);
|
||||
file = utilFileBasename(target);
|
||||
|
||||
do {
|
||||
handle = libssh2_sftp_opendir(session, path);
|
||||
if ((!handle) && (libssh2_session_last_errno(sshData->session) != LIBSSH2_ERROR_EAGAIN)) {
|
||||
libssh2_sftp_shutdown(session);
|
||||
free(file);
|
||||
free(path);
|
||||
return FALSE;
|
||||
}
|
||||
} while (!handle);
|
||||
|
||||
do {
|
||||
while ((rc = libssh2_sftp_readdir(handle, buffer, sizeof(buffer), &attrs)) == LIBSSH2_ERROR_EAGAIN) {
|
||||
;
|
||||
}
|
||||
// rc is the size of the content in buffer
|
||||
if (rc > 0) {
|
||||
if (strcmp(buffer, file) == 0) {
|
||||
result = TRUE;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
// Blocking - do nothing
|
||||
} else {
|
||||
// Finished.
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while(1);
|
||||
|
||||
free(file);
|
||||
free(path);
|
||||
|
||||
libssh2_sftp_closedir(handle);
|
||||
libssh2_sftp_shutdown(session);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
SFTPT *sshSFTPSend(char *title, SSHT *sshData, char *source, char *target, SFTPCallback callback) {
|
||||
SFTPT *sftp = NULL;
|
||||
int i;
|
||||
|
||||
// Do not allow two of the same transfers to be started.
|
||||
for (i=0; i<arrlen(_activeSFTPs); i++) {
|
||||
if ((strcmp(_activeSFTPs[i]->source, source) == 0) && (strcmp(_activeSFTPs[i]->target, target) == 0)) {
|
||||
// Return existing transfer handle.
|
||||
return _activeSFTPs[i];
|
||||
}
|
||||
}
|
||||
|
||||
sftp = NEW(SFTPT);
|
||||
|
||||
if (sftp) {
|
||||
sftp->fileSize = utilFileSize(source);
|
||||
sftp->local = fopen(source, "rb");
|
||||
if (sftp->local) {
|
||||
sftp->fileSent = 0;
|
||||
sftp->nread = 0;
|
||||
sftp->ptr = NULL;
|
||||
sftp->title = title;
|
||||
sftp->source = source;
|
||||
sftp->target = target;
|
||||
sftp->sshData = sshData;
|
||||
sftp->uploading = TRUE;
|
||||
sftp->readMore = TRUE;
|
||||
sftp->finished = FALSE;
|
||||
sftp->success = FALSE;
|
||||
sftp->callback = callback;
|
||||
do {
|
||||
sftp->session = libssh2_sftp_init(sshData->session);
|
||||
if (!sftp->session) {
|
||||
if (libssh2_session_last_errno(sshData->session) != LIBSSH2_ERROR_EAGAIN) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (!sftp->session);
|
||||
do {
|
||||
sftp->handle = libssh2_sftp_open(sftp->session, sftp->target, LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT | LIBSSH2_FXF_TRUNC, LIBSSH2_SFTP_S_IRUSR | LIBSSH2_SFTP_S_IWUSR | LIBSSH2_SFTP_S_IRGRP | LIBSSH2_SFTP_S_IROTH);
|
||||
if (!sftp->handle) {
|
||||
if (libssh2_session_last_errno(sshData->session) != LIBSSH2_ERROR_EAGAIN) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (!sftp->handle);
|
||||
if (sftp->handle) {
|
||||
//***TODO*** SFTP Status Dialog
|
||||
//sftp->status = new SFTPStatus(sftp);
|
||||
arrput(_activeSFTPs, sftp);
|
||||
return sftp;
|
||||
} else {
|
||||
message(MSG_SEVERE, "Failed to get SFTP handle! %d, %lu\n", libssh2_session_last_errno(sshData->session), libssh2_sftp_last_error(sftp->session));
|
||||
libssh2_sftp_shutdown(sftp->session);
|
||||
DEL(sftp);
|
||||
}
|
||||
} else {
|
||||
DEL(sftp);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
gboolean sshSFTPUpdate(gpointer userData) {
|
||||
int i;
|
||||
int rc;
|
||||
int count = 0;
|
||||
SFTPT *result = NULL;
|
||||
|
||||
(void)userData;
|
||||
|
||||
for (i=0; i<arrlen(_activeSFTPs); i++) {
|
||||
count++;
|
||||
// More data to read?
|
||||
if (_activeSFTPs[i]->readMore) {
|
||||
_activeSFTPs[i]->nread = fread(_activeSFTPs[i]->buffer, 1, sizeof(_activeSFTPs[i]->buffer), _activeSFTPs[i]->local);
|
||||
if (_activeSFTPs[i]->nread <= 0) {
|
||||
result = _activeSFTPs[i];
|
||||
arrdel(_activeSFTPs, i);
|
||||
break;
|
||||
}
|
||||
_activeSFTPs[i]->ptr = _activeSFTPs[i]->buffer;
|
||||
_activeSFTPs[i]->readMore = FALSE;
|
||||
}
|
||||
|
||||
// Is there data to send?
|
||||
if (_activeSFTPs[i]->nread > 0) {
|
||||
// Send data.
|
||||
while ((rc = (int)libssh2_sftp_write(_activeSFTPs[i]->handle, _activeSFTPs[i]->ptr, _activeSFTPs[i]->nread)) == LIBSSH2_ERROR_EAGAIN) {
|
||||
sshWaitSocket(_activeSFTPs[i]->sshData->sock, _activeSFTPs[i]->sshData->session);
|
||||
}
|
||||
if (rc >= 0) {
|
||||
_activeSFTPs[i]->ptr += rc;
|
||||
_activeSFTPs[i]->nread -= rc;
|
||||
_activeSFTPs[i]->fileSent += rc;
|
||||
} else {
|
||||
// We need more data!
|
||||
_activeSFTPs[i]->readMore = TRUE;
|
||||
}
|
||||
} else {
|
||||
// We need more data!
|
||||
_activeSFTPs[i]->readMore = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (result) {
|
||||
result->finished = TRUE;
|
||||
result->success = TRUE;
|
||||
libssh2_sftp_close(result->handle);
|
||||
libssh2_sftp_shutdown(result->session);
|
||||
//***TODO*** Display in status dialog
|
||||
//result->status->Finished();
|
||||
//result->status->Close();
|
||||
if (result->callback) {
|
||||
result->callback(result);
|
||||
}
|
||||
DEL(result);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
void sshShutdown(void) {
|
||||
//***TODO*** Any active sessions?
|
||||
|
||||
g_idle_remove_by_data(sshUpdate);
|
||||
g_idle_remove_by_data(sshSFTPUpdate);
|
||||
|
||||
DEL(_output);
|
||||
DEL(_buffer);
|
||||
|
@ -240,6 +433,7 @@ void sshStartup(void) {
|
|||
utilEnsureBufferSize((unsigned char **)&_buffer, &_bufferLen, 0x4000);
|
||||
|
||||
g_idle_add(sshUpdate, sshUpdate);
|
||||
g_idle_add(sshSFTPUpdate, sshSFTPUpdate);
|
||||
}
|
||||
|
||||
|
||||
|
|
42
src/utils.c
42
src/utils.c
|
@ -177,6 +177,8 @@ char *utilFileBasename(char *path) {
|
|||
size_t length;
|
||||
char *newString = NULL;
|
||||
|
||||
// Returns filename without path.
|
||||
|
||||
cwk_path_get_basename(path, &basename, &length);
|
||||
if (basename != NULL) newString = strdup(basename);
|
||||
|
||||
|
@ -272,6 +274,21 @@ gboolean utilFileOpen(WindowDataT *self, char *extension, char *what) {
|
|||
}
|
||||
|
||||
|
||||
char *utilFilePath(char *filename) {
|
||||
int i;
|
||||
char *temp = NULL;
|
||||
|
||||
if (filename) {
|
||||
// Derive the path from the filename.
|
||||
temp = strdup(filename);
|
||||
cwk_path_get_dirname(temp, &i);
|
||||
if (i > 0) temp[i] = 0;
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
||||
char *utilFileRemoveExtension(char *filename) {
|
||||
int x = (int)strlen(filename) - 1;
|
||||
char c;
|
||||
|
@ -347,6 +364,21 @@ gboolean utilFileSaveOtherAs(WindowDataT *self, char *extension, char *what, cha
|
|||
}
|
||||
|
||||
|
||||
size_t utilFileSize(char *filename) {
|
||||
size_t bytes = 0;
|
||||
|
||||
FILE *f = fopen(filename, "rb");
|
||||
|
||||
if (f) {
|
||||
fseek(f, 0, SEEK_END);
|
||||
bytes = ftell(f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
GtkWidget *utilFindChildWidget(GtkWidget *parent, const gchar *name) {
|
||||
GList *children = NULL;
|
||||
GtkWidget *widget = NULL;
|
||||
|
@ -599,16 +631,8 @@ void utilSetDirty(WindowDataT *self, gboolean dirty) {
|
|||
|
||||
|
||||
void utilUpdatePath(WindowDataT *self) {
|
||||
size_t i;
|
||||
|
||||
DEL(self->path);
|
||||
|
||||
if (self->filename) {
|
||||
// Derive the path from the filename.
|
||||
self->path = strdup(self->filename);
|
||||
cwk_path_get_dirname(self->path, &i);
|
||||
if (i > 0) self->path[i] = 0;
|
||||
}
|
||||
self->path = utilFilePath(self->filename);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue