fix: ports - netsurf renders pages (mmap, resources, error loop)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NQRTGoYgnZQsh7uCh6Jsxm
This commit is contained in:
2026-08-08 14:44:53 +02:00
co-authored by Claude Opus 5
parent f4dce0cdd6
commit 15f508d003
6 changed files with 250 additions and 24 deletions
@@ -1,5 +1,5 @@
diff --git a/utils/config.h b/utils/config.h
index 3914771fd..09f2659d6 100644
index 3914771fd..578280321 100644
--- a/utils/config.h
+++ b/utils/config.h
@@ -119,7 +119,7 @@ char *strchrnul(const char *s, int c);
@@ -11,7 +11,22 @@ index 3914771fd..09f2659d6 100644
#undef HAVE_UTSNAME
#endif
@@ -158,14 +158,14 @@ char *realpath(const char *path, char *resolved_path);
@@ -144,8 +144,13 @@ char *realpath(const char *path, char *resolved_path);
#undef HAVE_STDOUT
#endif
+/* MontaukOS: the libc mmap() is anonymous-only (it is a thin wrapper over
+ * SYS_ALLOC and rejects any fd != -1), so the file fetcher's
+ * mmap(..., MAP_SHARED, fd, 0) fails and every file: URL dies with "Unable to
+ * map memory for file data buffer". The fread() fallback in the same function
+ * is what we want. */
#define HAVE_MMAP
-#if (defined(_WIN32) || defined(__riscos__) || defined(__HAIKU__) || defined(__BEOS__) || defined(__amigaos4__) || defined(__AMIGA__) || defined(__MINT__))
+#if (defined(_WIN32) || defined(__riscos__) || defined(__HAIKU__) || defined(__BEOS__) || defined(__amigaos4__) || defined(__AMIGA__) || defined(__MINT__) || defined(__montauk__))
#undef HAVE_MMAP
#endif
@@ -158,14 +163,14 @@ char *realpath(const char *path, char *resolved_path);
#define HAVE_DIRFD
#define HAVE_UNLINKAT
#define HAVE_FSTATAT
@@ -0,0 +1,35 @@
diff --git a/utils/file.c b/utils/file.c
index 75a8a1c03..a8ab70f67 100644
--- a/utils/file.c
+++ b/utils/file.c
@@ -152,6 +152,30 @@ static nserror posix_nsurl_to_path(struct nsurl *url, char **path_out)
return res;
}
+#if defined(__montauk__)
+ /*
+ * MontaukOS absolute paths are drive-qualified ("0:/dir/file"). The
+ * file: URL syntax requires a leading slash before the path, so the
+ * round trip through path_to_nsurl() yields "/0%3A/dir/file", which
+ * unescapes to "/0:/dir/file". Resolving that treats the leading slash
+ * as "root of the current drive" and leaves the drive prefix as a
+ * directory name, producing "0:/0:/dir/file".
+ *
+ * Drop the slash when what follows is a drive prefix, restoring the
+ * original path.
+ */
+ if (path[0] == '/') {
+ const char *p = path + 1;
+
+ while (*p >= '0' && *p <= '9') {
+ p++;
+ }
+ if ((p > path + 1) && (*p == ':')) {
+ memmove(path, path + 1, strlen(path));
+ }
+ }
+#endif
+
*path_out = path;
return NSERROR_OK;
@@ -0,0 +1,97 @@
diff --git a/frontends/monkey/browser.c b/frontends/monkey/browser.c
index 958375486..6b406f552 100644
--- a/frontends/monkey/browser.c
+++ b/frontends/monkey/browser.c
@@ -27,10 +27,13 @@
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/nsurl.h"
+#include "utils/nsoption.h"
#include "netsurf/mouse.h"
#include "netsurf/window.h"
#include "netsurf/browser_window.h"
+#include "netsurf/content_type.h"
#include "netsurf/plotters.h"
+#include "css/utils.h"
#include "monkey/output.h"
#include "monkey/browser.h"
@@ -599,6 +602,69 @@ monkey_window_handle_redraw(int argc, char **argv)
moutf(MOUT_WINDOW, "REDRAW WIN %d STOP", atoi(argv[2]));
}
+/**
+ * WINDOW DUMP <win> [path]
+ *
+ * Port-local diagnostic. The layout dump goes to a file because it is
+ * hundreds of lines, then the head of it is echoed so the box geometry is
+ * visible without any way to get a file off the ramdisk. The LENGTHS line
+ * carries the inputs every CSS length conversion depends on -- if the DPI or
+ * font sizes come out wrong, every box is wrong and nothing plots.
+ */
+static void
+monkey_window_handle_dump(int argc, char **argv)
+{
+ const char *path = (argc > 3) ? argv[3] : "0:/users/admin/nsbox.txt";
+ struct gui_window *gw;
+ char line[512];
+ int lineno;
+ FILE *f;
+
+ if (argc != 3 && argc != 4) {
+ moutf(MOUT_ERROR, "WINDOW DUMP ARGS BAD");
+ return;
+ }
+
+ gw = monkey_find_window_by_num(atoi(argv[2]));
+ if (gw == NULL) {
+ moutf(MOUT_ERROR, "WINDOW NUM BAD");
+ return;
+ }
+
+ /* Raw css_fixed (22.10), not FIXTOINT: a value that is merely small
+ * rather than zero has to stay visible. */
+ moutf(MOUT_WINDOW,
+ "DUMP WIN %s LENGTHS DPI %d FONT_SIZE %d FONT_MIN %d SCALE %d",
+ argv[2], (int) nscss_screen_dpi, nsoption_int(font_size),
+ nsoption_int(font_min_size), nsoption_int(scale));
+
+ f = fopen(path, "w");
+ if (f == NULL) {
+ moutf(MOUT_ERROR, "WINDOW DUMP OPEN FAILED %s", path);
+ return;
+ }
+
+ browser_window_debug_dump(gw->bw, f, CONTENT_DEBUG_RENDER);
+ fclose(f);
+
+ f = fopen(path, "r");
+ if (f == NULL) {
+ moutf(MOUT_ERROR, "WINDOW DUMP REOPEN FAILED %s", path);
+ return;
+ }
+
+ for (lineno = 0; lineno < 40; lineno++) {
+ if (fgets(line, sizeof(line), f) == NULL) {
+ break;
+ }
+ line[strcspn(line, "\n")] = '\0';
+ moutf(MOUT_WINDOW, "DUMP WIN %s BOX %s", argv[2], line);
+ }
+ fclose(f);
+
+ moutf(MOUT_WINDOW, "DUMP WIN %s END LINES %d", argv[2], lineno);
+}
+
static void
monkey_window_handle_reload(int argc, char **argv)
{
@@ -721,6 +787,8 @@ monkey_window_handle_command(int argc, char **argv)
monkey_window_handle_stop(argc, argv);
} else if (strcmp(argv[1], "REDRAW") == 0) {
monkey_window_handle_redraw(argc, argv);
+ } else if (strcmp(argv[1], "DUMP") == 0) {
+ monkey_window_handle_dump(argc, argv);
} else if (strcmp(argv[1], "RELOAD") == 0) {
monkey_window_handle_reload(argc, argv);
} else if (strcmp(argv[1], "EXEC") == 0) {
@@ -0,0 +1,29 @@
diff --git a/desktop/browser_window.c b/desktop/browser_window.c
index 226741be5..57da7d56e 100644
--- a/desktop/browser_window.c
+++ b/desktop/browser_window.c
@@ -1338,6 +1338,24 @@ browser_window__handle_fetcherror(struct browser_window *bw,
memset(&params, 0, sizeof(params));
+ /* If it is the error page itself that failed, navigating to the error
+ * page again lands straight back here. Nothing bounds that: the pair
+ * recurses, allocating a content per turn, until the heap is gone and
+ * the real failure is buried under hundreds of retries. Report the
+ * reason and stop instead. */
+ if (nsurl_compare(url, corestring_nsurl_about_query_fetcherror,
+ NSURL_COMPLETE)) {
+ NSLOG(netsurf, WARNING,
+ "error page itself failed: %s -- not retrying", reason);
+ fprintf(stderr,
+ "netsurf: error page failed (%s); giving up\n", reason);
+ browser_window_set_status(bw, reason);
+ return browser_window_stop_throbber(bw);
+ }
+
+ fprintf(stderr, "netsurf: fetch of '%s' failed: %s\n",
+ nsurl_access(url), reason);
+
params.url = nsurl_ref(corestring_nsurl_about_query_fetcherror);
params.referrer = nsurl_ref(url);
params.flags = BW_NAVIGATE_HISTORY | BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE | BW_NAVIGATE_INTERNAL;