ftp: reduce amount of realloc's done in cmdio_write

text    data     bss     dec     hex filename
 808562     476    7864  816902   c7706 busybox_old
 808568     476    7864  816908   c770c busybox_unstripped
This commit is contained in:
Denis Vlasenko 2009-03-09 04:38:37 +00:00
parent d42eb81206
commit 57a3b17498

View File

@ -102,7 +102,7 @@ struct globals {
int pasv_listen_fd;
int data_fd;
off_t restart_pos;
char *ftp_cmp;
char *ftp_cmd;
char *ftp_arg;
#if ENABLE_FEATURE_FTP_WRITE
char *rnfr_filename;
@ -112,8 +112,9 @@ struct globals {
#define G (*(struct globals*)&bb_common_bufsiz1)
#define INIT_G() do { } while (0)
static char *
replace_text(const char *str, const char from, const char *to)
escape_text(const char *prepend, const char *str, char from, const char *to, char append)
{
size_t retlen, remainlen, chunklen, tolen;
const char *remain;
@ -124,29 +125,27 @@ replace_text(const char *str, const char from, const char *to)
tolen = strlen(to);
/* Simply alloc strlen(str)*strlen(to). "to" is max 2 so it's ok */
ret = xmalloc(remainlen * tolen + 1);
retlen = 0;
retlen = strlen(prepend);
ret = xmalloc(retlen + remainlen * tolen + 1 + 1);
strcpy(ret, prepend);
for (;;) {
found = strchr(remain, from);
if (found != NULL) {
chunklen = found - remain;
found = strchrnul(remain, from);
chunklen = found - remain;
/* Copy chunk which doesn't contain 'from' to ret */
memcpy(&ret[retlen], remain, chunklen);
retlen += chunklen;
/* Copy chunk which doesn't contain 'from' to ret */
memcpy(&ret[retlen], remain, chunklen);
retlen += chunklen;
if (*found != '\0') {
/* Now copy 'to' instead of 'from' */
memcpy(&ret[retlen], to, tolen);
retlen += tolen;
remain = found + 1;
} else {
/*
* The last chunk. We are already sure that we have enough space
* so we can use strcpy.
*/
strcpy(&ret[retlen], remain);
ret[retlen] = append;
ret[retlen+1] = '\0';
break;
}
}
@ -163,15 +162,12 @@ replace_char(char *str, char from, char to)
static void
cmdio_write(unsigned status, const char *str)
{
char *escaped_str, *response;
char *response;
int len;
/* FTP allegedly uses telnet protocol for command link.
* In telnet, 0xff is an escape char, and needs to be escaped: */
escaped_str = replace_text(str, '\xff', "\xff\xff");
response = xasprintf("%u%s\r", status, escaped_str);
free(escaped_str);
response = escape_text(utoa(status), str, '\xff', "\xff\xff", '\r');
/* ?! does FTP send embedded LFs as NULs? wow */
len = strlen(response);
@ -206,17 +202,15 @@ cmdio_write_raw(const char *p_text)
static void
handle_pwd(void)
{
char *cwd, *promoted_cwd, *response;
char *cwd, *response;
cwd = xrealloc_getcwd_or_warn(NULL);
if (cwd == NULL)
cwd = xstrdup("");
/* We have to promote each " to "" */
promoted_cwd = replace_text(cwd, '\"', "\"\"");
response = escape_text(" \"", cwd, '\"', "\"\"", '\"');
free(cwd);
response = xasprintf(" \"%s\"", promoted_cwd);
free(promoted_cwd);
cmdio_write(FTP_PWDOK, response);
free(response);
}
@ -872,9 +866,9 @@ cmdio_get_cmd_and_arg(void)
uint32_t cmdval;
char *cmd;
free(G.ftp_cmp);
free(G.ftp_cmd);
len = 8 * 1024; /* Paranoia. Peer may send 1 gigabyte long cmd... */
G.ftp_cmp = cmd = xmalloc_reads(STDIN_FILENO, NULL, &len);
G.ftp_cmd = cmd = xmalloc_reads(STDIN_FILENO, NULL, &len);
if (!cmd)
exit(0);