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 <arpa/inet.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <grp.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)
|
static int mime_mapping_cmp(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
return strcmp(
|
return strcmp( ((const struct mime_mapping *)a)->extension,
|
||||||
((const struct mime_mapping *)a)->extension,
|
((const struct mime_mapping *)b)->extension );
|
||||||
((const struct mime_mapping *)b)->extension
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sort_mime_map(void)
|
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.
|
* 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)
|
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. */
|
/* Only really need to calculate the date once. */
|
||||||
(void)rfc1123_date(date, time(NULL));
|
(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),
|
conn->reply_length = xasprintf(&(conn->reply),
|
||||||
"<html><head><title>%s</title></head><body>\n"
|
"<html><head><title>%s</title></head><body>\n"
|
||||||
"<h1>%s</h1>\n"
|
"<h1>%s</h1>\n"
|
||||||
"Unimplemented.\n"
|
"%s\n"
|
||||||
"<hr>\n"
|
"<hr>\n"
|
||||||
"Generated by %s on %s\n"
|
"Generated by %s on %s\n"
|
||||||
"</body></html>\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),
|
conn->header_length = xasprintf(&(conn->header),
|
||||||
"HTTP/1.1 200 OK\r\n"
|
"HTTP/1.1 200 OK\r\n"
|
||||||
@ -1855,7 +1971,10 @@ static void poll_send_reply(struct connection *conn)
|
|||||||
/* handle any errors (-1) or closure (0) in send() */
|
/* handle any errors (-1) or closure (0) in send() */
|
||||||
if (sent < 1)
|
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->conn_close = 1;
|
||||||
conn->state = DONE;
|
conn->state = DONE;
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user