1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-23 16:48:49 -05:00

libssh2: convert over to use dynbuf

In my very basic test that lists sftp://127.0.0.1/tmp/, this patched
code makes 161 allocations compared to 194 in git master. A 17%
reduction.

Closes #5336
This commit is contained in:
Daniel Stenberg 2020-05-04 14:44:07 +02:00
parent 8810064655
commit 44645ca8b0
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
2 changed files with 55 additions and 77 deletions

View File

@ -795,10 +795,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
struct SSHPROTO *sftp_scp = data->req.protop; struct SSHPROTO *sftp_scp = data->req.protop;
struct ssh_conn *sshc = &conn->proto.sshc; struct ssh_conn *sshc = &conn->proto.sshc;
curl_socket_t sock = conn->sock[FIRSTSOCKET]; curl_socket_t sock = conn->sock[FIRSTSOCKET];
char *new_readdir_line;
int rc = LIBSSH2_ERROR_NONE; int rc = LIBSSH2_ERROR_NONE;
int err; int err;
int seekerr = CURL_SEEKFUNC_OK; int seekerr = CURL_SEEKFUNC_OK;
size_t readdir_len;
*block = 0; /* we're not blocking by default */ *block = 0; /* we're not blocking by default */
do { do {
@ -2090,6 +2090,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->actualcode = CURLE_OUT_OF_MEMORY; sshc->actualcode = CURLE_OUT_OF_MEMORY;
break; break;
} }
Curl_dyn_init(&sshc->readdir, PATH_MAX * 2);
state(conn, SSH_SFTP_READDIR); state(conn, SSH_SFTP_READDIR);
break; break;
@ -2104,68 +2105,51 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break; break;
} }
if(rc > 0) { if(rc > 0) {
sshc->readdir_len = (size_t) rc; readdir_len = (size_t) rc;
sshc->readdir_filename[sshc->readdir_len] = '\0'; sshc->readdir_filename[readdir_len] = '\0';
if(data->set.ftp_list_only) { if(data->set.ftp_list_only) {
char *tmpLine;
tmpLine = aprintf("%s\n", sshc->readdir_filename);
if(tmpLine == NULL) {
state(conn, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
result = Curl_client_write(conn, CLIENTWRITE_BODY, result = Curl_client_write(conn, CLIENTWRITE_BODY,
tmpLine, sshc->readdir_len + 1); sshc->readdir_filename,
free(tmpLine); readdir_len);
if(!result)
result = Curl_client_write(conn, CLIENTWRITE_BODY,
(char *)"\n", 1);
if(result) { if(result) {
state(conn, SSH_STOP); state(conn, SSH_STOP);
break; break;
} }
/* since this counts what we send to the client, we include the /* since this counts what we send to the client, we include the
newline in this counter */ newline in this counter */
data->req.bytecount += sshc->readdir_len + 1; data->req.bytecount += readdir_len + 1;
/* output debug output if that is requested */ /* output debug output if that is requested */
if(data->set.verbose) { if(data->set.verbose) {
Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_filename, Curl_debug(data, CURLINFO_DATA_IN, sshc->readdir_filename,
sshc->readdir_len); readdir_len);
Curl_debug(data, CURLINFO_DATA_IN, (char *)"\n", 1);
} }
} }
else { else {
sshc->readdir_currLen = strlen(sshc->readdir_longentry); result = Curl_dyn_add(&sshc->readdir, sshc->readdir_longentry);
sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
if(!sshc->readdir_line) {
Curl_safefree(sshc->readdir_filename);
Curl_safefree(sshc->readdir_longentry);
state(conn, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
memcpy(sshc->readdir_line, sshc->readdir_longentry, if(!result) {
sshc->readdir_currLen); if((sshc->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
if((sshc->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) && ((sshc->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
((sshc->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFLNK)) {
LIBSSH2_SFTP_S_IFLNK)) { Curl_dyn_init(&sshc->readdir_link, PATH_MAX);
sshc->readdir_linkPath = malloc(PATH_MAX + 1); result = Curl_dyn_add(&sshc->readdir_link, sftp_scp->path);
if(sshc->readdir_linkPath == NULL) { state(conn, SSH_SFTP_READDIR_LINK);
Curl_safefree(sshc->readdir_filename); if(!result)
Curl_safefree(sshc->readdir_longentry); break;
state(conn, SSH_SFTP_CLOSE); }
sshc->actualcode = CURLE_OUT_OF_MEMORY; else {
state(conn, SSH_SFTP_READDIR_BOTTOM);
break; break;
} }
msnprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", sftp_scp->path,
sshc->readdir_filename);
state(conn, SSH_SFTP_READDIR_LINK);
break;
} }
state(conn, SSH_SFTP_READDIR_BOTTOM); sshc->actualcode = result;
state(conn, SSH_SFTP_CLOSE);
break; break;
} }
} }
@ -2192,64 +2176,56 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
case SSH_SFTP_READDIR_LINK: case SSH_SFTP_READDIR_LINK:
rc = rc =
libssh2_sftp_symlink_ex(sshc->sftp_session, libssh2_sftp_symlink_ex(sshc->sftp_session,
sshc->readdir_linkPath, Curl_dyn_ptr(&sshc->readdir_link),
curlx_uztoui(strlen(sshc->readdir_linkPath)), (int)Curl_dyn_len(&sshc->readdir_link),
sshc->readdir_filename, sshc->readdir_filename,
PATH_MAX, LIBSSH2_SFTP_READLINK); PATH_MAX, LIBSSH2_SFTP_READLINK);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
break; break;
} }
sshc->readdir_len = (size_t) rc; readdir_len = (size_t) rc;
Curl_safefree(sshc->readdir_linkPath); Curl_dyn_free(&sshc->readdir_link);
/* get room for the filename and extra output */ /* append filename and extra output */
sshc->readdir_totalLen += 4 + sshc->readdir_len; result = Curl_dyn_addf(&sshc->readdir, " -> %s", sshc->readdir_filename);
new_readdir_line = Curl_saferealloc(sshc->readdir_line,
sshc->readdir_totalLen); if(result) {
if(!new_readdir_line) {
sshc->readdir_line = NULL; sshc->readdir_line = NULL;
Curl_safefree(sshc->readdir_filename); Curl_safefree(sshc->readdir_filename);
Curl_safefree(sshc->readdir_longentry); Curl_safefree(sshc->readdir_longentry);
state(conn, SSH_SFTP_CLOSE); state(conn, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY; sshc->actualcode = result;
break; break;
} }
sshc->readdir_line = new_readdir_line;
sshc->readdir_currLen += msnprintf(sshc->readdir_line +
sshc->readdir_currLen,
sshc->readdir_totalLen -
sshc->readdir_currLen,
" -> %s",
sshc->readdir_filename);
state(conn, SSH_SFTP_READDIR_BOTTOM); state(conn, SSH_SFTP_READDIR_BOTTOM);
break; break;
case SSH_SFTP_READDIR_BOTTOM: case SSH_SFTP_READDIR_BOTTOM:
sshc->readdir_currLen += msnprintf(sshc->readdir_line + result = Curl_dyn_addn(&sshc->readdir, "\n", 1);
sshc->readdir_currLen, if(!result)
sshc->readdir_totalLen - result = Curl_client_write(conn, CLIENTWRITE_BODY,
sshc->readdir_currLen, "\n"); Curl_dyn_ptr(&sshc->readdir),
result = Curl_client_write(conn, CLIENTWRITE_BODY, Curl_dyn_len(&sshc->readdir));
sshc->readdir_line,
sshc->readdir_currLen);
if(!result) { if(!result) {
/* output debug output if that is requested */ /* output debug output if that is requested */
if(data->set.verbose) { if(data->set.verbose) {
Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line, Curl_debug(data, CURLINFO_DATA_IN,
sshc->readdir_currLen); Curl_dyn_ptr(&sshc->readdir),
Curl_dyn_len(&sshc->readdir));
} }
data->req.bytecount += sshc->readdir_currLen; data->req.bytecount += Curl_dyn_len(&sshc->readdir);
} }
Curl_safefree(sshc->readdir_line);
if(result) { if(result) {
Curl_dyn_free(&sshc->readdir);
state(conn, SSH_STOP); state(conn, SSH_STOP);
} }
else else {
Curl_dyn_reset(&sshc->readdir);
state(conn, SSH_SFTP_READDIR); state(conn, SSH_SFTP_READDIR);
}
break; break;
case SSH_SFTP_READDIR_DONE: case SSH_SFTP_READDIR_DONE:
@ -2830,7 +2806,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->readdir_filename); Curl_safefree(sshc->readdir_filename);
Curl_safefree(sshc->readdir_longentry); Curl_safefree(sshc->readdir_longentry);
Curl_safefree(sshc->readdir_line); Curl_safefree(sshc->readdir_line);
Curl_safefree(sshc->readdir_linkPath); Curl_dyn_free(&sshc->readdir);
/* the code we are about to return */ /* the code we are about to return */
result = sshc->actualcode; result = sshc->actualcode;

View File

@ -134,9 +134,7 @@ struct ssh_conn {
quote command fails) */ quote command fails) */
char *homedir; /* when doing SFTP we figure out home dir in the char *homedir; /* when doing SFTP we figure out home dir in the
connect phase */ connect phase */
size_t readdir_len, readdir_totalLen, readdir_currLen;
char *readdir_line; char *readdir_line;
char *readdir_linkPath;
/* end of READDIR stuff */ /* end of READDIR stuff */
int secondCreateDirs; /* counter use by the code to see if the int secondCreateDirs; /* counter use by the code to see if the
@ -147,6 +145,8 @@ struct ssh_conn {
int orig_waitfor; /* default READ/WRITE bits wait for */ int orig_waitfor; /* default READ/WRITE bits wait for */
#if defined(USE_LIBSSH) #if defined(USE_LIBSSH)
char *readdir_linkPath;
size_t readdir_len, readdir_totalLen, readdir_currLen;
/* our variables */ /* our variables */
unsigned kbd_state; /* 0 or 1 */ unsigned kbd_state; /* 0 or 1 */
ssh_key privkey; ssh_key privkey;
@ -168,6 +168,8 @@ struct ssh_conn {
const char *readdir_longentry; const char *readdir_longentry;
char *readdir_tmp; char *readdir_tmp;
#elif defined(USE_LIBSSH2) #elif defined(USE_LIBSSH2)
struct dynbuf readdir_link;
struct dynbuf readdir;
char *readdir_filename; char *readdir_filename;
char *readdir_longentry; char *readdir_longentry;