mirror of
https://github.com/emikulic/darkhttpd.git
synced 2023-08-10 21:13:08 +03:00
. 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:
parent
3dbf2f15b4
commit
2776f8c35e
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user