aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2026-01-26 07:15:54 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2026-01-26 07:21:11 +0100
commit28e4d2b854d7072c510f416acd2eea5dcdbc346a (patch)
treeefc0725d3d5b4b0a2808ecdb69ad358195acf34f
parent4e82d99460d36ab09b651eb90c77e7cd13fb368a (diff)
downloadbusybox-w32-28e4d2b854d7072c510f416acd2eea5dcdbc346a.tar.gz
busybox-w32-28e4d2b854d7072c510f416acd2eea5dcdbc346a.tar.bz2
busybox-w32-28e4d2b854d7072c510f416acd2eea5dcdbc346a.zip
httpd: optimize example CGIsbusybox
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/httpd_indexcgi.c43
-rw-r--r--networking/httpd_ratelimit_cgi.c19
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
74static 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
150static char *buffer; 162static 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 */
173static 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
184static CHARP fmt_str(CHARP_DST const char *src) 185static 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 */
193static CHARP fmt_url(CHARP_DST const char *name) 192static 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 */
212static CHARP fmt_html(CHARP_DST const char *name) 209static 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 "&amp;"); 218 SET_DST fmt_str(DST "&amp;");
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 */
248static CHARP fmt_02u(CHARP_DST unsigned n) 243static 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 */
258static CHARP fmt_04u(CHARP_DST unsigned n) 252static 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
42static ssize_t full_write(int fd, const void *buf, size_t len) 42static 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
69static void full_write2(int fd, const char *msg, const char *msg2) 56static void full_write2(int fd, const char *msg, const char *msg2)