From fd8db5c53ac1568fea50fb7d2f0353dfbad6097f Mon Sep 17 00:00:00 2001 From: cpq Date: Sun, 7 Feb 2021 22:43:49 +0000 Subject: [PATCH] Better unicode handling on win32 --- mongoose.c | 143 +++++++++++++++++++++++++++++++++++++++++------------ mongoose.h | 6 +-- src/http.c | 105 ++++++++++++++++++++++++++++++--------- src/ssi.c | 5 +- src/util.c | 35 ++++++++++--- src/util.h | 6 +-- 6 files changed, 231 insertions(+), 69 deletions(-) diff --git a/mongoose.c b/mongoose.c index 4ead56a1..e35c35ac 100644 --- a/mongoose.c +++ b/mongoose.c @@ -691,7 +691,7 @@ int mg_http_upload(struct mg_connection *c, struct mg_http_message *hm, snprintf(path, sizeof(path), "%s%c%s", dir, MG_DIRSEP, name); LOG(LL_DEBUG, ("%p %d bytes @ %d [%s]", c->fd, (int) hm->body.len, (int) oft, name)); - if ((fp = fopen(path, oft == 0 ? "wb" : "ab")) == NULL) { + if ((fp = mg_fopen(path, oft == 0 ? "wb" : "ab")) == NULL) { mg_http_reply(c, 400, "", "fopen(%s): %d", name, errno); return -2; } else { @@ -729,9 +729,9 @@ static const char *guess_content_type(const char *filename) { size_t ext_len; const char *type; } * t, types[] = { - MIME_ENTRY("html", "text/html"), - MIME_ENTRY("htm", "text/html"), - MIME_ENTRY("shtml", "text/html"), + MIME_ENTRY("html", "text/html; charset=utf-8"), + MIME_ENTRY("htm", "text/html; charset=utf-8"), + MIME_ENTRY("shtml", "text/html; charset=utf-8"), MIME_ENTRY("css", "text/css"), MIME_ENTRY("js", "text/javascript"), MIME_ENTRY("mjs", "text/javascript"), @@ -742,7 +742,7 @@ static const char *guess_content_type(const char *filename) { MIME_ENTRY("jpeg", "image/jpeg"), MIME_ENTRY("png", "image/png"), MIME_ENTRY("svg", "image/svg+xml"), - MIME_ENTRY("txt", "text/plain"), + MIME_ENTRY("txt", "text/plain; charset=utf-8"), MIME_ENTRY("wav", "audio/wav"), MIME_ENTRY("mp3", "audio/mpeg"), MIME_ENTRY("mid", "audio/mid"), @@ -779,18 +779,21 @@ static const char *guess_content_type(const char *filename) { if (mg_ncasecmp(t->ext, &filename[n - t->ext_len], t->ext_len)) continue; return t->type; } - return "text/plain"; + return "text/plain; charset=utf-8"; } void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm, const char *path, const char *mime, const char *hdrs) { struct mg_str *inm = mg_http_get_header(hm, "If-None-Match"); mg_stat_t st; - FILE *fp = fopen(path, "rb"); char etag[64]; + FILE *fp = mg_fopen(path, "rb"); if (fp == NULL || mg_stat(path, &st) != 0 || mg_http_etag(etag, sizeof(etag), &st) != etag) { + LOG(LL_DEBUG, + ("404 [%.*s] [%s] %p", (int) hm->uri.len, hm->uri.ptr, path, fp)); mg_http_reply(c, 404, "", "%s", "Not found\n"); + if (fp != NULL) fclose(fp); } else if (inm != NULL && mg_vcasecmp(inm, etag) == 0) { fclose(fp); mg_printf(c, "HTTP/1.1 304 Not Modified\r\nContent-Length: 0\r\n\r\n"); @@ -950,12 +953,34 @@ struct dirent *readdir(DIR *d) { } #endif -static void printdirentry(struct mg_connection *c, struct mg_http_message *hm, - const char *name, mg_stat_t *stp) { - char size[64], mod[64]; +static bool mg_is_safe(int c) { + return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || strchr("._-$,;~()/", c) != NULL; +} + +static int mg_url_encode(const char *s, char *buf, size_t len) { + int i, n = 0; + for (i = 0; s[i] != '\0'; i++) { + int c = *((const unsigned char *) (s + i)); + if ((size_t) n + 4 >= len) return 0; + if (mg_is_safe(c)) { + buf[n++] = s[i]; + } else { + buf[n++] = '%'; + mg_hex(&s[i], 1, &buf[n]); + n += 2; + } + } + return n; +} + +static void printdirentry(struct mg_connection *c, const char *name, + mg_stat_t *stp) { + char size[64], mod[64], path[MG_PATH_MAX]; int is_dir = S_ISDIR(stp->st_mode); const char *slash = is_dir ? "/" : ""; - const char *es = hm->uri.ptr[hm->uri.len - 1] != '/' ? "/" : ""; + // const char *es = hm->uri.ptr[hm->uri.len - 1] != '/' ? "/" : ""; + int n = 0; if (is_dir) { snprintf(size, sizeof(size), "%s", "[DIR]"); @@ -971,11 +996,11 @@ static void printdirentry(struct mg_connection *c, struct mg_http_message *hm, } } strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", localtime(&stp->st_mtime)); + n = mg_url_encode(name, path, sizeof(path)); mg_printf(c, - " %s%s" + " %s%s" "%s%s\n", - (int) hm->uri.len, hm->uri.ptr, es, name, slash, name, slash, mod, - size); + n, path, slash, name, slash, mod, size); } static void listdir(struct mg_connection *c, struct mg_http_message *hm, @@ -983,20 +1008,52 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm, char path[MG_PATH_MAX], *p = &dir[strlen(dir) - 1], tmp[10]; struct dirent *dp; DIR *dirp; + static const char *sort_js_code = + ""; while (p > dir && *p != '/') *p-- = '\0'; if ((dirp = (opendir(dir))) != NULL) { size_t off, n; - mg_printf(c, "%s\r\n", "HTTP/1.1 200 OK\r\nContent-Length: \r\n"); + mg_printf(c, "%s\r\n", + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/html; charset=utf-8\r\n" + "Content-Length: \r\n"); off = c->send.len; // Start of body mg_printf(c, - "Index of %.*s" + "Index of %.*s%s%s" "" "

Index of %.*s

" - "" - "\n", - (int) hm->uri.len, hm->uri.ptr, (int) hm->uri.len, hm->uri.ptr); + "" + "" + "" + "" + "\n", + (int) hm->uri.len, hm->uri.ptr, sort_js_code, sort_js_code2, + (int) hm->uri.len, hm->uri.ptr); + while ((dp = readdir(dirp)) != NULL) { mg_stat_t st; const char *sep = dp->d_name[0] == MG_DIRSEP ? "/" : ""; @@ -1008,7 +1065,7 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm, } else if (mg_stat(path, &st) != 0) { LOG(LL_ERROR, ("%lu stat(%s): %d", c->id, path, errno)); } else { - printdirentry(c, hm, dp->d_name, &st); + printdirentry(c, dp->d_name, &st); } } closedir(dirp); @@ -1042,6 +1099,7 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm, size_t n1 = strlen(t1), n2; mg_url_decode(hm->uri.ptr, hm->uri.len, t1 + n1, sizeof(t1) - n1, 0); + LOG(LL_DEBUG, ("SERVE: [%s]", t1 + n1)); t1[sizeof(t1) - 1] = '\0'; n2 = strlen(t1); while (n2 > 0 && t1[n2 - 1] == '/') t1[--n2] = 0; @@ -1057,16 +1115,17 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm, if (strlen(t2) < n1 || memcmp(t1, t2, n1) != 0) { // Requested file is located outside root directory, fail - mg_http_reply(c, 404, "", "Not found %.*s\n", hm->uri.len, hm->uri.ptr); + mg_http_reply(c, 404, "", "Not found %.*s\n", (int) hm->uri.len, + hm->uri.ptr); } else { - FILE *fp = fopen(t2, "r"); + FILE *fp = mg_fopen(t2, "r"); #if MG_ENABLE_SSI if (is_index && fp == NULL) { char *p = t2 + strlen(t2); while (p > t2 && p[-1] != '/') p--; strncpy(p, "index.shtml", &t2[sizeof(t2)] - p - 2); t2[sizeof(t2) - 1] = '\0'; - fp = fopen(t2, "r"); + fp = mg_fopen(t2, "r"); } #endif #if MG_ENABLE_HTTP_DEBUG_ENDPOINT @@ -3054,6 +3113,7 @@ void mg_mgr_poll(struct mg_mgr *mgr, int ms) { + #ifndef MG_MAX_SSI_DEPTH #define MG_MAX_SSI_DEPTH 5 #endif @@ -3061,7 +3121,7 @@ void mg_mgr_poll(struct mg_mgr *mgr, int ms) { #if MG_ENABLE_SSI static char *mg_ssi(const char *path, const char *root, int depth) { struct mg_iobuf b = {NULL, 0, 0}; - FILE *fp = fopen(path, "rb"); + FILE *fp = mg_fopen(path, "rb"); if (fp != NULL) { char buf[BUFSIZ], arg[sizeof(buf)]; int ch, intag = 0; @@ -3735,21 +3795,42 @@ struct mg_str mg_url_pass(const char *url) { #if MG_ENABLE_FS -size_t mg_file_size(const char *path) { +int mg_stat(const char *path, mg_stat_t *st) { +#ifdef _WIN32 + wchar_t tmp[MG_PATH_MAX]; + MultiByteToWideChar(CP_UTF8, 0, path, -1, tmp, sizeof(tmp) / sizeof(tmp[0])); + return _wstati64(tmp, st); +#else + return stat(path, st); +#endif +} + +FILE *mg_fopen(const char *path, const char *mode) { +#ifdef _WIN32 + wchar_t b1[MG_PATH_MAX], b2[10]; + MultiByteToWideChar(CP_UTF8, 0, path, -1, b1, sizeof(b1) / sizeof(b1[0])); + MultiByteToWideChar(CP_UTF8, 0, mode, -1, b2, sizeof(b2) / sizeof(b2[0])); + return _wfopen(b1, b2); +#else + return fopen(path, mode); +#endif +} + +int64_t mg_file_size(const char *path) { #if MG_ARCH == MG_ARCH_FREERTOS struct FF_STAT st; return ff_stat(path, &st) == 0 ? st.st_size : 0; #else - struct stat st; - return stat(path, &st) == 0 ? st.st_size : 0; + mg_stat_t st; + return mg_stat(path, &st) == 0 ? st.st_size : 0; #endif } char *mg_file_read(const char *path) { FILE *fp; char *data = NULL; - size_t size = mg_file_size(path); - if ((fp = fopen(path, "rb")) != NULL) { + size_t size = (size_t) mg_file_size(path); + if ((fp = mg_fopen(path, "rb")) != NULL) { data = (char *) malloc(size + 1); if (data != NULL) { if (fread(data, 1, size, fp) != size) { @@ -3769,7 +3850,7 @@ bool mg_file_write(const char *path, const void *buf, size_t len) { FILE *fp; char tmp[MG_PATH_MAX]; snprintf(tmp, sizeof(tmp), "%s.%d", path, rand()); - fp = fopen(tmp, "wb"); + fp = mg_fopen(tmp, "wb"); if (fp != NULL) { result = fwrite(buf, 1, len, fp) == len; fclose(fp); @@ -3797,7 +3878,7 @@ bool mg_file_printf(const char *path, const char *fmt, ...) { } void mg_random(void *buf, size_t len) { - FILE *fp = fopen("/dev/urandom", "rb"); + FILE *fp = mg_fopen("/dev/urandom", "rb"); size_t i, n = 0; if (fp != NULL) n = fread(buf, 1, len, fp); if (fp == NULL || n <= 0) { diff --git a/mongoose.h b/mongoose.h index fc883dc7..b62b6123 100644 --- a/mongoose.h +++ b/mongoose.h @@ -428,7 +428,7 @@ void mg_timer_poll(unsigned long uptime_ms); char *mg_file_read(const char *path); -size_t mg_file_size(const char *path); +int64_t mg_file_size(const char *path); bool mg_file_write(const char *path, const void *buf, size_t len); bool mg_file_printf(const char *path, const char *fmt, ...); void mg_random(void *buf, size_t len); @@ -450,11 +450,11 @@ void mg_usleep(unsigned long usecs); #if MG_ENABLE_FS #ifdef _WIN32 typedef struct _stati64 mg_stat_t; -#define mg_stat(a, b) _stati64((a), (b)) #else typedef struct stat mg_stat_t; -#define mg_stat(a, b) stat((a), (b)) #endif +int mg_stat(const char *path, mg_stat_t *); +FILE *mg_fopen(const char *fp, const char *mode); #endif #define mg_htons(x) mg_ntohs(x) diff --git a/src/http.c b/src/http.c index c758cb50..44cd4a1f 100644 --- a/src/http.c +++ b/src/http.c @@ -271,7 +271,7 @@ int mg_http_upload(struct mg_connection *c, struct mg_http_message *hm, snprintf(path, sizeof(path), "%s%c%s", dir, MG_DIRSEP, name); LOG(LL_DEBUG, ("%p %d bytes @ %d [%s]", c->fd, (int) hm->body.len, (int) oft, name)); - if ((fp = fopen(path, oft == 0 ? "wb" : "ab")) == NULL) { + if ((fp = mg_fopen(path, oft == 0 ? "wb" : "ab")) == NULL) { mg_http_reply(c, 400, "", "fopen(%s): %d", name, errno); return -2; } else { @@ -309,9 +309,9 @@ static const char *guess_content_type(const char *filename) { size_t ext_len; const char *type; } * t, types[] = { - MIME_ENTRY("html", "text/html"), - MIME_ENTRY("htm", "text/html"), - MIME_ENTRY("shtml", "text/html"), + MIME_ENTRY("html", "text/html; charset=utf-8"), + MIME_ENTRY("htm", "text/html; charset=utf-8"), + MIME_ENTRY("shtml", "text/html; charset=utf-8"), MIME_ENTRY("css", "text/css"), MIME_ENTRY("js", "text/javascript"), MIME_ENTRY("mjs", "text/javascript"), @@ -322,7 +322,7 @@ static const char *guess_content_type(const char *filename) { MIME_ENTRY("jpeg", "image/jpeg"), MIME_ENTRY("png", "image/png"), MIME_ENTRY("svg", "image/svg+xml"), - MIME_ENTRY("txt", "text/plain"), + MIME_ENTRY("txt", "text/plain; charset=utf-8"), MIME_ENTRY("wav", "audio/wav"), MIME_ENTRY("mp3", "audio/mpeg"), MIME_ENTRY("mid", "audio/mid"), @@ -359,18 +359,21 @@ static const char *guess_content_type(const char *filename) { if (mg_ncasecmp(t->ext, &filename[n - t->ext_len], t->ext_len)) continue; return t->type; } - return "text/plain"; + return "text/plain; charset=utf-8"; } void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm, const char *path, const char *mime, const char *hdrs) { struct mg_str *inm = mg_http_get_header(hm, "If-None-Match"); mg_stat_t st; - FILE *fp = fopen(path, "rb"); char etag[64]; + FILE *fp = mg_fopen(path, "rb"); if (fp == NULL || mg_stat(path, &st) != 0 || mg_http_etag(etag, sizeof(etag), &st) != etag) { + LOG(LL_DEBUG, + ("404 [%.*s] [%s] %p", (int) hm->uri.len, hm->uri.ptr, path, fp)); mg_http_reply(c, 404, "", "%s", "Not found\n"); + if (fp != NULL) fclose(fp); } else if (inm != NULL && mg_vcasecmp(inm, etag) == 0) { fclose(fp); mg_printf(c, "HTTP/1.1 304 Not Modified\r\nContent-Length: 0\r\n\r\n"); @@ -530,12 +533,34 @@ struct dirent *readdir(DIR *d) { } #endif -static void printdirentry(struct mg_connection *c, struct mg_http_message *hm, - const char *name, mg_stat_t *stp) { - char size[64], mod[64]; +static bool mg_is_safe(int c) { + return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || strchr("._-$,;~()/", c) != NULL; +} + +static int mg_url_encode(const char *s, char *buf, size_t len) { + int i, n = 0; + for (i = 0; s[i] != '\0'; i++) { + int c = *((const unsigned char *) (s + i)); + if ((size_t) n + 4 >= len) return 0; + if (mg_is_safe(c)) { + buf[n++] = s[i]; + } else { + buf[n++] = '%'; + mg_hex(&s[i], 1, &buf[n]); + n += 2; + } + } + return n; +} + +static void printdirentry(struct mg_connection *c, const char *name, + mg_stat_t *stp) { + char size[64], mod[64], path[MG_PATH_MAX]; int is_dir = S_ISDIR(stp->st_mode); const char *slash = is_dir ? "/" : ""; - const char *es = hm->uri.ptr[hm->uri.len - 1] != '/' ? "/" : ""; + // const char *es = hm->uri.ptr[hm->uri.len - 1] != '/' ? "/" : ""; + int n = 0; if (is_dir) { snprintf(size, sizeof(size), "%s", "[DIR]"); @@ -551,11 +576,11 @@ static void printdirentry(struct mg_connection *c, struct mg_http_message *hm, } } strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", localtime(&stp->st_mtime)); + n = mg_url_encode(name, path, sizeof(path)); mg_printf(c, - " " + " " "\n", - (int) hm->uri.len, hm->uri.ptr, es, name, slash, name, slash, mod, - size); + n, path, slash, name, slash, mod, size); } static void listdir(struct mg_connection *c, struct mg_http_message *hm, @@ -563,20 +588,52 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm, char path[MG_PATH_MAX], *p = &dir[strlen(dir) - 1], tmp[10]; struct dirent *dp; DIR *dirp; + static const char *sort_js_code = + ""; while (p > dir && *p != '/') *p-- = '\0'; if ((dirp = (opendir(dir))) != NULL) { size_t off, n; - mg_printf(c, "%s\r\n", "HTTP/1.1 200 OK\r\nContent-Length: \r\n"); + mg_printf(c, "%s\r\n", + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/html; charset=utf-8\r\n" + "Content-Length: \r\n"); off = c->send.len; // Start of body mg_printf(c, - "Index of %.*s" + "Index of %.*s%s%s" "" "

Index of %.*s

NameModifiedSize

Name" + "ModifiedSize

%s%s
%s%s%s%s
" - "" - "\n", - (int) hm->uri.len, hm->uri.ptr, (int) hm->uri.len, hm->uri.ptr); + "" + "" + "" + "" + "\n", + (int) hm->uri.len, hm->uri.ptr, sort_js_code, sort_js_code2, + (int) hm->uri.len, hm->uri.ptr); + while ((dp = readdir(dirp)) != NULL) { mg_stat_t st; const char *sep = dp->d_name[0] == MG_DIRSEP ? "/" : ""; @@ -588,7 +645,7 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm, } else if (mg_stat(path, &st) != 0) { LOG(LL_ERROR, ("%lu stat(%s): %d", c->id, path, errno)); } else { - printdirentry(c, hm, dp->d_name, &st); + printdirentry(c, dp->d_name, &st); } } closedir(dirp); @@ -622,6 +679,7 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm, size_t n1 = strlen(t1), n2; mg_url_decode(hm->uri.ptr, hm->uri.len, t1 + n1, sizeof(t1) - n1, 0); + LOG(LL_DEBUG, ("SERVE: [%s]", t1 + n1)); t1[sizeof(t1) - 1] = '\0'; n2 = strlen(t1); while (n2 > 0 && t1[n2 - 1] == '/') t1[--n2] = 0; @@ -637,16 +695,17 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm, if (strlen(t2) < n1 || memcmp(t1, t2, n1) != 0) { // Requested file is located outside root directory, fail - mg_http_reply(c, 404, "", "Not found %.*s\n", hm->uri.len, hm->uri.ptr); + mg_http_reply(c, 404, "", "Not found %.*s\n", (int) hm->uri.len, + hm->uri.ptr); } else { - FILE *fp = fopen(t2, "r"); + FILE *fp = mg_fopen(t2, "r"); #if MG_ENABLE_SSI if (is_index && fp == NULL) { char *p = t2 + strlen(t2); while (p > t2 && p[-1] != '/') p--; strncpy(p, "index.shtml", &t2[sizeof(t2)] - p - 2); t2[sizeof(t2) - 1] = '\0'; - fp = fopen(t2, "r"); + fp = mg_fopen(t2, "r"); } #endif #if MG_ENABLE_HTTP_DEBUG_ENDPOINT diff --git a/src/ssi.c b/src/ssi.c index 0417d51c..b862afa8 100644 --- a/src/ssi.c +++ b/src/ssi.c @@ -1,5 +1,6 @@ -#include "log.h" #include "ssi.h" +#include "log.h" +#include "util.h" #ifndef MG_MAX_SSI_DEPTH #define MG_MAX_SSI_DEPTH 5 @@ -8,7 +9,7 @@ #if MG_ENABLE_SSI static char *mg_ssi(const char *path, const char *root, int depth) { struct mg_iobuf b = {NULL, 0, 0}; - FILE *fp = fopen(path, "rb"); + FILE *fp = mg_fopen(path, "rb"); if (fp != NULL) { char buf[BUFSIZ], arg[sizeof(buf)]; int ch, intag = 0; diff --git a/src/util.c b/src/util.c index 6dbbd170..bee82fd4 100644 --- a/src/util.c +++ b/src/util.c @@ -2,21 +2,42 @@ #include "util.h" #if MG_ENABLE_FS -size_t mg_file_size(const char *path) { +int mg_stat(const char *path, mg_stat_t *st) { +#ifdef _WIN32 + wchar_t tmp[MG_PATH_MAX]; + MultiByteToWideChar(CP_UTF8, 0, path, -1, tmp, sizeof(tmp) / sizeof(tmp[0])); + return _wstati64(tmp, st); +#else + return stat(path, st); +#endif +} + +FILE *mg_fopen(const char *path, const char *mode) { +#ifdef _WIN32 + wchar_t b1[MG_PATH_MAX], b2[10]; + MultiByteToWideChar(CP_UTF8, 0, path, -1, b1, sizeof(b1) / sizeof(b1[0])); + MultiByteToWideChar(CP_UTF8, 0, mode, -1, b2, sizeof(b2) / sizeof(b2[0])); + return _wfopen(b1, b2); +#else + return fopen(path, mode); +#endif +} + +int64_t mg_file_size(const char *path) { #if MG_ARCH == MG_ARCH_FREERTOS struct FF_STAT st; return ff_stat(path, &st) == 0 ? st.st_size : 0; #else - struct stat st; - return stat(path, &st) == 0 ? st.st_size : 0; + mg_stat_t st; + return mg_stat(path, &st) == 0 ? st.st_size : 0; #endif } char *mg_file_read(const char *path) { FILE *fp; char *data = NULL; - size_t size = mg_file_size(path); - if ((fp = fopen(path, "rb")) != NULL) { + size_t size = (size_t) mg_file_size(path); + if ((fp = mg_fopen(path, "rb")) != NULL) { data = (char *) malloc(size + 1); if (data != NULL) { if (fread(data, 1, size, fp) != size) { @@ -36,7 +57,7 @@ bool mg_file_write(const char *path, const void *buf, size_t len) { FILE *fp; char tmp[MG_PATH_MAX]; snprintf(tmp, sizeof(tmp), "%s.%d", path, rand()); - fp = fopen(tmp, "wb"); + fp = mg_fopen(tmp, "wb"); if (fp != NULL) { result = fwrite(buf, 1, len, fp) == len; fclose(fp); @@ -64,7 +85,7 @@ bool mg_file_printf(const char *path, const char *fmt, ...) { } void mg_random(void *buf, size_t len) { - FILE *fp = fopen("/dev/urandom", "rb"); + FILE *fp = mg_fopen("/dev/urandom", "rb"); size_t i, n = 0; if (fp != NULL) n = fread(buf, 1, len, fp); if (fp == NULL || n <= 0) { diff --git a/src/util.h b/src/util.h index fe4ecf24..9b46a1a7 100644 --- a/src/util.h +++ b/src/util.h @@ -4,7 +4,7 @@ #include "str.h" char *mg_file_read(const char *path); -size_t mg_file_size(const char *path); +int64_t mg_file_size(const char *path); bool mg_file_write(const char *path, const void *buf, size_t len); bool mg_file_printf(const char *path, const char *fmt, ...); void mg_random(void *buf, size_t len); @@ -26,11 +26,11 @@ void mg_usleep(unsigned long usecs); #if MG_ENABLE_FS #ifdef _WIN32 typedef struct _stati64 mg_stat_t; -#define mg_stat(a, b) _stati64((a), (b)) #else typedef struct stat mg_stat_t; -#define mg_stat(a, b) stat((a), (b)) #endif +int mg_stat(const char *path, mg_stat_t *); +FILE *mg_fopen(const char *fp, const char *mode); #endif #define mg_htons(x) mg_ntohs(x)
NameModifiedSize

Name" + "ModifiedSize