. Implemented apbuf API.

. Reworked generate_dir_listing() to use apbuf - much nicer now.
This commit is contained in:
Emil Mikulic 2003-11-27 13:04:08 +00:00
parent 2776f8c35e
commit 3e378caaf0
1 changed files with 97 additions and 24 deletions

View File

@ -355,6 +355,69 @@ static unsigned int xasprintf(char **ret, const char *format, ...)
/* ---------------------------------------------------------------------------
* Append buffer code. A somewhat efficient string buffer with pool-based
* reallocation.
*/
#define APBUF_INIT 4096
#define APBUF_GROW APBUF_INIT
struct apbuf
{
size_t length, pool;
char *str;
};
static struct apbuf *make_apbuf(void)
{
struct apbuf *buf = xmalloc(sizeof(struct apbuf));
buf->length = 0;
buf->pool = APBUF_INIT;
buf->str = xmalloc(buf->pool);
return buf;
}
static void appendl(struct apbuf *buf, const char *s, const size_t len)
{
if (buf->pool <= buf->length + len)
{
/* pool has dried up */
while (buf->pool <= buf->length + len) buf->pool += APBUF_GROW;
buf->str = xrealloc(buf->str, buf->pool);
}
memcpy(buf->str + buf->length, s, len+1);
buf->length += len;
}
static void append(struct apbuf *buf, const char *s)
{
size_t len = strlen(s);
appendl(buf, s, len);
}
static void appendf(struct apbuf *buf, const char *format, ...)
{
char *tmp;
va_list va;
size_t len;
va_start(va, format);
len = xvasprintf(&tmp, format, va);
va_end(va);
appendl(buf, tmp, len);
}
/* ---------------------------------------------------------------------------
* Make the specified socket non-blocking.
*/
@ -1498,6 +1561,7 @@ static ssize_t make_sorted_dirlist(const char *path, struct dlent ***output)
qsort(list, entries, sizeof(struct dlent*), dlent_cmp);
*output = xrealloc(list, sizeof(struct dlent*) * entries);
return entries;
#undef POOL_INCR
}
@ -1520,57 +1584,66 @@ static void cleanup_sorted_dirlist(struct dlent **list, const ssize_t size)
/* ---------------------------------------------------------------------------
* Generate directory listing.
*/
/* FIXME: this is awful: */
#define appendf(dest, format...) do { char *tmp1, *tmp2; \
xasprintf(&tmp1, format); xasprintf(&tmp2, "%s%s", dest, tmp1); \
safefree(dest); dest=tmp2; safefree(tmp1); } while(0)
static void generate_dir_listing(struct connection *conn, const char *path)
{
char *listing, date[DATE_LEN];
char date[DATE_LEN];
struct dlent **list;
ssize_t listsize;
size_t maxlen = 0;
int i;
struct apbuf *listing = make_apbuf();
listsize = make_sorted_dirlist(path, &list); /* FIXME return -1 */
listsize = make_sorted_dirlist(path, &list);
if (listsize == -1)
{
default_reply(conn, 500, "Internal Server Error",
"Couldn't list directory: %s", strerror(errno));
return;
}
xasprintf(&listing, "<tt><pre>\n");
for (i=0; i<listsize; i++)
{
size_t tmp = strlen(list[i]->name);
if (maxlen < tmp) maxlen = tmp;
}
maxlen++;
appendf(listing,
"<html><head><title>%s</title></head><body>\n"
"<h1>%s</h1>\n"
"<tt><pre>\n",
conn->uri, conn->uri);
for (i=0; i<listsize; i++)
{
int j;
appendf(listing, "<a href=\"%s\">%s</a>",
list[i]->name, list[i]->name);
if (list[i]->is_dir) appendf(listing, "/");
for (j=strlen(list[i]->name); j<maxlen; j++)
appendf(listing, " ");
if (!list[i]->is_dir) appendf(listing, "%10d\n", list[i]->size);
appendf(listing, "\n");
if (list[i]->is_dir)
append(listing, "/\n");
else
{
int j;
for (j=strlen(list[i]->name); j<maxlen; j++)
append(listing, " ");
appendf(listing, "%10d\n", list[i]->size);
}
}
cleanup_sorted_dirlist(list, listsize);
safefree(list);
appendf(listing, "</pre></tt>\n");
/* Only really need to calculate the date once. */
(void)rfc1123_date(date, time(NULL));
conn->reply_length = xasprintf(&(conn->reply),
"<html><head><title>%s</title></head><body>\n"
"<h1>%s</h1>\n"
"%s\n"
appendf(listing,
"</pre></tt>\n"
"<hr>\n"
"Generated by %s on %s\n"
"</body></html>\n",
conn->uri, conn->uri, listing, pkgname, date);
safefree(listing);
pkgname, date);
conn->reply = listing->str;
conn->reply_length = listing->length;
safefree(listing); /* don't free inside of listing */
conn->header_length = xasprintf(&(conn->header),
"HTTP/1.1 200 OK\r\n"