#include <errno.h>
#include <sys/stat.h>
#include <fmt.h>
+#include <sys/prctl.h>
+
+// 64k RAM aren't really that much, and it should speed things up significantly
+#define OBULEN (64*1024)
+static char outbuf[OBULEN] = "Status: 200 here's your listing"
+ "\nX-Frame-Options: DENY"
+ "\nContent-Type: text/plain;charset=utf8"
+ "\n\n";
int main() {
- FASTOUTPUT
+ //FASTOUTPUT
+ prctl(PR_SET_DUMPABLE, 1); // FIXME XXX potential security problem; disable later!
+ if (chdir("/")) senderr("chdir / failed", MYFAULT);
char *encpath = getenv("QUERY_STRING");
login_and_setup(); // will clear the environment
senderr(errstr, NOTMYFAULT);
}
+ // ok, let's do fast output!
// The directory was opened successfully - send our success header.
- puts("Status: 200 here's your listing");
- puts("X-Frame-Options: DENY");
- puts("Content-Type: text/plain;charset=utf8");
- puts("");
+ char *p = outbuf+strlen(outbuf);
// send one line per file
+ #define LINE_LENGTH_LIMIT (NAME_MAX*2+1+FMT_ULONG+1+FMT_ULONG+1)
struct dirent *dent;
- char linedata[NAME_MAX*2+1+FMT_ULONG+1+FMT_ULONG+1];
while ((dent = readdir(dir)) != NULL) {
+ if (p+LINE_LENGTH_LIMIT >= outbuf+OBULEN) {
+ // Whoah, that's a big directory!
+ // Flush the pipe.
+ write(1, outbuf, p-outbuf);
+ // And reuse the buffer.
+ p = outbuf;
+ }
struct stat st;
// if we can't really see the file anyway, skip it
if (lstat(dent->d_name, &st)) continue;
//printf("%s %lu %u\n", encfilename, (unsigned long)st.st_size, (unsigned int)st.st_mode);
size_t name_len = strlen(dent->d_name);
- hex(linedata, (unsigned char *)dent->d_name, name_len);
- char *p = linedata+name_len*2;
+ hex(p, (unsigned char *)dent->d_name, name_len);
+ p += name_len*2;
*(p++) = ' ';
p += fmt_ulong(p, (unsigned long)st.st_size);
*(p++) = ' ';
p += fmt_ulong(p, (unsigned int)st.st_mode);
*(p++) = '\n';
- *p = 0;
- fputs(linedata, stdout);
}
+
+ // final pipe flush
+ write(1, outbuf, p-outbuf);
}