diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-03-09 04:38:37 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-03-09 04:38:37 +0000 |
commit | 57a3b174989c7778fb255f716e090d5be807b9b7 (patch) | |
tree | 5f2aeaede8073e72176a4d63f533a2c203570d8f /networking/ftpd.c | |
parent | d42eb81206dba25b01f68f98272daa34f61531d0 (diff) | |
download | busybox-w32-57a3b174989c7778fb255f716e090d5be807b9b7.tar.gz busybox-w32-57a3b174989c7778fb255f716e090d5be807b9b7.tar.bz2 busybox-w32-57a3b174989c7778fb255f716e090d5be807b9b7.zip |
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
Diffstat (limited to 'networking/ftpd.c')
-rw-r--r-- | networking/ftpd.c | 46 |
1 files changed, 20 insertions, 26 deletions
diff --git a/networking/ftpd.c b/networking/ftpd.c index 4988ce02e..b2d6ef2d2 100644 --- a/networking/ftpd.c +++ b/networking/ftpd.c | |||
@@ -102,7 +102,7 @@ struct globals { | |||
102 | int pasv_listen_fd; | 102 | int pasv_listen_fd; |
103 | int data_fd; | 103 | int data_fd; |
104 | off_t restart_pos; | 104 | off_t restart_pos; |
105 | char *ftp_cmp; | 105 | char *ftp_cmd; |
106 | char *ftp_arg; | 106 | char *ftp_arg; |
107 | #if ENABLE_FEATURE_FTP_WRITE | 107 | #if ENABLE_FEATURE_FTP_WRITE |
108 | char *rnfr_filename; | 108 | char *rnfr_filename; |
@@ -112,8 +112,9 @@ struct globals { | |||
112 | #define G (*(struct globals*)&bb_common_bufsiz1) | 112 | #define G (*(struct globals*)&bb_common_bufsiz1) |
113 | #define INIT_G() do { } while (0) | 113 | #define INIT_G() do { } while (0) |
114 | 114 | ||
115 | |||
115 | static char * | 116 | static char * |
116 | replace_text(const char *str, const char from, const char *to) | 117 | escape_text(const char *prepend, const char *str, char from, const char *to, char append) |
117 | { | 118 | { |
118 | size_t retlen, remainlen, chunklen, tolen; | 119 | size_t retlen, remainlen, chunklen, tolen; |
119 | const char *remain; | 120 | const char *remain; |
@@ -124,29 +125,27 @@ replace_text(const char *str, const char from, const char *to) | |||
124 | tolen = strlen(to); | 125 | tolen = strlen(to); |
125 | 126 | ||
126 | /* Simply alloc strlen(str)*strlen(to). "to" is max 2 so it's ok */ | 127 | /* Simply alloc strlen(str)*strlen(to). "to" is max 2 so it's ok */ |
127 | ret = xmalloc(remainlen * tolen + 1); | 128 | retlen = strlen(prepend); |
128 | retlen = 0; | 129 | ret = xmalloc(retlen + remainlen * tolen + 1 + 1); |
130 | strcpy(ret, prepend); | ||
129 | 131 | ||
130 | for (;;) { | 132 | for (;;) { |
131 | found = strchr(remain, from); | 133 | found = strchrnul(remain, from); |
132 | if (found != NULL) { | 134 | chunklen = found - remain; |
133 | chunklen = found - remain; | ||
134 | 135 | ||
135 | /* Copy chunk which doesn't contain 'from' to ret */ | 136 | /* Copy chunk which doesn't contain 'from' to ret */ |
136 | memcpy(&ret[retlen], remain, chunklen); | 137 | memcpy(&ret[retlen], remain, chunklen); |
137 | retlen += chunklen; | 138 | retlen += chunklen; |
138 | 139 | ||
140 | if (*found != '\0') { | ||
139 | /* Now copy 'to' instead of 'from' */ | 141 | /* Now copy 'to' instead of 'from' */ |
140 | memcpy(&ret[retlen], to, tolen); | 142 | memcpy(&ret[retlen], to, tolen); |
141 | retlen += tolen; | 143 | retlen += tolen; |
142 | 144 | ||
143 | remain = found + 1; | 145 | remain = found + 1; |
144 | } else { | 146 | } else { |
145 | /* | 147 | ret[retlen] = append; |
146 | * The last chunk. We are already sure that we have enough space | 148 | ret[retlen+1] = '\0'; |
147 | * so we can use strcpy. | ||
148 | */ | ||
149 | strcpy(&ret[retlen], remain); | ||
150 | break; | 149 | break; |
151 | } | 150 | } |
152 | } | 151 | } |
@@ -163,15 +162,12 @@ replace_char(char *str, char from, char to) | |||
163 | static void | 162 | static void |
164 | cmdio_write(unsigned status, const char *str) | 163 | cmdio_write(unsigned status, const char *str) |
165 | { | 164 | { |
166 | char *escaped_str, *response; | 165 | char *response; |
167 | int len; | 166 | int len; |
168 | 167 | ||
169 | /* FTP allegedly uses telnet protocol for command link. | 168 | /* FTP allegedly uses telnet protocol for command link. |
170 | * In telnet, 0xff is an escape char, and needs to be escaped: */ | 169 | * In telnet, 0xff is an escape char, and needs to be escaped: */ |
171 | escaped_str = replace_text(str, '\xff', "\xff\xff"); | 170 | response = escape_text(utoa(status), str, '\xff', "\xff\xff", '\r'); |
172 | |||
173 | response = xasprintf("%u%s\r", status, escaped_str); | ||
174 | free(escaped_str); | ||
175 | 171 | ||
176 | /* ?! does FTP send embedded LFs as NULs? wow */ | 172 | /* ?! does FTP send embedded LFs as NULs? wow */ |
177 | len = strlen(response); | 173 | len = strlen(response); |
@@ -206,17 +202,15 @@ cmdio_write_raw(const char *p_text) | |||
206 | static void | 202 | static void |
207 | handle_pwd(void) | 203 | handle_pwd(void) |
208 | { | 204 | { |
209 | char *cwd, *promoted_cwd, *response; | 205 | char *cwd, *response; |
210 | 206 | ||
211 | cwd = xrealloc_getcwd_or_warn(NULL); | 207 | cwd = xrealloc_getcwd_or_warn(NULL); |
212 | if (cwd == NULL) | 208 | if (cwd == NULL) |
213 | cwd = xstrdup(""); | 209 | cwd = xstrdup(""); |
214 | 210 | ||
215 | /* We have to promote each " to "" */ | 211 | /* We have to promote each " to "" */ |
216 | promoted_cwd = replace_text(cwd, '\"', "\"\""); | 212 | response = escape_text(" \"", cwd, '\"', "\"\"", '\"'); |
217 | free(cwd); | 213 | free(cwd); |
218 | response = xasprintf(" \"%s\"", promoted_cwd); | ||
219 | free(promoted_cwd); | ||
220 | cmdio_write(FTP_PWDOK, response); | 214 | cmdio_write(FTP_PWDOK, response); |
221 | free(response); | 215 | free(response); |
222 | } | 216 | } |
@@ -872,9 +866,9 @@ cmdio_get_cmd_and_arg(void) | |||
872 | uint32_t cmdval; | 866 | uint32_t cmdval; |
873 | char *cmd; | 867 | char *cmd; |
874 | 868 | ||
875 | free(G.ftp_cmp); | 869 | free(G.ftp_cmd); |
876 | len = 8 * 1024; /* Paranoia. Peer may send 1 gigabyte long cmd... */ | 870 | len = 8 * 1024; /* Paranoia. Peer may send 1 gigabyte long cmd... */ |
877 | G.ftp_cmp = cmd = xmalloc_reads(STDIN_FILENO, NULL, &len); | 871 | G.ftp_cmd = cmd = xmalloc_reads(STDIN_FILENO, NULL, &len); |
878 | if (!cmd) | 872 | if (!cmd) |
879 | exit(0); | 873 | exit(0); |
880 | 874 | ||