Builds being sent and received over SFTP! Now to unpack them!

This commit is contained in:
Scott Duensing 2023-05-03 20:44:44 -05:00
parent f34af2f6ff
commit 8de2ffc18f
6 changed files with 253 additions and 82 deletions

View file

@ -44,9 +44,7 @@ typedef struct SSHS {
int sock; int sock;
int result; int result;
gboolean finished; gboolean finished;
char *title;
SSHCallback callback; SSHCallback callback;
GtkWidget *status;
} SSHT; } SSHT;
@ -61,14 +59,12 @@ typedef struct SFTPS {
uint64_t fileSize; uint64_t fileSize;
uint64_t fileSent; uint64_t fileSent;
size_t nread; size_t nread;
char *source; char *localName;
char *target; char *remoteName;
char *title;
gboolean uploading; gboolean uploading;
gboolean readMore; gboolean readMore;
gboolean finished; gboolean finished;
gboolean success; gboolean success;
GtkWidget *status;
SFTPCallback callback; SFTPCallback callback;
} SFTPT; } SFTPT;
@ -77,7 +73,8 @@ SSHT *sshConnect(char *hostname, uint16_t port, char *user, char *password);
void sshDisconnect(SSHT **sshData); void sshDisconnect(SSHT **sshData);
//int sshExecute(SSHT *sshData, char *command, char **output); //int sshExecute(SSHT *sshData, char *command, char **output);
gboolean sshSFTPFileExists(SSHT *sshData, char *target); gboolean sshSFTPFileExists(SSHT *sshData, char *target);
SFTPT *sshSFTPSend(char *title, SSHT *sshData, char *source, char *target, SFTPCallback callback); SFTPT *sshSFTPReceive(SSHT *sshData, char *remote, char *local, SFTPCallback callback);
SFTPT *sshSFTPSend(SSHT *sshData, char *local, char *remote, SFTPCallback callback);
void sshShutdown(void); void sshShutdown(void);
void sshStartup(void); void sshStartup(void);

View file

@ -53,6 +53,7 @@ gboolean utilFileSaveAs(WindowDataT *self, char *extension, char *what);
gboolean utilFileSaveOtherAs(WindowDataT *self, char *extension, char *what, char **filename); gboolean utilFileSaveOtherAs(WindowDataT *self, char *extension, char *what, char **filename);
size_t utilFileSize(char *filename); size_t utilFileSize(char *filename);
GtkWidget *utilFindChildWidget(GtkWidget *parent, const gchar *name); GtkWidget *utilFindChildWidget(GtkWidget *parent, const gchar *name);
void utilForceUpdate(void);
char *utilGetToken(char *input, char *delimit, char *openblock, char *closeblock); char *utilGetToken(char *input, char *delimit, char *openblock, char *closeblock);
WindowDataT *utilGetWindowData(GtkWidget *window); WindowDataT *utilGetWindowData(GtkWidget *window);
gboolean utilGetWidgetsFromMemory(char *resource, char *name[], GtkWidget **widgets[], gpointer userData); gboolean utilGetWidgetsFromMemory(char *resource, char *name[], GtkWidget **widgets[], gpointer userData);

View file

@ -26,8 +26,10 @@
static GtkWidget *_lstMessages = NULL; static GtkWidget *_lstMessages = NULL;
static int _autoScroll = 0;
static gboolean messagesScroll(gpointer userData);
EVENT gboolean winMessagesClose(GtkWidget *object, gpointer userData); EVENT gboolean winMessagesClose(GtkWidget *object, gpointer userData);
static void winMessagesDelete(gpointer userData); static void winMessagesDelete(gpointer userData);
@ -43,19 +45,19 @@ void message(MessageTypesT level, char *format, ...) {
NULL, NULL,
&_lstMessages &_lstMessages
}; };
GtkWidget *row; GtkWidget *row;
GtkWidget *box; GtkWidget *box;
GtkWidget *label; GtkWidget *label;
va_list args; va_list args;
char *string; char *string;
char *msg; char *msg;
char *tok; char *tok;
char *labels[MSG_COUNT] = { char *labels[MSG_COUNT] = {
"<span foreground=\"gray\"> Info:</span>", "<span foreground=\"gray\"> Info:</span>",
"<span foreground=\"yellow\">Warning:</span>", "<span foreground=\"yellow\">Warning:</span>",
"<span foreground=\"red\"> Error:</span>", "<span foreground=\"red\"> Error:</span>",
"<span foreground=\"red\"><b> Severe:</b></span>" "<span foreground=\"red\"><b> Severe:</b></span>"
}; };
// Do we need to open this window? // Do we need to open this window?
if (!_lstMessages) { if (!_lstMessages) {
@ -71,6 +73,9 @@ void message(MessageTypesT level, char *format, ...) {
// Show window. // Show window.
gtk_widget_show_all(self->window); gtk_widget_show_all(self->window);
// Set up automatic scrolling.
g_idle_add(messagesScroll, messagesScroll);
} }
// Display message. // Display message.
@ -96,13 +101,35 @@ void message(MessageTypesT level, char *format, ...) {
gtk_container_add(GTK_CONTAINER(row), box); gtk_container_add(GTK_CONTAINER(row), box);
gtk_list_box_insert(GTK_LIST_BOX(_lstMessages), row, -1); gtk_list_box_insert(GTK_LIST_BOX(_lstMessages), row, -1);
// Force paint.
gtk_widget_show_all(row); gtk_widget_show_all(row);
utilForceUpdate();
_autoScroll = 5; // Try 5 times to show the new row.
tok = strtok(NULL, "\n"); tok = strtok(NULL, "\n");
} }
} }
static gboolean messagesScroll(gpointer userData) {
GtkAdjustment *adjustment;
(void)userData;
if (_autoScroll <= 0) return G_SOURCE_CONTINUE;
// Scroll to show new line.
adjustment = gtk_list_box_get_adjustment(GTK_LIST_BOX(_lstMessages));
gtk_adjustment_set_value(adjustment, gtk_adjustment_get_upper(adjustment));
gtk_widget_show_all(_lstMessages);
utilForceUpdate();
_autoScroll--;
return G_SOURCE_CONTINUE;
}
EVENT gboolean winMessagesClose(GtkWidget *object, gpointer userData) { EVENT gboolean winMessagesClose(GtkWidget *object, gpointer userData) {
// userData is not reliable due to util indirectly calling us. // userData is not reliable due to util indirectly calling us.
WindowDataT *self = (WindowDataT *)utilGetWindowData(object); WindowDataT *self = (WindowDataT *)utilGetWindowData(object);
@ -115,6 +142,7 @@ EVENT gboolean winMessagesClose(GtkWidget *object, gpointer userData) {
static void winMessagesDelete(gpointer userData) { static void winMessagesDelete(gpointer userData) {
g_idle_remove_by_data(messagesScroll);
utilWindowUnRegister(userData); utilWindowUnRegister(userData);
_lstMessages = NULL; _lstMessages = NULL;
DEL(userData); DEL(userData);

View file

@ -132,12 +132,14 @@ EVENT void menuProjectBuildTargets(GtkWidget *object, gpointer userData
EVENT void menuProjectBuildCookRecipes(GtkWidget *object, gpointer userData); EVENT void menuProjectBuildCookRecipes(GtkWidget *object, gpointer userData);
EVENT void menuProjectBuildBuild(GtkWidget *object, gpointer userData); EVENT void menuProjectBuildBuild(GtkWidget *object, gpointer userData);
EVENT void menuProjectHelpProject(GtkWidget *object, gpointer userData); EVENT void menuProjectHelpProject(GtkWidget *object, gpointer userData);
static void receiveSFTP(SFTPT *sftp);
static void saveConfig(ProjectDataT *self); static void saveConfig(ProjectDataT *self);
static void sendSFTP(SFTPT *sftp); static void sendSFTP(SFTPT *sftp);
static TargetT **targetArrayCopy(TargetT **targets); static TargetT **targetArrayCopy(TargetT **targets);
static void targetArrayDelete(TargetT ***array); static void targetArrayDelete(TargetT ***array);
EVENT void treeProjectRowActivated(GtkTreeView *treeView, GtkTreePath *path, GtkTreeViewColumn *column, gpointer userData); EVENT void treeProjectRowActivated(GtkTreeView *treeView, GtkTreePath *path, GtkTreeViewColumn *column, gpointer userData);
static gboolean updateBuildOptions(ProjectDataT *self); static gboolean updateBuildOptions(ProjectDataT *self);
static gboolean waitForBuild(gpointer userData);
EVENT gboolean winProjectClose(GtkWidget *object, gpointer userData); EVENT gboolean winProjectClose(GtkWidget *object, gpointer userData);
static void winProjectDelete(gpointer userData); static void winProjectDelete(gpointer userData);
@ -955,20 +957,28 @@ EVENT void menuProjectBuildBuild(GtkWidget *object, gpointer userData) {
gboolean archPrinted; gboolean archPrinted;
FILE *out; FILE *out;
menuProjectBuildCookRecipes(object, userData);
ssh = NEW(SSHT); 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) {
message(MSG_ERROR, "Unable to connect to SSH port."); message(MSG_ERROR, "Unable to connect to SSH port");
return; return;
} }
// Do we have a build package to clean up?
if (sshSFTPFileExists(ssh, "build/build.tar.bz2")) {
message(MSG_INFO, "Removing stale build results");
}
// Generate build.start. // Generate build.start.
buildStart = utilCreateString("%sbuild.start", self->windowData.path); buildStart = utilCreateString("%sbuild.start", self->windowData.path);
out = fopen(buildStart, "wt"); out = fopen(buildStart, "wt");
if (!out) { if (!out) {
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");
sshDisconnect(&ssh); sshDisconnect(&ssh);
return; return;
} }
@ -1085,6 +1095,25 @@ gboolean projectAddToTree(ProjectDataT *self, char *filename) {
} }
static void receiveSFTP(SFTPT *sftp) {
ProjectDataT *self = (ProjectDataT *)sftp->userData;
if (sftp->finished) {
if (sftp->success) {
//***TODO*** Unpack results
message(MSG_INFO, "Unpacking build");
} 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);
}
}
static void saveConfig(ProjectDataT *self) { static void saveConfig(ProjectDataT *self) {
char *temp; char *temp;
FILE *out; FILE *out;
@ -1249,32 +1278,56 @@ 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 *next; SFTPT *last;
char *title;
char *target; char *target;
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->source == NULL && sftp->target == NULL) || (sftp->finished && sftp->success)) { if ((sftp->localName == NULL && sftp->remoteName == NULL) || (sftp->finished && sftp->success)) {
if (sftp->localName == NULL && sftp->remoteName == NULL) {
message(MSG_INFO, "Building %s", self->windowData.filename);
}
// Are there more files to send? // Are there more files to send?
if (arrlen(_sendList) > 0) { if (arrlen(_sendList) > 0) {
// Send next entry in the file list. // Send next entry in the file list.
title = utilCreateString("Building %s", self->windowData.filename); name = utilFileBasename(_sendList[0]);
target = utilFileBasename(_sendList[0]); target = utilCreateString("build/%s", name);
sftp = sshSFTPSend(title, sftp->sshData, _sendList[0], target, sendSFTP); message(MSG_INFO, "Sending %s to build server", name);
sftp = sshSFTPSend(last->sshData, _sendList[0], target, sendSFTP);
sftp->userData = self;
DEL(target); DEL(target);
DEL(title); DEL(name);
arrdel(_sendList, 0); arrdel(_sendList, 0);
return;
} else { } else {
// Finished! // Finished!
//***TODO*** message(MSG_INFO, "Waiting for build to complete");
g_timeout_add_seconds(5, waitForBuild, last->sshData);
} }
} }
// Did the transfer fail? // Do we have a transfer? Did the transfer fail?
if (sftp->finished && !sftp->success) { if ((!sftp) || (sftp->finished && !sftp->success)) {
//***TODO*** if (sftp) {
message(MSG_ERROR, "Sending %s to build server - FAILED", sftp->remoteName);
}
message(MSG_INFO, "Build canceled");
sshDisconnect(&last->sshData);
// Clear any remaining transfers.
while (arrlen(_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);
} }
} }
@ -1326,6 +1379,31 @@ static void targetArrayDelete(TargetT ***array) {
} }
static gboolean waitForBuild(gpointer userData) {
SSHT *ssh = (SSHT *)userData;
SFTPT *sftp;
char *temp;
if (sshSFTPFileExists(ssh, "build/build.tar.bz2")) {
// Build complete! Next step!
message(MSG_INFO, "Retrieving build results");
temp = utilCreateString("%s%cbuild.tar.bz2", g_get_user_config_dir(), UTIL_PATH_CHAR);
sftp = sshSFTPReceive(ssh, "build/build.tar.bz2", temp, receiveSFTP);
DEL(temp);
if (!sftp) {
message(MSG_ERROR, "Receiving build from build server - FAILED");
message(MSG_INFO, "Build canceled");
sshDisconnect(&ssh);
}
return G_SOURCE_REMOVE;
}
// Keep waiting.
//***TODO*** Add a timeout of some kind here and sshDisconnect.
return G_SOURCE_CONTINUE;
}
EVENT gboolean winProjectClose(GtkWidget *object, gpointer userData) { EVENT gboolean winProjectClose(GtkWidget *object, gpointer userData) {
// userData is not reliable due to menuVectorFileClose and util indirectly calling us. // userData is not reliable due to menuVectorFileClose and util indirectly calling us.
ProjectDataT *self = (ProjectDataT *)utilGetWindowData(object); ProjectDataT *self = (ProjectDataT *)utilGetWindowData(object);

158
src/ssh.c
View file

@ -47,9 +47,10 @@ static char *_buffer = NULL;
static int _bufferLen = 0; static int _bufferLen = 0;
gboolean sshUpdate(gpointer userData); // Not static gboolean sshUpdate(gpointer userData); // Not static
gboolean sshSFTPUpdate(gpointer userData); // Not static static SFTPT *sshSFTPTransfer(SSHT *sshData, char *local, char *remote, SFTPCallback callback, gboolean uploading);
static int sshWaitSocket(int socket_fd, LIBSSH2_SESSION *session); 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) { SSHT *sshConnect(char *hostname, uint16_t port, char *user, char *password) {
@ -220,6 +221,7 @@ gboolean sshSFTPFileExists(SSHT *sshData, char *target) {
LIBSSH2_SFTP_ATTRIBUTES attrs; LIBSSH2_SFTP_ATTRIBUTES attrs;
char *path; char *path;
char *file; char *file;
char *temp;
char buffer[512]; char buffer[512];
int rc; int rc;
gboolean result = FALSE; gboolean result = FALSE;
@ -233,8 +235,25 @@ gboolean sshSFTPFileExists(SSHT *sshData, char *target) {
} }
} while (!session); } while (!session);
path = utilFilePath(target); // Split filename and path.
file = utilFileBasename(target); // Cannot use utilFilePath and friends because this is a remote path.
temp = strdup(target); // Make copy in case they pass in a constant.
path = strdup("/"); // Set some defaults.
file = strdup(target); // Set some defaults.
rc = (int)strlen(temp);
while (rc > 0) {
if (temp[rc] == '/') {
// Found it.
temp[rc] = 0;
DEL(path);
DEL(file);
path = strdup(temp);
file = strdup(&temp[rc + 1]);
break;
}
rc--;
}
DEL(temp);
do { do {
handle = libssh2_sftp_opendir(session, path); handle = libssh2_sftp_opendir(session, path);
@ -276,13 +295,23 @@ gboolean sshSFTPFileExists(SSHT *sshData, char *target) {
} }
SFTPT *sshSFTPSend(char *title, SSHT *sshData, char *source, char *target, SFTPCallback callback) { SFTPT *sshSFTPReceive(SSHT *sshData, char *remote, char *local, SFTPCallback callback) {
return sshSFTPTransfer(sshData, local, remote, callback, FALSE);
}
SFTPT *sshSFTPSend(SSHT *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; 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]->source, source) == 0) && (strcmp(_activeSFTPs[i]->target, target) == 0)) { if ((strcmp(_activeSFTPs[i]->localName, local) == 0) && (strcmp(_activeSFTPs[i]->remoteName, remote) == 0)) {
// Return existing transfer handle. // Return existing transfer handle.
return _activeSFTPs[i]; return _activeSFTPs[i];
} }
@ -291,21 +320,20 @@ SFTPT *sshSFTPSend(char *title, SSHT *sshData, char *source, char *target, SFTPC
sftp = NEW(SFTPT); sftp = NEW(SFTPT);
if (sftp) { if (sftp) {
sftp->fileSize = utilFileSize(source); sftp->fileSize = uploading ? utilFileSize(local) : 0;
sftp->local = fopen(source, "rb"); sftp->local = fopen(local, uploading ? "rb" : "wb");
if (sftp->local) { if (sftp->local) {
sftp->fileSent = 0; sftp->fileSent = 0;
sftp->nread = 0; sftp->nread = 0;
sftp->ptr = NULL; sftp->ptr = NULL;
sftp->title = strdup(title); sftp->localName = strdup(local);
sftp->source = strdup(source); sftp->remoteName = strdup(remote);
sftp->target = strdup(target); sftp->sshData = sshData;
sftp->sshData = sshData; sftp->uploading = uploading;
sftp->uploading = TRUE; sftp->readMore = TRUE;
sftp->readMore = TRUE; sftp->finished = FALSE;
sftp->finished = FALSE; sftp->success = FALSE;
sftp->success = FALSE; sftp->callback = callback;
sftp->callback = callback;
do { do {
sftp->session = libssh2_sftp_init(sshData->session); sftp->session = libssh2_sftp_init(sshData->session);
if (!sftp->session) { if (!sftp->session) {
@ -315,7 +343,17 @@ SFTPT *sshSFTPSend(char *title, SSHT *sshData, char *source, char *target, SFTPC
} }
} while (!sftp->session); } while (!sftp->session);
do { 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 (uploading) {
sftp->handle = libssh2_sftp_open(sftp->session, sftp->remoteName,
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,
LIBSSH2_FXF_READ,
LIBSSH2_SFTP_S_IRUSR | LIBSSH2_SFTP_S_IWUSR | LIBSSH2_SFTP_S_IRGRP |
LIBSSH2_SFTP_S_IROTH);
}
if (!sftp->handle) { if (!sftp->handle) {
if (libssh2_session_last_errno(sshData->session) != LIBSSH2_ERROR_EAGAIN) { if (libssh2_session_last_errno(sshData->session) != LIBSSH2_ERROR_EAGAIN) {
break; break;
@ -323,8 +361,6 @@ SFTPT *sshSFTPSend(char *title, SSHT *sshData, char *source, char *target, SFTPC
} }
} while (!sftp->handle); } while (!sftp->handle);
if (sftp->handle) { if (sftp->handle) {
//***TODO*** SFTP Status Dialog
//sftp->status = new SFTPStatus(sftp);
arrput(_activeSFTPs, sftp); arrput(_activeSFTPs, sftp);
return sftp; return sftp;
} else { } else {
@ -344,60 +380,78 @@ SFTPT *sshSFTPSend(char *title, SSHT *sshData, char *source, char *target, SFTPC
gboolean sshSFTPUpdate(gpointer userData) { gboolean sshSFTPUpdate(gpointer userData) {
int i; int i;
int rc; int rc;
int count = 0;
SFTPT *result = NULL; SFTPT *result = NULL;
(void)userData; (void)userData;
for (i=0; i<arrlen(_activeSFTPs); i++) { for (i=0; i<arrlen(_activeSFTPs); i++) {
count++; // Uploading or downloading?
// More data to read? if (_activeSFTPs[i]->uploading) {
if (_activeSFTPs[i]->readMore) { // Uploading
_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? // More data to read?
if (_activeSFTPs[i]->nread > 0) { if (_activeSFTPs[i]->readMore) {
// Send data. _activeSFTPs[i]->nread = fread(_activeSFTPs[i]->buffer, 1, sizeof(_activeSFTPs[i]->buffer), _activeSFTPs[i]->local);
while ((rc = (int)libssh2_sftp_write(_activeSFTPs[i]->handle, _activeSFTPs[i]->ptr, _activeSFTPs[i]->nread)) == LIBSSH2_ERROR_EAGAIN) { if (_activeSFTPs[i]->nread <= 0) {
sshWaitSocket(_activeSFTPs[i]->sshData->sock, _activeSFTPs[i]->sshData->session); result = _activeSFTPs[i];
arrdel(_activeSFTPs, i);
break;
}
_activeSFTPs[i]->ptr = _activeSFTPs[i]->buffer;
_activeSFTPs[i]->readMore = FALSE;
} }
if (rc >= 0) {
_activeSFTPs[i]->ptr += rc; // Is there data to send?
_activeSFTPs[i]->nread -= rc; if (_activeSFTPs[i]->nread > 0) {
_activeSFTPs[i]->fileSent += rc; // 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 { } else {
// We need more data! // We need more data!
_activeSFTPs[i]->readMore = TRUE; _activeSFTPs[i]->readMore = TRUE;
} }
} else { } else {
// We need more data! // Downloading
_activeSFTPs[i]->readMore = TRUE;
// 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);
}
if (rc > 0) {
_activeSFTPs[i]->fileSize += rc;
fwrite(_activeSFTPs[i]->buffer, 1, rc, _activeSFTPs[i]->local);
} else {
result = _activeSFTPs[i];
arrdel(_activeSFTPs, i);
break;
}
} }
} }
if (result) { if (result) {
result->finished = TRUE; result->finished = TRUE;
result->success = TRUE; result->success = TRUE;
fclose(result->local);
libssh2_sftp_close(result->handle); libssh2_sftp_close(result->handle);
libssh2_sftp_shutdown(result->session); libssh2_sftp_shutdown(result->session);
//***TODO*** Display in status dialog
//result->status->Finished();
//result->status->Close();
if (result->callback) { if (result->callback) {
result->callback(result); result->callback(result);
} }
DEL(result); DEL(result);
} }
return count; return G_SOURCE_CONTINUE;
} }

View file

@ -409,6 +409,16 @@ GtkWidget *utilFindChildWidget(GtkWidget *parent, const gchar *name) {
} }
void utilForceUpdate(void) {
//***TODO*** This is supposed to force any pending paint operations.
// It doesn't work.
//while (g_main_context_pending(NULL)) {
g_main_context_iteration(NULL,FALSE);
//}
}
char *utilGetToken(char *input, char *delimit, char *openblock, char *closeblock) { char *utilGetToken(char *input, char *delimit, char *openblock, char *closeblock) {
static char *token = NULL; static char *token = NULL;
char *lead = NULL; char *lead = NULL;
@ -642,6 +652,9 @@ void utilWindowRegister(gpointer windowData) {
// Grab title. // Grab title.
w->title = strdup(gtk_window_get_title(GTK_WINDOW(w->window))); w->title = strdup(gtk_window_get_title(GTK_WINDOW(w->window)));
gtk_widget_show_all(w->window);
utilForceUpdate();
hmput(_windowList, w->window, windowData); hmput(_windowList, w->window, windowData);
debug("Window Registered: %ld\n", hmlen(_windowList)); debug("Window Registered: %ld\n", hmlen(_windowList));
} }