diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2026-01-26 07:15:54 +0100 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2026-01-26 07:21:11 +0100 |
| commit | 28e4d2b854d7072c510f416acd2eea5dcdbc346a (patch) | |
| tree | efc0725d3d5b4b0a2808ecdb69ad358195acf34f /networking | |
| parent | 4e82d99460d36ab09b651eb90c77e7cd13fb368a (diff) | |
| download | busybox-w32-busybox.tar.gz busybox-w32-busybox.tar.bz2 busybox-w32-busybox.zip | |
httpd: optimize example CGIsbusybox
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'networking')
| -rw-r--r-- | networking/httpd_indexcgi.c | 43 | ||||
| -rw-r--r-- | networking/httpd_ratelimit_cgi.c | 19 |
2 files changed, 25 insertions, 37 deletions
diff --git a/networking/httpd_indexcgi.c b/networking/httpd_indexcgi.c index 3965bb5e0..2e4e0b80e 100644 --- a/networking/httpd_indexcgi.c +++ b/networking/httpd_indexcgi.c | |||
| @@ -71,6 +71,19 @@ struct linux_dirent64 { | |||
| 71 | char d_name[]; | 71 | char d_name[]; |
| 72 | }; | 72 | }; |
| 73 | 73 | ||
| 74 | static void full_write(int fd, const void *buf, size_t len) | ||
| 75 | { | ||
| 76 | ssize_t cc; | ||
| 77 | |||
| 78 | while (len) { | ||
| 79 | cc = write(fd, buf, len); | ||
| 80 | if (cc < 0) | ||
| 81 | return; | ||
| 82 | buf = ((const char *)buf) + cc; | ||
| 83 | len -= cc; | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 74 | /* Appearance of the table is controlled by style sheet *ONLY*, | 87 | /* Appearance of the table is controlled by style sheet *ONLY*, |
| 75 | * formatting code uses <TAG class=CLASS> to apply style | 88 | * formatting code uses <TAG class=CLASS> to apply style |
| 76 | * to elements. Edit stylesheet to your liking and recompile. */ | 89 | * to elements. Edit stylesheet to your liking and recompile. */ |
| @@ -144,7 +157,6 @@ enum { | |||
| 144 | BUFFER_SIZE = 8 * 1024*1024, | 157 | BUFFER_SIZE = 8 * 1024*1024, |
| 145 | //one dirent is typically <= 100 bytes, 1M is enough for ~10k files | 158 | //one dirent is typically <= 100 bytes, 1M is enough for ~10k files |
| 146 | //FIXME: change code to *iterate* getdents64 if need to support giant file lists | 159 | //FIXME: change code to *iterate* getdents64 if need to support giant file lists |
| 147 | HEADROOM = 64, | ||
| 148 | }; | 160 | }; |
| 149 | 161 | ||
| 150 | static char *buffer; | 162 | static char *buffer; |
| @@ -168,33 +180,19 @@ static char *dst; | |||
| 168 | # define RETURN_DST return dst | 180 | # define RETURN_DST return dst |
| 169 | #endif | 181 | #endif |
| 170 | 182 | ||
| 171 | /* After this call, you have at least size + HEADROOM bytes available | ||
| 172 | * ahead of dst */ | ||
| 173 | static CHARP guarantee(CHARP_DST int size) | ||
| 174 | { | ||
| 175 | if (buffer + (BUFFER_SIZE-HEADROOM) - dst < size) { | ||
| 176 | write(STDOUT_FILENO, buffer, dst - buffer); | ||
| 177 | dst = buffer; | ||
| 178 | } | ||
| 179 | RETURN_DST; | ||
| 180 | } | ||
| 181 | |||
| 182 | /* NB: formatters do not store terminating NUL! */ | 183 | /* NB: formatters do not store terminating NUL! */ |
| 183 | 184 | ||
| 184 | static CHARP fmt_str(CHARP_DST const char *src) | 185 | static CHARP fmt_str(CHARP_DST const char *src) |
| 185 | { | 186 | { |
| 186 | unsigned len = strlen(src); | 187 | unsigned len = strlen(src); |
| 187 | SET_DST guarantee(DST len); | ||
| 188 | dst = mempcpy(dst, src, len); | 188 | dst = mempcpy(dst, src, len); |
| 189 | RETURN_DST; | 189 | RETURN_DST; |
| 190 | } | 190 | } |
| 191 | 191 | ||
| 192 | /* HEADROOM bytes after dst are available after this call */ | ||
| 193 | static CHARP fmt_url(CHARP_DST const char *name) | 192 | static CHARP fmt_url(CHARP_DST const char *name) |
| 194 | { | 193 | { |
| 195 | while (*name) { | 194 | while (*name) { |
| 196 | unsigned c = (unsigned char)*name++; | 195 | unsigned c = (unsigned char)*name++; |
| 197 | SET_DST guarantee(DST 3); | ||
| 198 | if ((c - '0') > 9 /* not a digit */ | 196 | if ((c - '0') > 9 /* not a digit */ |
| 199 | && ((c|0x20) - 'a') > ('z' - 'a') /* not A-Z or a-z */ | 197 | && ((c|0x20) - 'a') > ('z' - 'a') /* not A-Z or a-z */ |
| 200 | && !strchr("._-+@", c) | 198 | && !strchr("._-+@", c) |
| @@ -208,7 +206,6 @@ static CHARP fmt_url(CHARP_DST const char *name) | |||
| 208 | RETURN_DST; | 206 | RETURN_DST; |
| 209 | } | 207 | } |
| 210 | 208 | ||
| 211 | /* HEADROOM bytes are available after dst after this call */ | ||
| 212 | static CHARP fmt_html(CHARP_DST const char *name) | 209 | static CHARP fmt_html(CHARP_DST const char *name) |
| 213 | { | 210 | { |
| 214 | while (*name) { | 211 | while (*name) { |
| @@ -220,7 +217,6 @@ static CHARP fmt_html(CHARP_DST const char *name) | |||
| 220 | else if (c == '&') { | 217 | else if (c == '&') { |
| 221 | SET_DST fmt_str(DST "&"); | 218 | SET_DST fmt_str(DST "&"); |
| 222 | } else { | 219 | } else { |
| 223 | SET_DST guarantee(DST 1); | ||
| 224 | *dst++ = c; | 220 | *dst++ = c; |
| 225 | continue; | 221 | continue; |
| 226 | } | 222 | } |
| @@ -244,7 +240,6 @@ static CHARP fmt_ull(CHARP_DST unsigned long long n) | |||
| 244 | RETURN_DST; | 240 | RETURN_DST; |
| 245 | } | 241 | } |
| 246 | 242 | ||
| 247 | /* Does not call guarantee - eats into headroom instead */ | ||
| 248 | static CHARP fmt_02u(CHARP_DST unsigned n) | 243 | static CHARP fmt_02u(CHARP_DST unsigned n) |
| 249 | { | 244 | { |
| 250 | /* n %= 100; - not needed, callers don't pass big n */ | 245 | /* n %= 100; - not needed, callers don't pass big n */ |
| @@ -254,7 +249,6 @@ static CHARP fmt_02u(CHARP_DST unsigned n) | |||
| 254 | RETURN_DST; | 249 | RETURN_DST; |
| 255 | } | 250 | } |
| 256 | 251 | ||
| 257 | /* Does not call guarantee - eats into headroom instead */ | ||
| 258 | static CHARP fmt_04u(CHARP_DST unsigned n) | 252 | static CHARP fmt_04u(CHARP_DST unsigned n) |
| 259 | { | 253 | { |
| 260 | /* n %= 10000; - not needed, callers don't pass big n */ | 254 | /* n %= 10000; - not needed, callers don't pass big n */ |
| @@ -401,7 +395,7 @@ int main(int argc, char **argv) | |||
| 401 | SET_DST fmt_ull(DST cdir->D_SIZE); | 395 | SET_DST fmt_ull(DST cdir->D_SIZE); |
| 402 | SET_DST fmt_str(DST "<td class=dt>"); | 396 | SET_DST fmt_str(DST "<td class=dt>"); |
| 403 | if (sizeof(cdir->D_MTIME) == sizeof(tt)) | 397 | if (sizeof(cdir->D_MTIME) == sizeof(tt)) |
| 404 | ptm = gmtime(&cdir->D_MTIME); | 398 | ptm = gmtime((time_t*)&cdir->D_MTIME); |
| 405 | else { | 399 | else { |
| 406 | tt = cdir->D_MTIME; | 400 | tt = cdir->D_MTIME; |
| 407 | ptm = gmtime(&tt); | 401 | ptm = gmtime(&tt); |
| @@ -413,6 +407,12 @@ int main(int argc, char **argv) | |||
| 413 | SET_DST fmt_02u(DST ptm->tm_min); *dst++ = ':'; | 407 | SET_DST fmt_02u(DST ptm->tm_min); *dst++ = ':'; |
| 414 | SET_DST fmt_02u(DST ptm->tm_sec); | 408 | SET_DST fmt_02u(DST ptm->tm_sec); |
| 415 | *dst++ = '\n'; | 409 | *dst++ = '\n'; |
| 410 | |||
| 411 | /* Flush after every 256 files (typically around 50k of output) */ | ||
| 412 | if ((dir_list_count & 0xff) == 0) { | ||
| 413 | full_write(STDOUT_FILENO, buffer, dst - buffer); | ||
| 414 | dst = buffer; | ||
| 415 | } | ||
| 416 | } | 416 | } |
| 417 | 417 | ||
| 418 | SET_DST fmt_str(DST "<tr class=foot><th class=cnt>Files: "); | 418 | SET_DST fmt_str(DST "<tr class=foot><th class=cnt>Files: "); |
| @@ -424,7 +424,8 @@ int main(int argc, char **argv) | |||
| 424 | SET_DST fmt_ull(DST size_total); | 424 | SET_DST fmt_ull(DST size_total); |
| 425 | SET_DST fmt_str(DST "<th class=dt>\n"); | 425 | SET_DST fmt_str(DST "<th class=dt>\n"); |
| 426 | /* "</table></body></html>" - why bother? */ | 426 | /* "</table></body></html>" - why bother? */ |
| 427 | SET_DST guarantee(DST BUFFER_SIZE * 2); /* flush */ | 427 | |
| 428 | full_write(STDOUT_FILENO, buffer, dst - buffer); | ||
| 428 | 429 | ||
| 429 | return 0; | 430 | return 0; |
| 430 | } | 431 | } |
diff --git a/networking/httpd_ratelimit_cgi.c b/networking/httpd_ratelimit_cgi.c index 96702131e..cadaf5a07 100644 --- a/networking/httpd_ratelimit_cgi.c +++ b/networking/httpd_ratelimit_cgi.c | |||
| @@ -39,31 +39,18 @@ httpd_ratelimit_cgi.c -o httpd_ratelimit_cgi | |||
| 39 | #include <sys/stat.h> /* mkdir */ | 39 | #include <sys/stat.h> /* mkdir */ |
| 40 | #include <limits.h> | 40 | #include <limits.h> |
| 41 | 41 | ||
| 42 | static ssize_t full_write(int fd, const void *buf, size_t len) | 42 | static void full_write(int fd, const void *buf, size_t len) |
| 43 | { | 43 | { |
| 44 | ssize_t cc; | 44 | ssize_t cc; |
| 45 | ssize_t total; | ||
| 46 | |||
| 47 | total = 0; | ||
| 48 | 45 | ||
| 49 | while (len) { | 46 | while (len) { |
| 50 | cc = write(fd, buf, len); | 47 | cc = write(fd, buf, len); |
| 51 | 48 | ||
| 52 | if (cc < 0) { | 49 | if (cc < 0) |
| 53 | if (total) { | 50 | return; |
| 54 | /* we already wrote some! */ | ||
| 55 | /* user can do another write to know the error code */ | ||
| 56 | return total; | ||
| 57 | } | ||
| 58 | return cc; /* write() returns -1 on failure. */ | ||
| 59 | } | ||
| 60 | |||
| 61 | total += cc; | ||
| 62 | buf = ((const char *)buf) + cc; | 51 | buf = ((const char *)buf) + cc; |
| 63 | len -= cc; | 52 | len -= cc; |
| 64 | } | 53 | } |
| 65 | |||
| 66 | return total; | ||
| 67 | } | 54 | } |
| 68 | 55 | ||
| 69 | static void full_write2(int fd, const char *msg, const char *msg2) | 56 | static void full_write2(int fd, const char *msg, const char *msg2) |
