. Cosmetics in mime_mapping_cmp().

. Added make_sorted_dirlist(), cleanup_sorted_dirlist().
. generate_dir_listing() works better and produces sorted output, but
  still looks awful.
This commit is contained in:
Emil Mikulic 2003-11-27 12:20:55 +00:00
parent 3dbf2f15b4
commit 2776f8c35e
1 changed files with 128 additions and 9 deletions

View File

@ -22,6 +22,7 @@ static const char rcsid[] =
#include <arpa/inet.h>
#include <assert.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
@ -558,10 +559,8 @@ static void add_mime_mapping(const char *extension, const char *mimetype)
*/
static int mime_mapping_cmp(const void *a, const void *b)
{
return strcmp(
((const struct mime_mapping *)a)->extension,
((const struct mime_mapping *)b)->extension
);
return strcmp( ((const struct mime_mapping *)a)->extension,
((const struct mime_mapping *)b)->extension );
}
static void sort_mime_map(void)
@ -1437,12 +1436,128 @@ static int file_exists(const char *path)
/* ---------------------------------------------------------------------------
* Make sorted list of files in a directory. Returns number of entries, or -1
* if error occurs.
*/
struct dlent
{
char *name;
int is_dir;
off_t size;
};
static int dlent_cmp(const void *a, const void *b)
{
return strcmp( (*(const struct dlent **)a)->name,
(*(const struct dlent **)b)->name );
}
static ssize_t make_sorted_dirlist(const char *path, struct dlent ***output)
{
DIR *dir;
struct dirent *ent;
size_t entries = 0, pool = 0;
#define POOL_INCR 100
char *currname;
struct dlent **list = NULL;
dir = opendir(path);
if (dir == NULL) return -1;
currname = xmalloc(strlen(path) + MAXNAMLEN + 1);
/* construct list */
while ((ent = readdir(dir)) != NULL)
{
struct stat s;
if (ent->d_name[0] == '.' && ent->d_name[1] == '\0')
continue; /* skip "." */
assert(strlen(ent->d_name) <= MAXNAMLEN);
sprintf(currname, "%s%s", path, ent->d_name);
if (stat(currname, &s) == -1)
continue; /* skip un-stat-able files */
if (entries == pool)
{
pool += POOL_INCR;
list = xrealloc(list, sizeof(struct dlent*) * pool);
}
list[entries] = xmalloc(sizeof(struct dlent));
list[entries]->name = xstrdup(ent->d_name);
list[entries]->is_dir = S_ISDIR(s.st_mode);
list[entries]->size = s.st_size;
entries++;
}
(void)closedir(dir); /* FIXME: not checking return -1 */
safefree(currname);
qsort(list, entries, sizeof(struct dlent*), dlent_cmp);
*output = xrealloc(list, sizeof(struct dlent*) * entries);
return entries;
}
/* ---------------------------------------------------------------------------
* Cleanly deallocate a sorted list of directory files.
*/
static void cleanup_sorted_dirlist(struct dlent **list, const ssize_t size)
{
ssize_t i;
for (i=0; i<size; i++)
{
safefree(list[i]->name);
safefree(list[i]);
}
}
/* ---------------------------------------------------------------------------
* 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 date[DATE_LEN];
char *listing, date[DATE_LEN];
struct dlent **list;
ssize_t listsize;
size_t maxlen = 0;
int i;
listsize = make_sorted_dirlist(path, &list); /* FIXME return -1 */
xasprintf(&listing, "<tt><pre>\n");
for (i=0; i<listsize; i++)
{
size_t tmp = strlen(list[i]->name);
if (maxlen < tmp) maxlen = tmp;
}
maxlen++;
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");
}
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));
@ -1450,11 +1565,12 @@ static void generate_dir_listing(struct connection *conn, const char *path)
conn->reply_length = xasprintf(&(conn->reply),
"<html><head><title>%s</title></head><body>\n"
"<h1>%s</h1>\n"
"Unimplemented.\n"
"%s\n"
"<hr>\n"
"Generated by %s on %s\n"
"</body></html>\n",
conn->uri, conn->uri, pkgname, date);
conn->uri, conn->uri, listing, pkgname, date);
safefree(listing);
conn->header_length = xasprintf(&(conn->header),
"HTTP/1.1 200 OK\r\n"
@ -1465,7 +1581,7 @@ static void generate_dir_listing(struct connection *conn, const char *path)
"Content-Type: text/html\r\n"
"\r\n",
date, pkgname, keep_alive(conn), conn->reply_length);
conn->reply_type = REPLY_GENERATED;
conn->http_code = 200;
}
@ -1855,7 +1971,10 @@ static void poll_send_reply(struct connection *conn)
/* handle any errors (-1) or closure (0) in send() */
if (sent < 1)
{
if (sent == -1) debugf("send() error: %s\n", strerror(errno));
if (sent == -1)
debugf("send(%d) error: %s\n", conn->socket, strerror(errno));
else if (sent == 0)
debugf("send(%d) closure\n", conn->socket);
conn->conn_close = 1;
conn->state = DONE;
return;