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;
|
} 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
|
#endif // ARRAY_H
|
||||||
|
|
|
@ -31,29 +31,19 @@
|
||||||
|
|
||||||
|
|
||||||
struct SFTPS;
|
struct SFTPS;
|
||||||
struct SSHS;
|
|
||||||
|
|
||||||
|
|
||||||
typedef void (*SFTPCallback)(struct SFTPS*);
|
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 {
|
typedef struct SFTPS {
|
||||||
SSHT *sshData;
|
LIBSSH2_SESSION *sshSession;
|
||||||
|
LIBSSH2_CHANNEL *sshChannel;
|
||||||
|
int sock;
|
||||||
void *userData;
|
void *userData;
|
||||||
FILE *local;
|
FILE *local;
|
||||||
LIBSSH2_SFTP *session;
|
LIBSSH2_SFTP *sftpSession;
|
||||||
LIBSSH2_SFTP_HANDLE *handle;
|
LIBSSH2_SFTP_HANDLE *sftpHandle;
|
||||||
char buffer[102400];
|
char buffer[102400];
|
||||||
char *ptr;
|
char *ptr;
|
||||||
uint64_t fileSize;
|
uint64_t fileSize;
|
||||||
|
@ -69,13 +59,12 @@ typedef struct SFTPS {
|
||||||
} SFTPT;
|
} SFTPT;
|
||||||
|
|
||||||
|
|
||||||
SSHT *sshConnect(char *hostname, uint16_t port, char *user, char *password);
|
SFTPT *sshConnect(char *hostname, uint16_t port, char *user, char *password);
|
||||||
void sshDisconnect(SSHT **sshData);
|
void sshDisconnect(SFTPT **sshData);
|
||||||
gboolean sshSFTPDelete(SSHT *sshData, char *target);
|
gboolean sshSFTPDelete(SFTPT *sshData, char *target);
|
||||||
//int sshExecute(SSHT *sshData, char *command, char **output);
|
gboolean sshSFTPFileExists(SFTPT *sshData, char *target);
|
||||||
gboolean sshSFTPFileExists(SSHT *sshData, char *target);
|
gboolean sshSFTPReceive(SFTPT *sshData, char *remote, char *local, SFTPCallback callback);
|
||||||
SFTPT *sshSFTPReceive(SSHT *sshData, char *remote, char *local, SFTPCallback callback);
|
gboolean sshSFTPSend(SFTPT *sshData, char *local, char *remote, SFTPCallback callback);
|
||||||
SFTPT *sshSFTPSend(SSHT *sshData, char *local, char *remote, SFTPCallback callback);
|
|
||||||
void sshShutdown(void);
|
void sshShutdown(void);
|
||||||
void sshStartup(void);
|
void sshStartup(void);
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,7 @@ extern char __utilFilenameBuffer[FILENAME_MAX];
|
||||||
char *utilCreateString(char *format, ...);
|
char *utilCreateString(char *format, ...);
|
||||||
char *utilCreateStringVArgs(char *format, va_list args);
|
char *utilCreateStringVArgs(char *format, va_list args);
|
||||||
ArchiveT *utilDecompress(char *archive, char *outPath, archiveCallback callback, void *userData);
|
ArchiveT *utilDecompress(char *archive, char *outPath, archiveCallback callback, void *userData);
|
||||||
|
int utilDeleteTree(const char *path);
|
||||||
char *utilDeobfuscateASCII(char *obfuscated);
|
char *utilDeobfuscateASCII(char *obfuscated);
|
||||||
void utilDequote(char *string);
|
void utilDequote(char *string);
|
||||||
void utilEnsureBufferSize(unsigned char **buffer, int *length, int wanted);
|
void utilEnsureBufferSize(unsigned char **buffer, int *length, int wanted);
|
||||||
|
|
|
@ -55,6 +55,8 @@ void message(MessageTypesT level, char *format, ...) {
|
||||||
msg = utilCreateStringVArgs(format, args);
|
msg = utilCreateStringVArgs(format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
|
debug("%s\n", msg);
|
||||||
|
|
||||||
// Break multiline messages down into individual lines.
|
// Break multiline messages down into individual lines.
|
||||||
tok = strtok(msg, "\n");
|
tok = strtok(msg, "\n");
|
||||||
while (tok != NULL) {
|
while (tok != NULL) {
|
||||||
|
@ -68,6 +70,8 @@ void message(MessageTypesT level, char *format, ...) {
|
||||||
|
|
||||||
tok = strtok(NULL, "\n");
|
tok = strtok(NULL, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEL(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -209,7 +213,7 @@ static void winMessagesDelete(gpointer userData) {
|
||||||
DEL(_pendingMessages[0]);
|
DEL(_pendingMessages[0]);
|
||||||
arrdel(_pendingMessages, 0);
|
arrdel(_pendingMessages, 0);
|
||||||
}
|
}
|
||||||
ARRFREE(_pendingMessages);
|
//ARRFREE(_pendingMessages); // This is making Memwatch mad.
|
||||||
|
|
||||||
utilWindowUnRegister(userData);
|
utilWindowUnRegister(userData);
|
||||||
_lstMessages = NULL;
|
_lstMessages = NULL;
|
||||||
|
|
|
@ -242,9 +242,10 @@ static void clearRecipeData(ProjectDataT *self) {
|
||||||
while (arrlen(self->recipes) > 0) {
|
while (arrlen(self->recipes) > 0) {
|
||||||
DEL(self->recipes[0]->key);
|
DEL(self->recipes[0]->key);
|
||||||
DEL(self->recipes[0]->value);
|
DEL(self->recipes[0]->value);
|
||||||
|
DEL(self->recipes[0]);
|
||||||
arrdel(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 this is not first call, process context.
|
||||||
if (self->tempInteger != -1) {
|
if (self->tempInteger != -1) {
|
||||||
if (ctx->programResult != 0) {
|
if (ctx->programResult != 0) {
|
||||||
//***TODO*** Not all negative returns are severe.
|
message(MSG_ERROR, "Recipe %s returned %d", self->recipes[self->tempInteger]->value, ctx->programResult);
|
||||||
message(ctx->programResult > 0 ? MSG_ERROR : MSG_SEVERE, "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];
|
char temp[6];
|
||||||
int result = 0;
|
int result = 0;
|
||||||
SSHT *ssh = NULL;
|
SFTPT *ssh = NULL;
|
||||||
char *error = NULL;
|
char *error = NULL;
|
||||||
|
|
||||||
(void)object;
|
(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));
|
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(self->treeProject));
|
||||||
GtkTreeIter iter;
|
GtkTreeIter iter;
|
||||||
GtkTreeIter child;
|
GtkTreeIter child;
|
||||||
SSHT *ssh;
|
SFTPT *ssh;
|
||||||
SFTPT *sftp;
|
|
||||||
char *temp;
|
char *temp;
|
||||||
char *filename;
|
char *filename;
|
||||||
char *pathString;
|
char *pathString;
|
||||||
|
@ -1081,7 +1080,6 @@ EVENT void menuProjectBuildBuild(GtkWidget *object, gpointer userData) {
|
||||||
gboolean archPrinted;
|
gboolean archPrinted;
|
||||||
FILE *out;
|
FILE *out;
|
||||||
|
|
||||||
ssh = NEW(SSHT);
|
|
||||||
ssh = sshConnect(self->buildHost, self->buildSSHPort, self->buildUser, self->buildPassword);
|
ssh = sshConnect(self->buildHost, self->buildSSHPort, self->buildUser, self->buildPassword);
|
||||||
|
|
||||||
if (!ssh) {
|
if (!ssh) {
|
||||||
|
@ -1101,6 +1099,7 @@ EVENT void menuProjectBuildBuild(GtkWidget *object, gpointer userData) {
|
||||||
message(MSG_SEVERE, "Unable to write temporary build.start file");
|
message(MSG_SEVERE, "Unable to write temporary build.start file");
|
||||||
unlink(buildStart); // Just in case.
|
unlink(buildStart); // Just in case.
|
||||||
message(MSG_INFO, "Build canceled");
|
message(MSG_INFO, "Build canceled");
|
||||||
|
DEL(buildStart);
|
||||||
sshDisconnect(&ssh);
|
sshDisconnect(&ssh);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1138,7 +1137,7 @@ EVENT void menuProjectBuildBuild(GtkWidget *object, gpointer userData) {
|
||||||
temp = utilCreateString("%s%s", self->windowData.path, filename);
|
temp = utilCreateString("%s%s", self->windowData.path, filename);
|
||||||
arrput(_sendList, temp);
|
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, &child));
|
||||||
}
|
}
|
||||||
} while (gtk_tree_model_iter_next(model, &iter));
|
} while (gtk_tree_model_iter_next(model, &iter));
|
||||||
|
@ -1147,10 +1146,8 @@ EVENT void menuProjectBuildBuild(GtkWidget *object, gpointer userData) {
|
||||||
arrput(_sendList, buildStart);
|
arrput(_sendList, buildStart);
|
||||||
|
|
||||||
// Prime the pump! We only set sshData and userData so sendSFTP can determine this is the first file.
|
// Prime the pump! We only set sshData and userData so sendSFTP can determine this is the first file.
|
||||||
sftp = NEW(SFTPT);
|
ssh->userData = self;
|
||||||
sftp->sshData = ssh;
|
sendSFTP(ssh);
|
||||||
sftp->userData = self;
|
|
||||||
sendSFTP(sftp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1181,10 +1178,10 @@ gboolean projectAddToTree(ProjectDataT *self, char *filename) {
|
||||||
do {
|
do {
|
||||||
gtk_tree_model_get(model, &child, COL_FILENAME, &temp, -1);
|
gtk_tree_model_get(model, &child, COL_FILENAME, &temp, -1);
|
||||||
if (strcmp(temp, filename) == 0) {
|
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.
|
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, &child));
|
||||||
}
|
}
|
||||||
} while (gtk_tree_model_iter_next(model, &iter));
|
} 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;
|
fileLen = 0;
|
||||||
utilEnsureBufferSize((unsigned char **)&temp, &fileLen, 4); // fileLen is just a throwaway here.
|
utilEnsureBufferSize((unsigned char **)&temp, &fileLen, 4); // fileLen is just a throwaway here.
|
||||||
snprintf(temp, 4, "%d", foundAt);
|
snprintf(temp, 4, "%d", foundAt);
|
||||||
|
@ -1224,8 +1221,10 @@ static void receiveSFTP(SFTPT *sftp) {
|
||||||
if (sftp->finished) {
|
if (sftp->finished) {
|
||||||
if (sftp->success) {
|
if (sftp->success) {
|
||||||
message(MSG_INFO, "Cleaning up remote build");
|
message(MSG_INFO, "Cleaning up remote build");
|
||||||
sshSFTPDelete(sftp->sshData, REMOTE_BUILD_RESULTS);
|
sshSFTPDelete(sftp, REMOTE_BUILD_RESULTS);
|
||||||
//***TODO*** Delete any local "results" folder.
|
temp = utilCreateString("%sresults", self->windowData.path);
|
||||||
|
utilDeleteTree(temp);
|
||||||
|
DEL(temp);
|
||||||
message(MSG_INFO, "Unpacking build");
|
message(MSG_INFO, "Unpacking build");
|
||||||
temp = utilCreateString("%s%s", self->windowData.path, LOCAL_BUILD_RESULTS);
|
temp = utilCreateString("%s%s", self->windowData.path, LOCAL_BUILD_RESULTS);
|
||||||
utilDecompress(temp, self->windowData.path, decompressBuild, self);
|
utilDecompress(temp, self->windowData.path, decompressBuild, self);
|
||||||
|
@ -1233,11 +1232,8 @@ static void receiveSFTP(SFTPT *sftp) {
|
||||||
} else {
|
} else {
|
||||||
message(MSG_ERROR, "Receiving %s from build server - FAILED", sftp->remoteName);
|
message(MSG_ERROR, "Receiving %s from build server - FAILED", sftp->remoteName);
|
||||||
message(MSG_INFO, "Build canceled");
|
message(MSG_INFO, "Build canceled");
|
||||||
sshDisconnect(&sftp->sshData);
|
|
||||||
}
|
}
|
||||||
DEL(sftp->localName);
|
sshDisconnect(&sftp);
|
||||||
DEL(sftp->remoteName);
|
|
||||||
DEL(sftp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1406,13 +1402,9 @@ static gboolean updateBuildOptions(ProjectDataT *self) {
|
||||||
|
|
||||||
static void sendSFTP(SFTPT *sftp) {
|
static void sendSFTP(SFTPT *sftp) {
|
||||||
ProjectDataT *self = (ProjectDataT *)sftp->userData;
|
ProjectDataT *self = (ProjectDataT *)sftp->userData;
|
||||||
SFTPT *last;
|
|
||||||
SFTPT *next;
|
|
||||||
char *target;
|
char *target;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
last = sftp;
|
|
||||||
|
|
||||||
// If source and target are missing, this is the first file - start sending.
|
// If source and target are missing, this is the first file - start sending.
|
||||||
// Or, did the current transfer succeed? If so, send next file.
|
// Or, did the current transfer succeed? If so, send next file.
|
||||||
if ((sftp->localName == NULL && sftp->remoteName == NULL) || (sftp->finished && sftp->success)) {
|
if ((sftp->localName == NULL && sftp->remoteName == NULL) || (sftp->finished && sftp->success)) {
|
||||||
|
@ -1425,19 +1417,15 @@ static void sendSFTP(SFTPT *sftp) {
|
||||||
name = utilFileBasename(_sendList[0]);
|
name = utilFileBasename(_sendList[0]);
|
||||||
target = utilCreateString("build/%s", name);
|
target = utilCreateString("build/%s", name);
|
||||||
message(MSG_INFO, "Sending %s to build server", name);
|
message(MSG_INFO, "Sending %s to build server", name);
|
||||||
sftp = sshSFTPSend(last->sshData, _sendList[0], target, sendSFTP);
|
sshSFTPSend(sftp, _sendList[0], target, sendSFTP);
|
||||||
sftp->userData = self;
|
|
||||||
DEL(target);
|
DEL(target);
|
||||||
DEL(name);
|
DEL(name);
|
||||||
|
DEL(_sendList[0]);
|
||||||
arrdel(_sendList, 0);
|
arrdel(_sendList, 0);
|
||||||
} else {
|
} else {
|
||||||
// Finished!
|
// Finished!
|
||||||
message(MSG_INFO, "Waiting for build to complete");
|
message(MSG_INFO, "Waiting for build to complete");
|
||||||
// "last" will be deleted by sshSFTPUpdate so copy what we need to "next".
|
g_timeout_add_seconds(5, waitForBuild, sftp);
|
||||||
next = NEW(SFTPT);
|
|
||||||
next->sshData = last->sshData;
|
|
||||||
next->userData = last->userData;
|
|
||||||
g_timeout_add_seconds(5, waitForBuild, next);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1447,21 +1435,14 @@ static void sendSFTP(SFTPT *sftp) {
|
||||||
message(MSG_ERROR, "Sending %s to build server - FAILED", sftp->remoteName);
|
message(MSG_ERROR, "Sending %s to build server - FAILED", sftp->remoteName);
|
||||||
}
|
}
|
||||||
message(MSG_INFO, "Build canceled");
|
message(MSG_INFO, "Build canceled");
|
||||||
sshDisconnect(&last->sshData);
|
sshDisconnect(&sftp);
|
||||||
// Clear any remaining transfers.
|
// Clear any remaining transfers.
|
||||||
while (arrlen(_sendList) > 0) {
|
while (arrlen(_sendList) > 0) {
|
||||||
|
DEL(_sendList[0]);
|
||||||
arrdel(_sendList, 0);
|
arrdel(_sendList, 0);
|
||||||
}
|
}
|
||||||
ARRFREE(_sendList);
|
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) {
|
static gboolean waitForBuild(gpointer userData) {
|
||||||
SFTPT *last = (SFTPT *)userData;
|
SFTPT *sftp = (SFTPT *)userData;
|
||||||
ProjectDataT *self = (ProjectDataT *)last->userData;
|
ProjectDataT *self = (ProjectDataT *)sftp->userData;
|
||||||
SFTPT *sftp;
|
|
||||||
char *temp;
|
char *temp;
|
||||||
|
gboolean result;
|
||||||
|
|
||||||
if (sshSFTPFileExists(last->sshData, REMOTE_BUILD_RESULTS)) {
|
if (sshSFTPFileExists(sftp, REMOTE_BUILD_RESULTS)) {
|
||||||
// Build complete! Next step!
|
// Build complete! Next step!
|
||||||
//***TODO*** Delete any local build archive.
|
|
||||||
message(MSG_INFO, "Retrieving build results");
|
message(MSG_INFO, "Retrieving build results");
|
||||||
temp = utilCreateString("%s%s", self->windowData.path, LOCAL_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);
|
DEL(temp);
|
||||||
if (!sftp) {
|
if (!result) {
|
||||||
message(MSG_ERROR, "Receiving build from build server - FAILED");
|
message(MSG_ERROR, "Receiving build from build server - FAILED");
|
||||||
message(MSG_INFO, "Build canceled");
|
message(MSG_INFO, "Build canceled");
|
||||||
sshDisconnect(&last->sshData);
|
sshDisconnect(&sftp);
|
||||||
} else {
|
|
||||||
sftp->userData = last->userData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally finished with "last"
|
|
||||||
DEL(last->localName);
|
|
||||||
DEL(last->remoteName);
|
|
||||||
DEL(last);
|
|
||||||
|
|
||||||
return G_SOURCE_REMOVE;
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1627,6 +1601,8 @@ static void winProjectDelete(gpointer userData) {
|
||||||
targetArrayDelete(&self->targets);
|
targetArrayDelete(&self->targets);
|
||||||
clearRecipeData(self);
|
clearRecipeData(self);
|
||||||
|
|
||||||
|
DEL(self->projectName);
|
||||||
|
DEL(self->projectType);
|
||||||
DEL(self->buildHost);
|
DEL(self->buildHost);
|
||||||
DEL(self->buildUser);
|
DEL(self->buildUser);
|
||||||
DEL(self->buildPassword);
|
DEL(self->buildPassword);
|
||||||
|
|
333
src/ssh.c
333
src/ssh.c
|
@ -40,25 +40,19 @@ closesocket(data->sock);
|
||||||
|
|
||||||
|
|
||||||
static SFTPT **_activeSFTPs = NULL;
|
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 gboolean sshSFTPTransfer(SFTPT *sshData, char *local, char *remote, SFTPCallback callback, gboolean uploading);
|
||||||
static SFTPT *sshSFTPTransfer(SSHT *sshData, char *local, char *remote, SFTPCallback callback, gboolean uploading);
|
|
||||||
gboolean sshSFTPUpdate(gpointer userData); // Not static
|
gboolean sshSFTPUpdate(gpointer userData); // Not static
|
||||||
static int sshWaitSocket(int socket_fd, LIBSSH2_SESSION *session);
|
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;
|
int rc;
|
||||||
struct hostent *hostent;
|
struct hostent *hostent;
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
in_addr_t hostaddr;
|
in_addr_t hostaddr;
|
||||||
SSHT *data = NULL;
|
SFTPT *data = NULL;
|
||||||
|
|
||||||
hostent = gethostbyname(hostname);
|
hostent = gethostbyname(hostname);
|
||||||
if (hostent == NULL) {
|
if (hostent == NULL) {
|
||||||
|
@ -72,7 +66,7 @@ SSHT *sshConnect(char *hostname, uint16_t port, char *user, char *password) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = NEW(SSHT);
|
data = NEW(SFTPT);
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
data->sock = socket(AF_INET, SOCK_STREAM, 0);
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->session = libssh2_session_init();
|
data->sshSession = libssh2_session_init();
|
||||||
if (!data->session) {
|
if (!data->sshSession) {
|
||||||
socketclose(data->sock);
|
socketclose(data->sock);
|
||||||
DEL(data);
|
DEL(data);
|
||||||
return NULL;
|
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) {
|
if (rc) {
|
||||||
message(MSG_ERROR, "Failure establishing SSH session: %d\n", rc);
|
message(MSG_ERROR, "Failure establishing SSH session: %d\n", rc);
|
||||||
libssh2_session_free(data->session);
|
libssh2_session_free(data->sshSession);
|
||||||
socketclose(data->sock);
|
socketclose(data->sock);
|
||||||
DEL(data);
|
DEL(data);
|
||||||
return NULL;
|
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) {
|
if (rc) {
|
||||||
message(MSG_ERROR, "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)
|
while (libssh2_session_disconnect(data->sshSession, "Error") == LIBSSH2_ERROR_EAGAIN)
|
||||||
;
|
;
|
||||||
libssh2_session_free(data->session);
|
libssh2_session_free(data->sshSession);
|
||||||
socketclose(data->sock);
|
socketclose(data->sock);
|
||||||
DEL(data);
|
DEL(data);
|
||||||
return NULL;
|
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;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void sshDisconnect(SSHT **sshData) {
|
void sshDisconnect(SFTPT **sshData) {
|
||||||
SSHT *data = *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_disconnect(data->sshSession, "Normal Shutdown.");
|
||||||
libssh2_session_free(data->session);
|
libssh2_session_free(data->sshSession);
|
||||||
socketclose(data->sock);
|
socketclose(data->sock);
|
||||||
|
|
||||||
|
DEL(data->localName);
|
||||||
|
DEL(data->remoteName);
|
||||||
|
|
||||||
DEL(data);
|
DEL(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gboolean sshSFTPDelete(SSHT *sshData, char *target) {
|
gboolean sshSFTPDelete(SFTPT *sshData, char *target) {
|
||||||
LIBSSH2_SFTP *session;
|
|
||||||
int rc;
|
int rc;
|
||||||
gboolean result = TRUE;
|
gboolean result = TRUE;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
session = libssh2_sftp_init(sshData->session);
|
rc = libssh2_sftp_unlink(sshData->sftpSession, target);
|
||||||
if (!session) {
|
|
||||||
if (libssh2_session_last_errno(sshData->session) != LIBSSH2_ERROR_EAGAIN) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (!session);
|
|
||||||
|
|
||||||
do {
|
|
||||||
rc = libssh2_sftp_unlink(session, target);
|
|
||||||
if (rc == 0) break;
|
if (rc == 0) break;
|
||||||
if (rc != LIBSSH2_ERROR_EAGAIN) {
|
if (rc != LIBSSH2_ERROR_EAGAIN) {
|
||||||
result = FALSE;
|
result = FALSE;
|
||||||
|
@ -160,96 +157,11 @@ gboolean sshSFTPDelete(SSHT *sshData, char *target) {
|
||||||
}
|
}
|
||||||
} while (TRUE);
|
} while (TRUE);
|
||||||
|
|
||||||
libssh2_sftp_shutdown(session);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
gboolean sshSFTPFileExists(SFTPT *sshData, char *target) {
|
||||||
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;
|
|
||||||
LIBSSH2_SFTP_HANDLE *handle;
|
LIBSSH2_SFTP_HANDLE *handle;
|
||||||
LIBSSH2_SFTP_ATTRIBUTES attrs;
|
LIBSSH2_SFTP_ATTRIBUTES attrs;
|
||||||
char *path;
|
char *path;
|
||||||
|
@ -259,15 +171,6 @@ gboolean sshSFTPFileExists(SSHT *sshData, char *target) {
|
||||||
int rc;
|
int rc;
|
||||||
gboolean result = FALSE;
|
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.
|
// Split filename and path.
|
||||||
// Cannot use utilFilePath and friends because this is a remote path.
|
// Cannot use utilFilePath and friends because this is a remote path.
|
||||||
temp = strdup(target); // Make copy in case they pass in a constant.
|
temp = strdup(target); // Make copy in case they pass in a constant.
|
||||||
|
@ -289,9 +192,8 @@ gboolean sshSFTPFileExists(SSHT *sshData, char *target) {
|
||||||
DEL(temp);
|
DEL(temp);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
handle = libssh2_sftp_opendir(session, path);
|
handle = libssh2_sftp_opendir(sshData->sftpSession, path);
|
||||||
if ((!handle) && (libssh2_session_last_errno(sshData->session) != LIBSSH2_ERROR_EAGAIN)) {
|
if ((!handle) && (libssh2_session_last_errno(sshData->sshSession) != LIBSSH2_ERROR_EAGAIN)) {
|
||||||
libssh2_sftp_shutdown(session);
|
|
||||||
free(file);
|
free(file);
|
||||||
free(path);
|
free(path);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -322,91 +224,76 @@ gboolean sshSFTPFileExists(SSHT *sshData, char *target) {
|
||||||
free(path);
|
free(path);
|
||||||
|
|
||||||
libssh2_sftp_closedir(handle);
|
libssh2_sftp_closedir(handle);
|
||||||
libssh2_sftp_shutdown(session);
|
|
||||||
|
|
||||||
return result;
|
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);
|
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);
|
return sshSFTPTransfer(sshData, local, remote, callback, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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) {
|
||||||
SFTPT *sftp = NULL;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// Do not allow two of the same transfers to be started.
|
// Do not allow two of the same transfers to be started.
|
||||||
for (i=0; i<arrlen(_activeSFTPs); i++) {
|
for (i=0; i<arrlen(_activeSFTPs); i++) {
|
||||||
if ((strcmp(_activeSFTPs[i]->localName, local) == 0) && (strcmp(_activeSFTPs[i]->remoteName, remote) == 0)) {
|
if ((strcmp(_activeSFTPs[i]->localName, local) == 0) && (strcmp(_activeSFTPs[i]->remoteName, remote) == 0)) {
|
||||||
// Return existing transfer handle.
|
// Return existing transfer is running.
|
||||||
return _activeSFTPs[i];
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sftp = NEW(SFTPT);
|
if (sshData) {
|
||||||
|
sshData->fileSize = uploading ? utilFileSize(local) : 0;
|
||||||
if (sftp) {
|
sshData->local = fopen(local, uploading ? "rb" : "wb");
|
||||||
sftp->fileSize = uploading ? utilFileSize(local) : 0;
|
if (sshData->local) {
|
||||||
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);
|
|
||||||
do {
|
do {
|
||||||
if (uploading) {
|
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_FXF_WRITE | LIBSSH2_FXF_CREAT | LIBSSH2_FXF_TRUNC,
|
||||||
LIBSSH2_SFTP_S_IRUSR | LIBSSH2_SFTP_S_IWUSR | LIBSSH2_SFTP_S_IRGRP |
|
LIBSSH2_SFTP_S_IRUSR | LIBSSH2_SFTP_S_IWUSR | LIBSSH2_SFTP_S_IRGRP |
|
||||||
LIBSSH2_SFTP_S_IROTH);
|
LIBSSH2_SFTP_S_IROTH);
|
||||||
} else {
|
} else {
|
||||||
sftp->handle = libssh2_sftp_open(sftp->session, sftp->remoteName,
|
sshData->sftpHandle = libssh2_sftp_open(sshData->sftpSession, remote,
|
||||||
LIBSSH2_FXF_READ,
|
LIBSSH2_FXF_READ,
|
||||||
LIBSSH2_SFTP_S_IRUSR | LIBSSH2_SFTP_S_IWUSR | LIBSSH2_SFTP_S_IRGRP |
|
LIBSSH2_SFTP_S_IRUSR | LIBSSH2_SFTP_S_IWUSR | LIBSSH2_SFTP_S_IRGRP |
|
||||||
LIBSSH2_SFTP_S_IROTH);
|
LIBSSH2_SFTP_S_IROTH);
|
||||||
}
|
}
|
||||||
if (!sftp->handle) {
|
if (!sshData->sftpHandle) {
|
||||||
if (libssh2_session_last_errno(sshData->session) != LIBSSH2_ERROR_EAGAIN) {
|
if (libssh2_session_last_errno(sshData->sshSession) != LIBSSH2_ERROR_EAGAIN) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (!sftp->handle);
|
} while (!sshData->sftpHandle);
|
||||||
if (sftp->handle) {
|
if (sshData->sftpHandle) {
|
||||||
arrput(_activeSFTPs, sftp);
|
DEL(sshData->localName);
|
||||||
return sftp;
|
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 {
|
} else {
|
||||||
message(MSG_SEVERE, "Failed to get SFTP handle! %d, %lu\n", libssh2_session_last_errno(sshData->session), libssh2_sftp_last_error(sftp->session));
|
message(MSG_SEVERE, "Failed to get SFTP handle! %d, %lu\n", libssh2_session_last_errno(sshData->sshSession), libssh2_sftp_last_error(sshData->sftpSession));
|
||||||
libssh2_sftp_shutdown(sftp->session);
|
|
||||||
DEL(sftp);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
DEL(sftp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -425,6 +312,7 @@ gboolean sshSFTPUpdate(gpointer userData) {
|
||||||
// More data to read?
|
// More data to read?
|
||||||
if (_activeSFTPs[i]->readMore) {
|
if (_activeSFTPs[i]->readMore) {
|
||||||
_activeSFTPs[i]->nread = fread(_activeSFTPs[i]->buffer, 1, sizeof(_activeSFTPs[i]->buffer), _activeSFTPs[i]->local);
|
_activeSFTPs[i]->nread = fread(_activeSFTPs[i]->buffer, 1, sizeof(_activeSFTPs[i]->buffer), _activeSFTPs[i]->local);
|
||||||
|
// Are we finished sending?
|
||||||
if (_activeSFTPs[i]->nread <= 0) {
|
if (_activeSFTPs[i]->nread <= 0) {
|
||||||
result = _activeSFTPs[i];
|
result = _activeSFTPs[i];
|
||||||
arrdel(_activeSFTPs, i);
|
arrdel(_activeSFTPs, i);
|
||||||
|
@ -437,8 +325,8 @@ gboolean sshSFTPUpdate(gpointer userData) {
|
||||||
// Is there data to send?
|
// Is there data to send?
|
||||||
if (_activeSFTPs[i]->nread > 0) {
|
if (_activeSFTPs[i]->nread > 0) {
|
||||||
// Send data.
|
// Send data.
|
||||||
while ((rc = (int)libssh2_sftp_write(_activeSFTPs[i]->handle, _activeSFTPs[i]->ptr, _activeSFTPs[i]->nread)) == LIBSSH2_ERROR_EAGAIN) {
|
while ((rc = (int)libssh2_sftp_write(_activeSFTPs[i]->sftpHandle, _activeSFTPs[i]->ptr, _activeSFTPs[i]->nread)) == LIBSSH2_ERROR_EAGAIN) {
|
||||||
sshWaitSocket(_activeSFTPs[i]->sshData->sock, _activeSFTPs[i]->sshData->session);
|
sshWaitSocket(_activeSFTPs[i]->sock, _activeSFTPs[i]->sshSession);
|
||||||
}
|
}
|
||||||
if (rc >= 0) {
|
if (rc >= 0) {
|
||||||
_activeSFTPs[i]->ptr += rc;
|
_activeSFTPs[i]->ptr += rc;
|
||||||
|
@ -457,8 +345,8 @@ gboolean sshSFTPUpdate(gpointer userData) {
|
||||||
// Downloading
|
// Downloading
|
||||||
|
|
||||||
// Data to read?
|
// Data to read?
|
||||||
while ((rc = libssh2_sftp_read(_activeSFTPs[i]->handle, _activeSFTPs[i]->buffer, sizeof(_activeSFTPs[i]->buffer))) == LIBSSH2_ERROR_EAGAIN) {
|
while ((rc = libssh2_sftp_read(_activeSFTPs[i]->sftpHandle, _activeSFTPs[i]->buffer, sizeof(_activeSFTPs[i]->buffer))) == LIBSSH2_ERROR_EAGAIN) {
|
||||||
sshWaitSocket(_activeSFTPs[i]->sshData->sock, _activeSFTPs[i]->sshData->session);
|
sshWaitSocket(_activeSFTPs[i]->sock, _activeSFTPs[i]->sshSession);
|
||||||
}
|
}
|
||||||
if (rc > 0) {
|
if (rc > 0) {
|
||||||
_activeSFTPs[i]->fileSize += rc;
|
_activeSFTPs[i]->fileSize += rc;
|
||||||
|
@ -476,12 +364,10 @@ gboolean sshSFTPUpdate(gpointer userData) {
|
||||||
result->finished = TRUE;
|
result->finished = TRUE;
|
||||||
result->success = TRUE;
|
result->success = TRUE;
|
||||||
fclose(result->local);
|
fclose(result->local);
|
||||||
libssh2_sftp_close(result->handle);
|
libssh2_sftp_close(result->sftpHandle);
|
||||||
libssh2_sftp_shutdown(result->session);
|
|
||||||
if (result->callback) {
|
if (result->callback) {
|
||||||
result->callback(result);
|
result->callback(result);
|
||||||
}
|
}
|
||||||
DEL(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return G_SOURCE_CONTINUE;
|
return G_SOURCE_CONTINUE;
|
||||||
|
@ -489,14 +375,16 @@ gboolean sshSFTPUpdate(gpointer userData) {
|
||||||
|
|
||||||
|
|
||||||
void sshShutdown(void) {
|
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);
|
g_idle_remove_by_data(sshSFTPUpdate);
|
||||||
|
|
||||||
DEL(_output);
|
|
||||||
DEL(_buffer);
|
|
||||||
|
|
||||||
libssh2_exit();
|
libssh2_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,71 +404,10 @@ void sshStartup(void) {
|
||||||
printf("libssh2 initialization failed: %d\n", err);
|
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);
|
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) {
|
static int sshWaitSocket(int socket_fd, LIBSSH2_SESSION *session) {
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
int rc;
|
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);
|
vsnprintf(buffer, (size_t)size, format, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//debug("%s = %s\n", format, buffer);
|
||||||
|
|
||||||
return 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 *utilDeobfuscateASCII(char *obfuscated) {
|
||||||
char *deobfuscated = NULL;
|
char *deobfuscated = NULL;
|
||||||
char *hostname;
|
char *hostname;
|
||||||
|
@ -874,6 +905,7 @@ gboolean utilWindowUnRegister(gpointer windowData) {
|
||||||
debug("Window Unregistered: %ld\n", hmlen(_windowList));
|
debug("Window Unregistered: %ld\n", hmlen(_windowList));
|
||||||
|
|
||||||
DEL(w->filename);
|
DEL(w->filename);
|
||||||
|
DEL(w->path);
|
||||||
DEL(w->title);
|
DEL(w->title);
|
||||||
|
|
||||||
return (result == 1) ? TRUE : FALSE;
|
return (result == 1) ? TRUE : FALSE;
|
||||||
|
|
Loading…
Add table
Reference in a new issue