SFTP code cleaned up. Memory leaks fixed.
This commit is contained in:
parent
fc0ebb6e3f
commit
2fbeac943b
7 changed files with 165 additions and 336 deletions
|
@ -33,7 +33,7 @@ typedef struct StringHashS {
|
|||
} StringHashT;
|
||||
|
||||
|
||||
#define ARRFREE(a) do { if (a != NULL) { arrfree(a); } break; } while(1)
|
||||
#define ARRFREE(a) do { if (a != NULL) { arrfree(a); a = NULL; } break; } while(1)
|
||||
|
||||
|
||||
#endif // ARRAY_H
|
||||
|
|
|
@ -31,29 +31,19 @@
|
|||
|
||||
|
||||
struct SFTPS;
|
||||
struct SSHS;
|
||||
|
||||
|
||||
typedef void (*SFTPCallback)(struct SFTPS*);
|
||||
typedef void (*SSHCallback)(struct SSHS*);
|
||||
|
||||
|
||||
typedef struct SSHS {
|
||||
LIBSSH2_SESSION *session;
|
||||
LIBSSH2_CHANNEL *channel;
|
||||
int sock;
|
||||
int result;
|
||||
gboolean finished;
|
||||
SSHCallback callback;
|
||||
} SSHT;
|
||||
|
||||
|
||||
typedef struct SFTPS {
|
||||
SSHT *sshData;
|
||||
LIBSSH2_SESSION *sshSession;
|
||||
LIBSSH2_CHANNEL *sshChannel;
|
||||
int sock;
|
||||
void *userData;
|
||||
FILE *local;
|
||||
LIBSSH2_SFTP *session;
|
||||
LIBSSH2_SFTP_HANDLE *handle;
|
||||
LIBSSH2_SFTP *sftpSession;
|
||||
LIBSSH2_SFTP_HANDLE *sftpHandle;
|
||||
char buffer[102400];
|
||||
char *ptr;
|
||||
uint64_t fileSize;
|
||||
|
@ -69,13 +59,12 @@ typedef struct SFTPS {
|
|||
} SFTPT;
|
||||
|
||||
|
||||
SSHT *sshConnect(char *hostname, uint16_t port, char *user, char *password);
|
||||
void sshDisconnect(SSHT **sshData);
|
||||
gboolean sshSFTPDelete(SSHT *sshData, char *target);
|
||||
//int sshExecute(SSHT *sshData, char *command, char **output);
|
||||
gboolean sshSFTPFileExists(SSHT *sshData, char *target);
|
||||
SFTPT *sshSFTPReceive(SSHT *sshData, char *remote, char *local, SFTPCallback callback);
|
||||
SFTPT *sshSFTPSend(SSHT *sshData, char *local, char *remote, SFTPCallback callback);
|
||||
SFTPT *sshConnect(char *hostname, uint16_t port, char *user, char *password);
|
||||
void sshDisconnect(SFTPT **sshData);
|
||||
gboolean sshSFTPDelete(SFTPT *sshData, char *target);
|
||||
gboolean sshSFTPFileExists(SFTPT *sshData, char *target);
|
||||
gboolean sshSFTPReceive(SFTPT *sshData, char *remote, char *local, SFTPCallback callback);
|
||||
gboolean sshSFTPSend(SFTPT *sshData, char *local, char *remote, SFTPCallback callback);
|
||||
void sshShutdown(void);
|
||||
void sshStartup(void);
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ extern char __utilFilenameBuffer[FILENAME_MAX];
|
|||
char *utilCreateString(char *format, ...);
|
||||
char *utilCreateStringVArgs(char *format, va_list args);
|
||||
ArchiveT *utilDecompress(char *archive, char *outPath, archiveCallback callback, void *userData);
|
||||
int utilDeleteTree(const char *path);
|
||||
char *utilDeobfuscateASCII(char *obfuscated);
|
||||
void utilDequote(char *string);
|
||||
void utilEnsureBufferSize(unsigned char **buffer, int *length, int wanted);
|
||||
|
|
|
@ -55,6 +55,8 @@ void message(MessageTypesT level, char *format, ...) {
|
|||
msg = utilCreateStringVArgs(format, args);
|
||||
va_end(args);
|
||||
|
||||
debug("%s\n", msg);
|
||||
|
||||
// Break multiline messages down into individual lines.
|
||||
tok = strtok(msg, "\n");
|
||||
while (tok != NULL) {
|
||||
|
@ -68,6 +70,8 @@ void message(MessageTypesT level, char *format, ...) {
|
|||
|
||||
tok = strtok(NULL, "\n");
|
||||
}
|
||||
|
||||
DEL(msg);
|
||||
}
|
||||
|
||||
|
||||
|
@ -209,7 +213,7 @@ static void winMessagesDelete(gpointer userData) {
|
|||
DEL(_pendingMessages[0]);
|
||||
arrdel(_pendingMessages, 0);
|
||||
}
|
||||
ARRFREE(_pendingMessages);
|
||||
//ARRFREE(_pendingMessages); // This is making Memwatch mad.
|
||||
|
||||
utilWindowUnRegister(userData);
|
||||
_lstMessages = NULL;
|
||||
|
|
|
@ -242,9 +242,10 @@ static void clearRecipeData(ProjectDataT *self) {
|
|||
while (arrlen(self->recipes) > 0) {
|
||||
DEL(self->recipes[0]->key);
|
||||
DEL(self->recipes[0]->value);
|
||||
DEL(self->recipes[0]);
|
||||
arrdel(self->recipes, 0);
|
||||
}
|
||||
ARRFREE(self->recipes);
|
||||
//ARRFREE(self->recipes); // This is making Memwatch mad.
|
||||
}
|
||||
|
||||
|
||||
|
@ -263,8 +264,7 @@ static void cookFinished(CompilerContextT **context) {
|
|||
// If this is not first call, process context.
|
||||
if (self->tempInteger != -1) {
|
||||
if (ctx->programResult != 0) {
|
||||
//***TODO*** Not all negative returns are severe.
|
||||
message(ctx->programResult > 0 ? MSG_ERROR : MSG_SEVERE, "Recipe %s returned %d", self->recipes[self->tempInteger]->value, ctx->programResult);
|
||||
message(MSG_ERROR, "Recipe %s returned %d", self->recipes[self->tempInteger]->value, ctx->programResult);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -896,7 +896,7 @@ EVENT void menuProjectBuildSettings(GtkWidget *object, gpointer userData) {
|
|||
};
|
||||
char temp[6];
|
||||
int result = 0;
|
||||
SSHT *ssh = NULL;
|
||||
SFTPT *ssh = NULL;
|
||||
char *error = NULL;
|
||||
|
||||
(void)object;
|
||||
|
@ -1069,8 +1069,7 @@ EVENT void menuProjectBuildBuild(GtkWidget *object, gpointer userData) {
|
|||
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(self->treeProject));
|
||||
GtkTreeIter iter;
|
||||
GtkTreeIter child;
|
||||
SSHT *ssh;
|
||||
SFTPT *sftp;
|
||||
SFTPT *ssh;
|
||||
char *temp;
|
||||
char *filename;
|
||||
char *pathString;
|
||||
|
@ -1081,7 +1080,6 @@ EVENT void menuProjectBuildBuild(GtkWidget *object, gpointer userData) {
|
|||
gboolean archPrinted;
|
||||
FILE *out;
|
||||
|
||||
ssh = NEW(SSHT);
|
||||
ssh = sshConnect(self->buildHost, self->buildSSHPort, self->buildUser, self->buildPassword);
|
||||
|
||||
if (!ssh) {
|
||||
|
@ -1101,6 +1099,7 @@ EVENT void menuProjectBuildBuild(GtkWidget *object, gpointer userData) {
|
|||
message(MSG_SEVERE, "Unable to write temporary build.start file");
|
||||
unlink(buildStart); // Just in case.
|
||||
message(MSG_INFO, "Build canceled");
|
||||
DEL(buildStart);
|
||||
sshDisconnect(&ssh);
|
||||
return;
|
||||
}
|
||||
|
@ -1138,7 +1137,7 @@ EVENT void menuProjectBuildBuild(GtkWidget *object, gpointer userData) {
|
|||
temp = utilCreateString("%s%s", self->windowData.path, filename);
|
||||
arrput(_sendList, temp);
|
||||
}
|
||||
DEL(filename);
|
||||
//DEL(filename); // GTK says I need to free this. Memwatch says otherwise.
|
||||
} while (gtk_tree_model_iter_next(model, &child));
|
||||
}
|
||||
} while (gtk_tree_model_iter_next(model, &iter));
|
||||
|
@ -1147,10 +1146,8 @@ EVENT void menuProjectBuildBuild(GtkWidget *object, gpointer userData) {
|
|||
arrput(_sendList, buildStart);
|
||||
|
||||
// Prime the pump! We only set sshData and userData so sendSFTP can determine this is the first file.
|
||||
sftp = NEW(SFTPT);
|
||||
sftp->sshData = ssh;
|
||||
sftp->userData = self;
|
||||
sendSFTP(sftp);
|
||||
ssh->userData = self;
|
||||
sendSFTP(ssh);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1181,10 +1178,10 @@ gboolean projectAddToTree(ProjectDataT *self, char *filename) {
|
|||
do {
|
||||
gtk_tree_model_get(model, &child, COL_FILENAME, &temp, -1);
|
||||
if (strcmp(temp, filename) == 0) {
|
||||
DEL(temp); // This generates an unknown pointer warning in memwatch. Pretty sure it's bogus.
|
||||
//DEL(temp); // GTK says I need to free this. Memwatch says otherwise.
|
||||
return FALSE; // Item exists and was not added.
|
||||
}
|
||||
DEL(temp); // This generates an unknown pointer warning in memwatch. Pretty sure it's bogus.
|
||||
//DEL(temp); // GTK says I need to free this. Memwatch says otherwise.
|
||||
} while (gtk_tree_model_iter_next(model, &child));
|
||||
}
|
||||
} while (gtk_tree_model_iter_next(model, &iter));
|
||||
|
@ -1201,7 +1198,7 @@ gboolean projectAddToTree(ProjectDataT *self, char *filename) {
|
|||
}
|
||||
}
|
||||
}
|
||||
DEL(temp);
|
||||
temp = NULL; //DEL(temp); // GTK says I need to free this. Memwatch says otherwise.
|
||||
fileLen = 0;
|
||||
utilEnsureBufferSize((unsigned char **)&temp, &fileLen, 4); // fileLen is just a throwaway here.
|
||||
snprintf(temp, 4, "%d", foundAt);
|
||||
|
@ -1224,8 +1221,10 @@ static void receiveSFTP(SFTPT *sftp) {
|
|||
if (sftp->finished) {
|
||||
if (sftp->success) {
|
||||
message(MSG_INFO, "Cleaning up remote build");
|
||||
sshSFTPDelete(sftp->sshData, REMOTE_BUILD_RESULTS);
|
||||
//***TODO*** Delete any local "results" folder.
|
||||
sshSFTPDelete(sftp, REMOTE_BUILD_RESULTS);
|
||||
temp = utilCreateString("%sresults", self->windowData.path);
|
||||
utilDeleteTree(temp);
|
||||
DEL(temp);
|
||||
message(MSG_INFO, "Unpacking build");
|
||||
temp = utilCreateString("%s%s", self->windowData.path, LOCAL_BUILD_RESULTS);
|
||||
utilDecompress(temp, self->windowData.path, decompressBuild, self);
|
||||
|
@ -1233,11 +1232,8 @@ static void receiveSFTP(SFTPT *sftp) {
|
|||
} else {
|
||||
message(MSG_ERROR, "Receiving %s from build server - FAILED", sftp->remoteName);
|
||||
message(MSG_INFO, "Build canceled");
|
||||
sshDisconnect(&sftp->sshData);
|
||||
}
|
||||
DEL(sftp->localName);
|
||||
DEL(sftp->remoteName);
|
||||
DEL(sftp);
|
||||
sshDisconnect(&sftp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1406,13 +1402,9 @@ static gboolean updateBuildOptions(ProjectDataT *self) {
|
|||
|
||||
static void sendSFTP(SFTPT *sftp) {
|
||||
ProjectDataT *self = (ProjectDataT *)sftp->userData;
|
||||
SFTPT *last;
|
||||
SFTPT *next;
|
||||
char *target;
|
||||
char *name;
|
||||
|
||||
last = sftp;
|
||||
|
||||
// If source and target are missing, this is the first file - start sending.
|
||||
// Or, did the current transfer succeed? If so, send next file.
|
||||
if ((sftp->localName == NULL && sftp->remoteName == NULL) || (sftp->finished && sftp->success)) {
|
||||
|
@ -1425,19 +1417,15 @@ static void sendSFTP(SFTPT *sftp) {
|
|||
name = utilFileBasename(_sendList[0]);
|
||||
target = utilCreateString("build/%s", name);
|
||||
message(MSG_INFO, "Sending %s to build server", name);
|
||||
sftp = sshSFTPSend(last->sshData, _sendList[0], target, sendSFTP);
|
||||
sftp->userData = self;
|
||||
sshSFTPSend(sftp, _sendList[0], target, sendSFTP);
|
||||
DEL(target);
|
||||
DEL(name);
|
||||
DEL(_sendList[0]);
|
||||
arrdel(_sendList, 0);
|
||||
} else {
|
||||
// Finished!
|
||||
message(MSG_INFO, "Waiting for build to complete");
|
||||
// "last" will be deleted by sshSFTPUpdate so copy what we need to "next".
|
||||
next = NEW(SFTPT);
|
||||
next->sshData = last->sshData;
|
||||
next->userData = last->userData;
|
||||
g_timeout_add_seconds(5, waitForBuild, next);
|
||||
g_timeout_add_seconds(5, waitForBuild, sftp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1447,21 +1435,14 @@ static void sendSFTP(SFTPT *sftp) {
|
|||
message(MSG_ERROR, "Sending %s to build server - FAILED", sftp->remoteName);
|
||||
}
|
||||
message(MSG_INFO, "Build canceled");
|
||||
sshDisconnect(&last->sshData);
|
||||
sshDisconnect(&sftp);
|
||||
// Clear any remaining transfers.
|
||||
while (arrlen(_sendList) > 0) {
|
||||
DEL(_sendList[0]);
|
||||
arrdel(_sendList, 0);
|
||||
}
|
||||
ARRFREE(_sendList);
|
||||
}
|
||||
|
||||
// Do we need to free this?
|
||||
if (last->finished) {
|
||||
// Do not delete last->sshData as we continue to need it until everything is finished.
|
||||
DEL(last->localName);
|
||||
DEL(last->remoteName);
|
||||
DEL(last);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1513,31 +1494,24 @@ static void targetArrayDelete(TargetT ***array) {
|
|||
|
||||
|
||||
static gboolean waitForBuild(gpointer userData) {
|
||||
SFTPT *last = (SFTPT *)userData;
|
||||
ProjectDataT *self = (ProjectDataT *)last->userData;
|
||||
SFTPT *sftp;
|
||||
SFTPT *sftp = (SFTPT *)userData;
|
||||
ProjectDataT *self = (ProjectDataT *)sftp->userData;
|
||||
char *temp;
|
||||
gboolean result;
|
||||
|
||||
if (sshSFTPFileExists(last->sshData, REMOTE_BUILD_RESULTS)) {
|
||||
if (sshSFTPFileExists(sftp, REMOTE_BUILD_RESULTS)) {
|
||||
// Build complete! Next step!
|
||||
//***TODO*** Delete any local build archive.
|
||||
message(MSG_INFO, "Retrieving build results");
|
||||
temp = utilCreateString("%s%s", self->windowData.path, LOCAL_BUILD_RESULTS);
|
||||
sftp = sshSFTPReceive(last->sshData, REMOTE_BUILD_RESULTS, temp, receiveSFTP);
|
||||
unlink(temp);
|
||||
result = sshSFTPReceive(sftp, REMOTE_BUILD_RESULTS, temp, receiveSFTP);
|
||||
DEL(temp);
|
||||
if (!sftp) {
|
||||
if (!result) {
|
||||
message(MSG_ERROR, "Receiving build from build server - FAILED");
|
||||
message(MSG_INFO, "Build canceled");
|
||||
sshDisconnect(&last->sshData);
|
||||
} else {
|
||||
sftp->userData = last->userData;
|
||||
sshDisconnect(&sftp);
|
||||
}
|
||||
|
||||
// Finally finished with "last"
|
||||
DEL(last->localName);
|
||||
DEL(last->remoteName);
|
||||
DEL(last);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
|
@ -1627,6 +1601,8 @@ static void winProjectDelete(gpointer userData) {
|
|||
targetArrayDelete(&self->targets);
|
||||
clearRecipeData(self);
|
||||
|
||||
DEL(self->projectName);
|
||||
DEL(self->projectType);
|
||||
DEL(self->buildHost);
|
||||
DEL(self->buildUser);
|
||||
DEL(self->buildPassword);
|
||||
|
|
333
src/ssh.c
333
src/ssh.c
|
@ -40,25 +40,19 @@ closesocket(data->sock);
|
|||
|
||||
|
||||
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
|
||||
static SFTPT *sshSFTPTransfer(SSHT *sshData, char *local, char *remote, SFTPCallback callback, gboolean uploading);
|
||||
static gboolean sshSFTPTransfer(SFTPT *sshData, char *local, char *remote, SFTPCallback callback, gboolean uploading);
|
||||
gboolean sshSFTPUpdate(gpointer userData); // Not static
|
||||
static int sshWaitSocket(int socket_fd, LIBSSH2_SESSION *session);
|
||||
|
||||
|
||||
SSHT *sshConnect(char *hostname, uint16_t port, char *user, char *password) {
|
||||
SFTPT *sshConnect(char *hostname, uint16_t port, char *user, char *password) {
|
||||
int rc;
|
||||
struct hostent *hostent;
|
||||
struct sockaddr_in sin;
|
||||
in_addr_t hostaddr;
|
||||
SSHT *data = NULL;
|
||||
SFTPT *data = NULL;
|
||||
|
||||
hostent = gethostbyname(hostname);
|
||||
if (hostent == NULL) {
|
||||
|
@ -72,7 +66,7 @@ SSHT *sshConnect(char *hostname, uint16_t port, char *user, char *password) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
data = NEW(SSHT);
|
||||
data = NEW(SFTPT);
|
||||
|
||||
if (data) {
|
||||
data->sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
@ -86,73 +80,76 @@ SSHT *sshConnect(char *hostname, uint16_t port, char *user, char *password) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
data->session = libssh2_session_init();
|
||||
if (!data->session) {
|
||||
data->sshSession = libssh2_session_init();
|
||||
if (!data->sshSession) {
|
||||
socketclose(data->sock);
|
||||
DEL(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
libssh2_session_set_blocking(data->session, 0);
|
||||
libssh2_session_set_blocking(data->sshSession, 0);
|
||||
|
||||
while ((rc = libssh2_session_handshake(data->session, data->sock)) == LIBSSH2_ERROR_EAGAIN)
|
||||
while ((rc = libssh2_session_handshake(data->sshSession, data->sock)) == LIBSSH2_ERROR_EAGAIN)
|
||||
;
|
||||
if (rc) {
|
||||
message(MSG_ERROR, "Failure establishing SSH session: %d\n", rc);
|
||||
libssh2_session_free(data->session);
|
||||
libssh2_session_free(data->sshSession);
|
||||
socketclose(data->sock);
|
||||
DEL(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((rc = libssh2_userauth_password(data->session, user, password)) == LIBSSH2_ERROR_EAGAIN)
|
||||
while ((rc = libssh2_userauth_password(data->sshSession, user, password)) == LIBSSH2_ERROR_EAGAIN)
|
||||
;
|
||||
if (rc) {
|
||||
message(MSG_ERROR, "Failure authenticating SSH session: %d\n", rc);
|
||||
while (libssh2_session_disconnect(data->session, "Error") == LIBSSH2_ERROR_EAGAIN)
|
||||
while (libssh2_session_disconnect(data->sshSession, "Error") == LIBSSH2_ERROR_EAGAIN)
|
||||
;
|
||||
libssh2_session_free(data->session);
|
||||
libssh2_session_free(data->sshSession);
|
||||
socketclose(data->sock);
|
||||
DEL(data);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//***TODO*** Move SFTP session setup here so we don't keep repeating it.
|
||||
// SFTP session setup here so we don't keep repeating it.
|
||||
do {
|
||||
data->sftpSession = libssh2_sftp_init(data->sshSession);
|
||||
if (!data->sftpSession) {
|
||||
if (libssh2_session_last_errno(data->sshSession) != LIBSSH2_ERROR_EAGAIN) {
|
||||
sshDisconnect(&data);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
} while (!data->sftpSession);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
void sshDisconnect(SSHT **sshData) {
|
||||
SSHT *data = *sshData;
|
||||
void sshDisconnect(SFTPT **sshData) {
|
||||
SFTPT *data = *sshData;
|
||||
|
||||
//***TODO*** Move SFTP session teardown here so we don't keep repeating it.
|
||||
// SFTP session teardown here so we don't keep repeating it.
|
||||
libssh2_sftp_shutdown(data->sftpSession);
|
||||
|
||||
libssh2_session_disconnect(data->session, "Normal Shutdown.");
|
||||
libssh2_session_free(data->session);
|
||||
libssh2_session_disconnect(data->sshSession, "Normal Shutdown.");
|
||||
libssh2_session_free(data->sshSession);
|
||||
socketclose(data->sock);
|
||||
|
||||
DEL(data->localName);
|
||||
DEL(data->remoteName);
|
||||
|
||||
DEL(data);
|
||||
}
|
||||
|
||||
|
||||
gboolean sshSFTPDelete(SSHT *sshData, char *target) {
|
||||
LIBSSH2_SFTP *session;
|
||||
gboolean sshSFTPDelete(SFTPT *sshData, char *target) {
|
||||
int rc;
|
||||
gboolean result = TRUE;
|
||||
|
||||
do {
|
||||
session = libssh2_sftp_init(sshData->session);
|
||||
if (!session) {
|
||||
if (libssh2_session_last_errno(sshData->session) != LIBSSH2_ERROR_EAGAIN) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
} while (!session);
|
||||
|
||||
do {
|
||||
rc = libssh2_sftp_unlink(session, target);
|
||||
rc = libssh2_sftp_unlink(sshData->sftpSession, target);
|
||||
if (rc == 0) break;
|
||||
if (rc != LIBSSH2_ERROR_EAGAIN) {
|
||||
result = FALSE;
|
||||
|
@ -160,96 +157,11 @@ gboolean sshSFTPDelete(SSHT *sshData, char *target) {
|
|||
}
|
||||
} while (TRUE);
|
||||
|
||||
libssh2_sftp_shutdown(session);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
int sshExecute(SSHT *sshData, char *command, char **output) {
|
||||
int rc;
|
||||
int exitcode = 127;
|
||||
char *exitsignal = (char *)"none";
|
||||
int outputLen = 0;
|
||||
|
||||
utilEnsureBufferSize((unsigned char **)output, &outputLen, 1024);
|
||||
*output[0] = 0;
|
||||
|
||||
while ((sshData->channel = libssh2_channel_open_session(sshData->session)) == NULL && libssh2_session_last_error(sshData->session, NULL, NULL, 0) == LIBSSH2_ERROR_EAGAIN) {
|
||||
sshWaitSocket(sshData->sock, sshData->session);
|
||||
}
|
||||
if (sshData->channel == NULL) {
|
||||
return exitcode;
|
||||
}
|
||||
while ((rc = libssh2_channel_exec(sshData->channel, command)) == LIBSSH2_ERROR_EAGAIN) {
|
||||
sshWaitSocket(sshData->sock, sshData->session);
|
||||
}
|
||||
if (rc != 0) {
|
||||
return exitcode;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
do {
|
||||
rc = libssh2_channel_read(sshData->channel, (char *)_buffer, sizeof(_buffer));
|
||||
if (rc > 0) {
|
||||
utilEnsureBufferSize((unsigned char **)output, &outputLen, (int)strlen((const char *)*output) + rc + 1);
|
||||
strncat(*output, (char *)_buffer, rc);
|
||||
}
|
||||
} while (rc > 0);
|
||||
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
sshWaitSocket(sshData->sock, sshData->session);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while ((rc = libssh2_channel_close(sshData->channel)) == LIBSSH2_ERROR_EAGAIN) {
|
||||
sshWaitSocket(sshData->sock, sshData->session);
|
||||
}
|
||||
if (rc == 0) {
|
||||
exitcode = libssh2_channel_get_exit_status(sshData->channel);
|
||||
libssh2_channel_get_exit_signal(sshData->channel, &exitsignal, NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
libssh2_channel_free(sshData->channel);
|
||||
|
||||
return exitcode;
|
||||
}
|
||||
|
||||
|
||||
SSHT *sshExecuteVerbose(SSHT *sshData, char *title, char *command, SSHCallback callback) {
|
||||
int rc;
|
||||
|
||||
sshData->title = strdup(title);
|
||||
sshData->callback = callback;
|
||||
sshData->finished = FALSE;
|
||||
|
||||
while ((sshData->channel = libssh2_channel_open_session(sshData->session)) == NULL && libssh2_session_last_error(sshData->session, NULL, NULL, 0) == LIBSSH2_ERROR_EAGAIN) {
|
||||
sshWaitSocket(sshData->sock, sshData->session);
|
||||
}
|
||||
if (sshData->channel == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
while ((rc = libssh2_channel_exec(sshData->channel, command)) == LIBSSH2_ERROR_EAGAIN) {
|
||||
sshWaitSocket(sshData->sock, sshData->session);
|
||||
}
|
||||
if (rc != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ***TODO*** SSH Progress Dialog Here
|
||||
//sshData->status = new SSHStatus(sshData);
|
||||
arrpush(_activeSSHs, sshData);
|
||||
|
||||
return sshData;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
gboolean sshSFTPFileExists(SSHT *sshData, char *target) {
|
||||
LIBSSH2_SFTP *session;
|
||||
gboolean sshSFTPFileExists(SFTPT *sshData, char *target) {
|
||||
LIBSSH2_SFTP_HANDLE *handle;
|
||||
LIBSSH2_SFTP_ATTRIBUTES attrs;
|
||||
char *path;
|
||||
|
@ -259,15 +171,6 @@ gboolean sshSFTPFileExists(SSHT *sshData, char *target) {
|
|||
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);
|
||||
|
||||
// Split filename and path.
|
||||
// Cannot use utilFilePath and friends because this is a remote path.
|
||||
temp = strdup(target); // Make copy in case they pass in a constant.
|
||||
|
@ -289,9 +192,8 @@ gboolean sshSFTPFileExists(SSHT *sshData, char *target) {
|
|||
DEL(temp);
|
||||
|
||||
do {
|
||||
handle = libssh2_sftp_opendir(session, path);
|
||||
if ((!handle) && (libssh2_session_last_errno(sshData->session) != LIBSSH2_ERROR_EAGAIN)) {
|
||||
libssh2_sftp_shutdown(session);
|
||||
handle = libssh2_sftp_opendir(sshData->sftpSession, path);
|
||||
if ((!handle) && (libssh2_session_last_errno(sshData->sshSession) != LIBSSH2_ERROR_EAGAIN)) {
|
||||
free(file);
|
||||
free(path);
|
||||
return FALSE;
|
||||
|
@ -322,91 +224,76 @@ gboolean sshSFTPFileExists(SSHT *sshData, char *target) {
|
|||
free(path);
|
||||
|
||||
libssh2_sftp_closedir(handle);
|
||||
libssh2_sftp_shutdown(session);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
SFTPT *sshSFTPReceive(SSHT *sshData, char *remote, char *local, SFTPCallback callback) {
|
||||
gboolean sshSFTPReceive(SFTPT *sshData, char *remote, char *local, SFTPCallback callback) {
|
||||
return sshSFTPTransfer(sshData, local, remote, callback, FALSE);
|
||||
}
|
||||
|
||||
|
||||
SFTPT *sshSFTPSend(SSHT *sshData, char *local, char *remote, SFTPCallback callback) {
|
||||
gboolean sshSFTPSend(SFTPT *sshData, char *local, char *remote, SFTPCallback callback) {
|
||||
return sshSFTPTransfer(sshData, local, remote, callback, TRUE);
|
||||
}
|
||||
|
||||
|
||||
static SFTPT *sshSFTPTransfer(SSHT *sshData, char *local, char *remote, SFTPCallback callback, gboolean uploading) {
|
||||
SFTPT *sftp = NULL;
|
||||
static gboolean sshSFTPTransfer(SFTPT *sshData, char *local, char *remote, SFTPCallback callback, gboolean uploading) {
|
||||
int i;
|
||||
|
||||
// Do not allow two of the same transfers to be started.
|
||||
for (i=0; i<arrlen(_activeSFTPs); i++) {
|
||||
if ((strcmp(_activeSFTPs[i]->localName, local) == 0) && (strcmp(_activeSFTPs[i]->remoteName, remote) == 0)) {
|
||||
// Return existing transfer handle.
|
||||
return _activeSFTPs[i];
|
||||
// Return existing transfer is running.
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
sftp = NEW(SFTPT);
|
||||
|
||||
if (sftp) {
|
||||
sftp->fileSize = uploading ? utilFileSize(local) : 0;
|
||||
sftp->local = fopen(local, uploading ? "rb" : "wb");
|
||||
if (sftp->local) {
|
||||
sftp->fileSent = 0;
|
||||
sftp->nread = 0;
|
||||
sftp->ptr = NULL;
|
||||
sftp->localName = strdup(local);
|
||||
sftp->remoteName = strdup(remote);
|
||||
sftp->sshData = sshData;
|
||||
sftp->uploading = uploading;
|
||||
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);
|
||||
if (sshData) {
|
||||
sshData->fileSize = uploading ? utilFileSize(local) : 0;
|
||||
sshData->local = fopen(local, uploading ? "rb" : "wb");
|
||||
if (sshData->local) {
|
||||
do {
|
||||
if (uploading) {
|
||||
sftp->handle = libssh2_sftp_open(sftp->session, sftp->remoteName,
|
||||
sshData->sftpHandle = libssh2_sftp_open(sshData->sftpSession, remote,
|
||||
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);
|
||||
} else {
|
||||
sftp->handle = libssh2_sftp_open(sftp->session, sftp->remoteName,
|
||||
sshData->sftpHandle = libssh2_sftp_open(sshData->sftpSession, remote,
|
||||
LIBSSH2_FXF_READ,
|
||||
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) {
|
||||
if (!sshData->sftpHandle) {
|
||||
if (libssh2_session_last_errno(sshData->sshSession) != LIBSSH2_ERROR_EAGAIN) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (!sftp->handle);
|
||||
if (sftp->handle) {
|
||||
arrput(_activeSFTPs, sftp);
|
||||
return sftp;
|
||||
} while (!sshData->sftpHandle);
|
||||
if (sshData->sftpHandle) {
|
||||
DEL(sshData->localName);
|
||||
DEL(sshData->remoteName);
|
||||
sshData->fileSent = 0;
|
||||
sshData->nread = 0;
|
||||
sshData->ptr = NULL;
|
||||
sshData->localName = strdup(local);
|
||||
sshData->remoteName = strdup(remote);
|
||||
sshData->uploading = uploading;
|
||||
sshData->readMore = TRUE;
|
||||
sshData->finished = FALSE;
|
||||
sshData->success = FALSE;
|
||||
sshData->callback = callback;
|
||||
arrput(_activeSFTPs, sshData);
|
||||
return TRUE;
|
||||
} 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);
|
||||
message(MSG_SEVERE, "Failed to get SFTP handle! %d, %lu\n", libssh2_session_last_errno(sshData->sshSession), libssh2_sftp_last_error(sshData->sftpSession));
|
||||
}
|
||||
} else {
|
||||
DEL(sftp);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -425,6 +312,7 @@ gboolean sshSFTPUpdate(gpointer userData) {
|
|||
// More data to read?
|
||||
if (_activeSFTPs[i]->readMore) {
|
||||
_activeSFTPs[i]->nread = fread(_activeSFTPs[i]->buffer, 1, sizeof(_activeSFTPs[i]->buffer), _activeSFTPs[i]->local);
|
||||
// Are we finished sending?
|
||||
if (_activeSFTPs[i]->nread <= 0) {
|
||||
result = _activeSFTPs[i];
|
||||
arrdel(_activeSFTPs, i);
|
||||
|
@ -437,8 +325,8 @@ gboolean sshSFTPUpdate(gpointer userData) {
|
|||
// 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);
|
||||
while ((rc = (int)libssh2_sftp_write(_activeSFTPs[i]->sftpHandle, _activeSFTPs[i]->ptr, _activeSFTPs[i]->nread)) == LIBSSH2_ERROR_EAGAIN) {
|
||||
sshWaitSocket(_activeSFTPs[i]->sock, _activeSFTPs[i]->sshSession);
|
||||
}
|
||||
if (rc >= 0) {
|
||||
_activeSFTPs[i]->ptr += rc;
|
||||
|
@ -457,8 +345,8 @@ gboolean sshSFTPUpdate(gpointer userData) {
|
|||
// Downloading
|
||||
|
||||
// Data to read?
|
||||
while ((rc = libssh2_sftp_read(_activeSFTPs[i]->handle, _activeSFTPs[i]->buffer, sizeof(_activeSFTPs[i]->buffer))) == LIBSSH2_ERROR_EAGAIN) {
|
||||
sshWaitSocket(_activeSFTPs[i]->sshData->sock, _activeSFTPs[i]->sshData->session);
|
||||
while ((rc = libssh2_sftp_read(_activeSFTPs[i]->sftpHandle, _activeSFTPs[i]->buffer, sizeof(_activeSFTPs[i]->buffer))) == LIBSSH2_ERROR_EAGAIN) {
|
||||
sshWaitSocket(_activeSFTPs[i]->sock, _activeSFTPs[i]->sshSession);
|
||||
}
|
||||
if (rc > 0) {
|
||||
_activeSFTPs[i]->fileSize += rc;
|
||||
|
@ -476,12 +364,10 @@ gboolean sshSFTPUpdate(gpointer userData) {
|
|||
result->finished = TRUE;
|
||||
result->success = TRUE;
|
||||
fclose(result->local);
|
||||
libssh2_sftp_close(result->handle);
|
||||
libssh2_sftp_shutdown(result->session);
|
||||
libssh2_sftp_close(result->sftpHandle);
|
||||
if (result->callback) {
|
||||
result->callback(result);
|
||||
}
|
||||
DEL(result);
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
|
@ -489,14 +375,16 @@ gboolean sshSFTPUpdate(gpointer userData) {
|
|||
|
||||
|
||||
void sshShutdown(void) {
|
||||
//***TODO*** Any active sessions?
|
||||
|
||||
g_idle_remove_by_data(sshUpdate);
|
||||
// Any active sessions to disconnect?
|
||||
while (arrlen(_activeSFTPs) > 0) {
|
||||
sshDisconnect(&_activeSFTPs[0]);
|
||||
arrdel(_activeSFTPs, 0);
|
||||
}
|
||||
//ARRFREE(_activeSFTPs); // This is making Memwatch mad.
|
||||
|
||||
g_idle_remove_by_data(sshSFTPUpdate);
|
||||
|
||||
DEL(_output);
|
||||
DEL(_buffer);
|
||||
|
||||
libssh2_exit();
|
||||
}
|
||||
|
||||
|
@ -516,71 +404,10 @@ void sshStartup(void) {
|
|||
printf("libssh2 initialization failed: %d\n", err);
|
||||
}
|
||||
|
||||
utilEnsureBufferSize((unsigned char **)&_output, &_outputLen, 1024);
|
||||
utilEnsureBufferSize((unsigned char **)&_buffer, &_bufferLen, 0x4000);
|
||||
|
||||
g_idle_add(sshUpdate, sshUpdate);
|
||||
g_idle_add(sshSFTPUpdate, sshSFTPUpdate);
|
||||
}
|
||||
|
||||
|
||||
gboolean sshUpdate(gpointer userData) {
|
||||
int rc;
|
||||
int exitcode = 127;
|
||||
char *exitsignal = (char *)"none";
|
||||
SSHT *s;
|
||||
int i;
|
||||
|
||||
(void)userData;
|
||||
|
||||
_output[0] = 0;
|
||||
|
||||
for (i=0; i<arrlen(_activeSSHs); i++) {
|
||||
s = _activeSSHs[i];
|
||||
if (!s->finished) {
|
||||
rc = libssh2_channel_read(s->channel, _buffer, sizeof(_buffer));
|
||||
if (rc > 0) {
|
||||
utilEnsureBufferSize((unsigned char **)&_output, &_outputLen, rc + 1);
|
||||
_output[0] = 0;
|
||||
strncat(_output, (char *)_buffer, rc);
|
||||
//***TODO*** Display in status dialog
|
||||
//s->status->AddOutput(output);
|
||||
} else {
|
||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||
sshWaitSocket(s->sock, s->session);
|
||||
} else {
|
||||
while ((rc = libssh2_channel_close(s->channel)) == LIBSSH2_ERROR_EAGAIN) {
|
||||
sshWaitSocket(s->sock, s->session);
|
||||
}
|
||||
DEL(_output);
|
||||
_output = strdup("\n\nUH OH! Something wrong happened. Check the output for errors.");
|
||||
if (rc == 0) {
|
||||
exitcode = libssh2_channel_get_exit_status(s->channel);
|
||||
libssh2_channel_get_exit_signal(s->channel, &exitsignal, NULL, NULL, NULL, NULL, NULL);
|
||||
if (exitcode == 0) {
|
||||
DEL(_output);
|
||||
_output = strdup("\n\nFINISHED! You can close this window anytime.");
|
||||
}
|
||||
}
|
||||
//***TODO*** Display in status dialog
|
||||
//s->status->AddOutput(output);
|
||||
libssh2_channel_free(s->channel);
|
||||
s->result = exitcode;
|
||||
//s->finished = true;
|
||||
//s->status->Finished(); // No close
|
||||
if (s->callback) s->callback(s);
|
||||
arrdel(_activeSSHs, i);
|
||||
break; // Exit for loop
|
||||
// We don't delete "s" because it will be handled by utilSSHDisconnect
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
|
||||
static int sshWaitSocket(int socket_fd, LIBSSH2_SESSION *session) {
|
||||
struct timeval timeout;
|
||||
int rc;
|
||||
|
|
32
src/utils.c
32
src/utils.c
|
@ -76,6 +76,8 @@ char *utilCreateStringVArgs(char *format, va_list args) {
|
|||
vsnprintf(buffer, (size_t)size, format, args);
|
||||
}
|
||||
|
||||
//debug("%s = %s\n", format, buffer);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
@ -251,6 +253,35 @@ gboolean utilDecompressUpdate(gpointer userData) {
|
|||
}
|
||||
|
||||
|
||||
int utilDeleteTree(const char *path) {
|
||||
DIR *directory = opendir(path);
|
||||
char *filename = NULL;
|
||||
struct dirent *entry;
|
||||
int (*removeFunc)(const char *);
|
||||
|
||||
if (directory) {
|
||||
while ((entry = readdir(directory))) {
|
||||
if (!strcmp(".", entry->d_name) || !strcmp("..", entry->d_name)) {
|
||||
continue;
|
||||
}
|
||||
filename = utilCreateString("%s/%s", path, entry->d_name);
|
||||
removeFunc = entry->d_type == DT_DIR ? utilDeleteTree : remove;
|
||||
if (removeFunc(filename)) {
|
||||
DEL(filename);
|
||||
closedir(directory);
|
||||
return -1;
|
||||
}
|
||||
DEL(filename);
|
||||
}
|
||||
if (closedir(directory)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return remove(path);
|
||||
}
|
||||
|
||||
|
||||
char *utilDeobfuscateASCII(char *obfuscated) {
|
||||
char *deobfuscated = NULL;
|
||||
char *hostname;
|
||||
|
@ -874,6 +905,7 @@ gboolean utilWindowUnRegister(gpointer windowData) {
|
|||
debug("Window Unregistered: %ld\n", hmlen(_windowList));
|
||||
|
||||
DEL(w->filename);
|
||||
DEL(w->path);
|
||||
DEL(w->title);
|
||||
|
||||
return (result == 1) ? TRUE : FALSE;
|
||||
|
|
Loading…
Add table
Reference in a new issue