diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2026-01-29 02:39:31 +0100 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2026-01-29 02:39:31 +0100 |
| commit | 768ab5384ced12cb263fcfc7fba23cebf705c15f (patch) | |
| tree | e9a1ebec64733350ff5f10cd1f04713e3e2ce757 | |
| parent | df1ef312a081a7aa9e16ef21020ee895aa5ab893 (diff) | |
| download | busybox-w32-768ab5384ced12cb263fcfc7fba23cebf705c15f.tar.gz busybox-w32-768ab5384ced12cb263fcfc7fba23cebf705c15f.tar.bz2 busybox-w32-768ab5384ced12cb263fcfc7fba23cebf705c15f.zip | |
httpd: do not use a global variable in index.cgi
text data bss dec hex filename
3255 0 0 3255 cb7 httpd_indexcgi.o
3253 0 4 3257 cb9 httpd_indexcgi.o.old
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
| -rw-r--r-- | networking/httpd_indexcgi.c | 127 |
1 files changed, 53 insertions, 74 deletions
diff --git a/networking/httpd_indexcgi.c b/networking/httpd_indexcgi.c index 2e4e0b80e..aeed8ccb1 100644 --- a/networking/httpd_indexcgi.c +++ b/networking/httpd_indexcgi.c | |||
| @@ -152,44 +152,16 @@ static int compare_dl(dir_list_t **aa, dir_list_t **bb) | |||
| 152 | return strcmp(a->d_name, b->d_name); | 152 | return strcmp(a->d_name, b->d_name); |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | enum { | ||
| 156 | /* Must be >= 64k (all Linux arches have pages <= 64k) */ | ||
| 157 | BUFFER_SIZE = 8 * 1024*1024, | ||
| 158 | //one dirent is typically <= 100 bytes, 1M is enough for ~10k files | ||
| 159 | //FIXME: change code to *iterate* getdents64 if need to support giant file lists | ||
| 160 | }; | ||
| 161 | |||
| 162 | static char *buffer; | ||
| 163 | #if 0 | ||
| 164 | /* Use global "dst" pointer */ | ||
| 165 | static char *dst; | ||
| 166 | # define INIT_DST dst = buffer; | ||
| 167 | # define CHARP void | ||
| 168 | # define CHARP_DST /*nothing*/ | ||
| 169 | # define DST /*nothing*/ | ||
| 170 | # define SET_DST /*nothing*/ | ||
| 171 | # define RETURN_DST ((void)0) | ||
| 172 | #else | ||
| 173 | /* Propagate "dst" pointer as parameter */ | ||
| 174 | /* This is usually more efficient (uses a register for it) */ | ||
| 175 | # define INIT_DST char *dst = buffer; | ||
| 176 | # define CHARP char* | ||
| 177 | # define CHARP_DST char *dst, | ||
| 178 | # define DST dst, | ||
| 179 | # define SET_DST dst = | ||
| 180 | # define RETURN_DST return dst | ||
| 181 | #endif | ||
| 182 | |||
| 183 | /* NB: formatters do not store terminating NUL! */ | 155 | /* NB: formatters do not store terminating NUL! */ |
| 184 | 156 | ||
| 185 | static CHARP fmt_str(CHARP_DST const char *src) | 157 | static char *fmt_str(char *dst, const char *src) |
| 186 | { | 158 | { |
| 187 | unsigned len = strlen(src); | 159 | unsigned len = strlen(src); |
| 188 | dst = mempcpy(dst, src, len); | 160 | dst = mempcpy(dst, src, len); |
| 189 | RETURN_DST; | 161 | return dst; |
| 190 | } | 162 | } |
| 191 | 163 | ||
| 192 | static CHARP fmt_url(CHARP_DST const char *name) | 164 | static char *fmt_url(char *dst, const char *name) |
| 193 | { | 165 | { |
| 194 | while (*name) { | 166 | while (*name) { |
| 195 | unsigned c = (unsigned char)*name++; | 167 | unsigned c = (unsigned char)*name++; |
| @@ -203,29 +175,29 @@ static CHARP fmt_url(CHARP_DST const char *name) | |||
| 203 | } | 175 | } |
| 204 | *dst++ = c; | 176 | *dst++ = c; |
| 205 | } | 177 | } |
| 206 | RETURN_DST; | 178 | return dst; |
| 207 | } | 179 | } |
| 208 | 180 | ||
| 209 | static CHARP fmt_html(CHARP_DST const char *name) | 181 | static char *fmt_html(char *dst, const char *name) |
| 210 | { | 182 | { |
| 211 | while (*name) { | 183 | while (*name) { |
| 212 | char c = *name++; | 184 | char c = *name++; |
| 213 | if (c == '<') | 185 | if (c == '<') |
| 214 | SET_DST fmt_str(DST "<"); | 186 | dst = fmt_str(dst, "<"); |
| 215 | else if (c == '>') | 187 | else if (c == '>') |
| 216 | SET_DST fmt_str(DST ">"); | 188 | dst = fmt_str(dst, ">"); |
| 217 | else if (c == '&') { | 189 | else if (c == '&') { |
| 218 | SET_DST fmt_str(DST "&"); | 190 | dst = fmt_str(dst, "&"); |
| 219 | } else { | 191 | } else { |
| 220 | *dst++ = c; | 192 | *dst++ = c; |
| 221 | continue; | 193 | continue; |
| 222 | } | 194 | } |
| 223 | } | 195 | } |
| 224 | RETURN_DST; | 196 | return dst; |
| 225 | } | 197 | } |
| 226 | 198 | ||
| 227 | /* HEADROOM bytes are available after dst after this call */ | 199 | /* HEADROOM bytes are available after dst after this call */ |
| 228 | static CHARP fmt_ull(CHARP_DST unsigned long long n) | 200 | static char *fmt_ull(char *dst, unsigned long long n) |
| 229 | { | 201 | { |
| 230 | char buf[sizeof(n)*3 + 2]; | 202 | char buf[sizeof(n)*3 + 2]; |
| 231 | char *p; | 203 | char *p; |
| @@ -236,29 +208,37 @@ static CHARP fmt_ull(CHARP_DST unsigned long long n) | |||
| 236 | *--p = (n % 10) + '0'; | 208 | *--p = (n % 10) + '0'; |
| 237 | n /= 10; | 209 | n /= 10; |
| 238 | } while (n); | 210 | } while (n); |
| 239 | SET_DST fmt_str(DST p); | 211 | dst = fmt_str(dst, p); |
| 240 | RETURN_DST; | 212 | return dst; |
| 241 | } | 213 | } |
| 242 | 214 | ||
| 243 | static CHARP fmt_02u(CHARP_DST unsigned n) | 215 | static char *fmt_02u(char *dst, unsigned n) |
| 244 | { | 216 | { |
| 245 | /* n %= 100; - not needed, callers don't pass big n */ | 217 | /* n %= 100; - not needed, callers don't pass big n */ |
| 246 | dst[0] = (n / 10) + '0'; | 218 | dst[0] = (n / 10) + '0'; |
| 247 | dst[1] = (n % 10) + '0'; | 219 | dst[1] = (n % 10) + '0'; |
| 248 | dst += 2; | 220 | dst += 2; |
| 249 | RETURN_DST; | 221 | return dst; |
| 250 | } | 222 | } |
| 251 | 223 | ||
| 252 | static CHARP fmt_04u(CHARP_DST unsigned n) | 224 | static char *fmt_04u(char *dst, unsigned n) |
| 253 | { | 225 | { |
| 254 | /* n %= 10000; - not needed, callers don't pass big n */ | 226 | /* n %= 10000; - not needed, callers don't pass big n */ |
| 255 | SET_DST fmt_02u(DST n / 100); | 227 | dst = fmt_02u(dst, n / 100); |
| 256 | SET_DST fmt_02u(DST n % 100); | 228 | dst = fmt_02u(dst, n % 100); |
| 257 | RETURN_DST; | 229 | return dst; |
| 258 | } | 230 | } |
| 259 | 231 | ||
| 232 | enum { | ||
| 233 | /* Must be >= 64k (all Linux arches have pages <= 64k) */ | ||
| 234 | BUFFER_SIZE = 8 * 1024*1024, | ||
| 235 | //one dirent is typically <= 100 bytes, 1M is enough for ~10k files | ||
| 236 | //FIXME: change code to *iterate* getdents64 if need to support giant file lists | ||
| 237 | }; | ||
| 238 | |||
| 260 | int main(int argc, char **argv) | 239 | int main(int argc, char **argv) |
| 261 | { | 240 | { |
| 241 | char *buffer, *dst; | ||
| 262 | char *location; | 242 | char *location; |
| 263 | dir_list_t **dir_list; | 243 | dir_list_t **dir_list; |
| 264 | dir_list_t *cdir; | 244 | dir_list_t *cdir; |
| @@ -343,22 +323,22 @@ int main(int argc, char **argv) | |||
| 343 | qsort(dir_list, dir_list_count, sizeof(dir_list[0]), (void*)compare_dl); | 323 | qsort(dir_list, dir_list_count, sizeof(dir_list[0]), (void*)compare_dl); |
| 344 | 324 | ||
| 345 | buffer += 2*BUFFER_SIZE; | 325 | buffer += 2*BUFFER_SIZE; |
| 346 | { | 326 | dst = buffer; |
| 347 | INIT_DST | 327 | |
| 348 | SET_DST fmt_str(DST | 328 | dst = fmt_str(dst, |
| 349 | "" /* Additional headers (currently none) */ | 329 | "" /* Additional headers (currently none) */ |
| 350 | "\r\n" /* Mandatory empty line after headers */ | 330 | "\r\n" /* Mandatory empty line after headers */ |
| 351 | "<html><head><title>Index of "); | 331 | "<html><head><title>Index of "); |
| 352 | /* Guard against directories with &, > etc */ | 332 | /* Guard against directories with &, > etc */ |
| 353 | SET_DST fmt_html(DST location); | 333 | dst = fmt_html(dst, location); |
| 354 | SET_DST fmt_str(DST | 334 | dst = fmt_str(dst, |
| 355 | "</title>\n" | 335 | "</title>\n" |
| 356 | STYLE_STR | 336 | STYLE_STR |
| 357 | "</head>" "\n" | 337 | "</head>" "\n" |
| 358 | "<body>" "\n" | 338 | "<body>" "\n" |
| 359 | "<h1>Index of "); | 339 | "<h1>Index of "); |
| 360 | SET_DST fmt_html(DST location); | 340 | dst = fmt_html(dst, location); |
| 361 | SET_DST fmt_str(DST | 341 | dst = fmt_str(dst, |
| 362 | "</h1>" "\n" | 342 | "</h1>" "\n" |
| 363 | "<table>" "\n" | 343 | "<table>" "\n" |
| 364 | "<col class=nm><col class=sz><col class=dt>" "\n" | 344 | "<col class=nm><col class=sz><col class=dt>" "\n" |
| @@ -382,30 +362,30 @@ int main(int argc, char **argv) | |||
| 382 | continue; | 362 | continue; |
| 383 | //fprintf(stderr, "%d '%s'\n", dir_list_count, cdir->d_name); | 363 | //fprintf(stderr, "%d '%s'\n", dir_list_count, cdir->d_name); |
| 384 | 364 | ||
| 385 | SET_DST fmt_str(DST "<tr><td class=nm><a href='"); | 365 | dst = fmt_str(dst, "<tr><td class=nm><a href='"); |
| 386 | SET_DST fmt_url(DST cdir->d_name); /* %20 etc */ | 366 | dst = fmt_url(dst, cdir->d_name); /* %20 etc */ |
| 387 | if (S_ISDIR(cdir->D_MODE)) | 367 | if (S_ISDIR(cdir->D_MODE)) |
| 388 | *dst++ = '/'; | 368 | *dst++ = '/'; |
| 389 | SET_DST fmt_str(DST "'>"); | 369 | dst = fmt_str(dst, "'>"); |
| 390 | SET_DST fmt_html(DST cdir->d_name); /* < etc */ | 370 | dst = fmt_html(dst, cdir->d_name); /* < etc */ |
| 391 | if (S_ISDIR(cdir->D_MODE)) | 371 | if (S_ISDIR(cdir->D_MODE)) |
| 392 | *dst++ = '/'; | 372 | *dst++ = '/'; |
| 393 | SET_DST fmt_str(DST "</a><td class=sz>"); | 373 | dst = fmt_str(dst, "</a><td class=sz>"); |
| 394 | if (S_ISREG(cdir->D_MODE)) | 374 | if (S_ISREG(cdir->D_MODE)) |
| 395 | SET_DST fmt_ull(DST cdir->D_SIZE); | 375 | dst = fmt_ull(dst, cdir->D_SIZE); |
| 396 | SET_DST fmt_str(DST "<td class=dt>"); | 376 | dst = fmt_str(dst, "<td class=dt>"); |
| 397 | if (sizeof(cdir->D_MTIME) == sizeof(tt)) | 377 | if (sizeof(cdir->D_MTIME) == sizeof(tt)) |
| 398 | ptm = gmtime((time_t*)&cdir->D_MTIME); | 378 | ptm = gmtime((time_t*)&cdir->D_MTIME); |
| 399 | else { | 379 | else { |
| 400 | tt = cdir->D_MTIME; | 380 | tt = cdir->D_MTIME; |
| 401 | ptm = gmtime(&tt); | 381 | ptm = gmtime(&tt); |
| 402 | } | 382 | } |
| 403 | SET_DST fmt_04u(DST 1900 + ptm->tm_year); *dst++ = '-'; | 383 | dst = fmt_04u(dst, 1900 + ptm->tm_year); *dst++ = '-'; |
| 404 | SET_DST fmt_02u(DST ptm->tm_mon + 1); *dst++ = '-'; | 384 | dst = fmt_02u(dst, ptm->tm_mon + 1); *dst++ = '-'; |
| 405 | SET_DST fmt_02u(DST ptm->tm_mday); *dst++ = ' '; | 385 | dst = fmt_02u(dst, ptm->tm_mday); *dst++ = ' '; |
| 406 | SET_DST fmt_02u(DST ptm->tm_hour); *dst++ = ':'; | 386 | dst = fmt_02u(dst, ptm->tm_hour); *dst++ = ':'; |
| 407 | SET_DST fmt_02u(DST ptm->tm_min); *dst++ = ':'; | 387 | dst = fmt_02u(dst, ptm->tm_min); *dst++ = ':'; |
| 408 | SET_DST fmt_02u(DST ptm->tm_sec); | 388 | dst = fmt_02u(dst, ptm->tm_sec); |
| 409 | *dst++ = '\n'; | 389 | *dst++ = '\n'; |
| 410 | 390 | ||
| 411 | /* Flush after every 256 files (typically around 50k of output) */ | 391 | /* Flush after every 256 files (typically around 50k of output) */ |
| @@ -415,18 +395,17 @@ int main(int argc, char **argv) | |||
| 415 | } | 395 | } |
| 416 | } | 396 | } |
| 417 | 397 | ||
| 418 | SET_DST fmt_str(DST "<tr class=foot><th class=cnt>Files: "); | 398 | dst = fmt_str(dst, "<tr class=foot><th class=cnt>Files: "); |
| 419 | SET_DST fmt_ull(DST count_files); | 399 | dst = fmt_ull(dst, count_files); |
| 420 | /* count_dirs - 1: we don't want to count ".." */ | 400 | /* count_dirs - 1: we don't want to count ".." */ |
| 421 | SET_DST fmt_str(DST ", directories: "); | 401 | dst = fmt_str(dst, ", directories: "); |
| 422 | SET_DST fmt_ull(DST count_dirs - 1); | 402 | dst = fmt_ull(dst, count_dirs - 1); |
| 423 | SET_DST fmt_str(DST "<th class=sz>"); | 403 | dst = fmt_str(dst, "<th class=sz>"); |
| 424 | SET_DST fmt_ull(DST size_total); | 404 | dst = fmt_ull(dst, size_total); |
| 425 | SET_DST fmt_str(DST "<th class=dt>\n"); | 405 | dst = fmt_str(dst, "<th class=dt>\n"); |
| 426 | /* "</table></body></html>" - why bother? */ | 406 | /* "</table></body></html>" - why bother? */ |
| 427 | 407 | ||
| 428 | full_write(STDOUT_FILENO, buffer, dst - buffer); | 408 | full_write(STDOUT_FILENO, buffer, dst - buffer); |
| 429 | 409 | ||
| 430 | return 0; | 410 | return 0; |
| 431 | } | ||
| 432 | } | 411 | } |
