Enhance packed fs serving

This commit is contained in:
Sergey Lyubka 2021-07-30 17:41:23 +01:00
parent 3a46055e52
commit b40b1232cc
5 changed files with 59 additions and 20 deletions

View File

@ -433,14 +433,14 @@ const char *mg_unlist(size_t no) {
static char *packed_realpath(const char *path, char *resolved_path) {
if (resolved_path == NULL) resolved_path = (char *) malloc(strlen(path) + 1);
while (*path == '.' || *path == '/') path++;
// while (*path == '.' || *path == '/') path++;
strcpy(resolved_path, path);
return resolved_path;
}
static int is_dir_prefix(const char *prefix, size_t n, const char *path) {
return n < strlen(path) && memcmp(prefix, path, n) == 0 &&
(n == 0 || path[n] == MG_DIRSEP);
return n < strlen(path) && memcmp(prefix, path, n) == 0 && path[n] == '/';
//(n == 0 || path[n] == MG_DIRSEP);
}
static int packed_stat(const char *path, size_t *size, time_t *mtime) {
@ -454,12 +454,24 @@ static int packed_stat(const char *path, size_t *size, time_t *mtime) {
return 0;
}
static void packed_list(const char *path, void (*fn)(const char *, void *),
static void packed_list(const char *dir, void (*fn)(const char *, void *),
void *userdata) {
const char *p;
size_t i, n = strlen(path);
for (i = 0; (p = mg_unlist(i)) != NULL; i++) {
if (is_dir_prefix(path, n, p)) fn(&p[n], userdata);
char buf[256], tmp[sizeof(buf)];
const char *path, *begin, *end;
size_t i, n = strlen(dir);
tmp[0] = '\0'; // Previously listed entry
for (i = 0; (path = mg_unlist(i)) != NULL; i++) {
if (!is_dir_prefix(dir, n, path)) continue;
begin = &path[n + 1];
end = strchr(begin, '/');
if (end == NULL) end = begin + strlen(begin);
snprintf(buf, sizeof(buf), "%.*s", (int) (end - begin), begin);
buf[sizeof(buf) - 1] = '\0';
// If this entry has been already listed, skip
// NOTE: we're assuming that file list is sorted alphabetically
if (strcmp(buf, tmp) == 0) continue;
fn(buf, userdata); // Not yet listed, call user function
strcpy(tmp, buf); // And save this entry as listed
}
}
@ -1355,6 +1367,7 @@ static void printdirentry(const char *name, void *userdata) {
char path[MG_PATH_MAX], sz[64], mod[64];
int flags, n = 0;
// LOG(LL_DEBUG, ("[%s] [%s]", d->dir, name));
if (snprintf(path, sizeof(path), "%s%c%s", d->dir, '/', name) < 0) {
LOG(LL_ERROR, ("%s truncated", name));
} else if ((flags = fs->stat(path, &size, &mtime)) == 0) {

View File

@ -22,14 +22,14 @@ const char *mg_unlist(size_t no) {
static char *packed_realpath(const char *path, char *resolved_path) {
if (resolved_path == NULL) resolved_path = (char *) malloc(strlen(path) + 1);
while (*path == '.' || *path == '/') path++;
// while (*path == '.' || *path == '/') path++;
strcpy(resolved_path, path);
return resolved_path;
}
static int is_dir_prefix(const char *prefix, size_t n, const char *path) {
return n < strlen(path) && memcmp(prefix, path, n) == 0 &&
(n == 0 || path[n] == MG_DIRSEP);
return n < strlen(path) && memcmp(prefix, path, n) == 0 && path[n] == '/';
//(n == 0 || path[n] == MG_DIRSEP);
}
static int packed_stat(const char *path, size_t *size, time_t *mtime) {
@ -43,12 +43,24 @@ static int packed_stat(const char *path, size_t *size, time_t *mtime) {
return 0;
}
static void packed_list(const char *path, void (*fn)(const char *, void *),
static void packed_list(const char *dir, void (*fn)(const char *, void *),
void *userdata) {
const char *p;
size_t i, n = strlen(path);
for (i = 0; (p = mg_unlist(i)) != NULL; i++) {
if (is_dir_prefix(path, n, p)) fn(&p[n], userdata);
char buf[256], tmp[sizeof(buf)];
const char *path, *begin, *end;
size_t i, n = strlen(dir);
tmp[0] = '\0'; // Previously listed entry
for (i = 0; (path = mg_unlist(i)) != NULL; i++) {
if (!is_dir_prefix(dir, n, path)) continue;
begin = &path[n + 1];
end = strchr(begin, '/');
if (end == NULL) end = begin + strlen(begin);
snprintf(buf, sizeof(buf), "%.*s", (int) (end - begin), begin);
buf[sizeof(buf) - 1] = '\0';
// If this entry has been already listed, skip
// NOTE: we're assuming that file list is sorted alphabetically
if (strcmp(buf, tmp) == 0) continue;
fn(buf, userdata); // Not yet listed, call user function
strcpy(tmp, buf); // And save this entry as listed
}
}

View File

@ -596,6 +596,7 @@ static void printdirentry(const char *name, void *userdata) {
char path[MG_PATH_MAX], sz[64], mod[64];
int flags, n = 0;
// LOG(LL_DEBUG, ("[%s] [%s]", d->dir, name));
if (snprintf(path, sizeof(path), "%s%c%s", d->dir, '/', name) < 0) {
LOG(LL_ERROR, ("%s truncated", name));
} else if ((flags = fs->stat(path, &size, &mtime)) == 0) {

View File

@ -76,7 +76,7 @@ int main(int argc, char *argv[]) {
for (i = 1; i < argc; i++) {
struct stat st;
stat(argv[i], &st);
printf(" {\"%s\", v%d, sizeof(v%d), %lu},\n", argv[i], i, i, st.st_mtime);
printf(" {\"/%s\", v%d, sizeof(v%d), %lu},\n", argv[i], i, i, st.st_mtime);
}
printf("%s", " {NULL, NULL, 0, 0}\n");
printf("%s", "};\n\n");

View File

@ -582,7 +582,6 @@ static void test_http_server(void) {
// Directory listing
fetch(&mgr, buf, url, "GET /test/ HTTP/1.0\n\n");
ASSERT(fetch(&mgr, buf, url, "GET /test/ HTTP/1.0\n\n") == 200);
printf("-------\n%s\n", buf);
ASSERT(mg_strstr(mg_str(buf), mg_str(">Index of /test/<")) != NULL);
ASSERT(mg_strstr(mg_str(buf), mg_str(">fuzz.c<")) != NULL);
@ -1358,7 +1357,7 @@ static void eh7(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
struct mg_http_serve_opts sopts;
memset(&sopts, 0, sizeof(sopts));
sopts.root_dir = ".";
sopts.root_dir = "";
sopts.fs = &mg_fs_packed;
mg_http_serve_dir(c, hm, &sopts);
}
@ -1371,12 +1370,26 @@ static void test_packed(void) {
char buf[FETCH_BUF_SIZE] = "", *data = mg_file_read("Makefile", NULL);
mg_mgr_init(&mgr);
mg_http_listen(&mgr, url, eh7, NULL);
// Load top level file directly
ASSERT(fetch(&mgr, buf, url, "GET /Makefile HTTP/1.0\n\n") == 200);
ASSERT(cmpbody(buf, data) == 0);
free(data);
// Load file deeper in the FS tree directly
data = mg_file_read("src/ssi.h", NULL);
ASSERT(fetch(&mgr, buf, url, "GET /src/ssi.h HTTP/1.0\n\n") == 200);
ASSERT(cmpbody(buf, data) == 0);
free(data);
// List root dir
ASSERT(fetch(&mgr, buf, url, "GET / HTTP/1.0\n\n") == 200);
// printf("--------\n%s\n", buf);
// exit(0);
// List nested dir
ASSERT(fetch(&mgr, buf, url, "GET /test HTTP/1.0\n\n") == 200);
// printf("--------\n%s\n", buf);
mg_mgr_free(&mgr);
ASSERT(mgr.conns == NULL);
}