Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions cmake/check-anxs2ext-abi.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
# made of its own code bytes, and on a PiStorm32 A1200 neither card came up.
# This compiles a call through each typedef with the tree's flags and stops
# the configure unless the caller pops what it pushed: 8, 16 and 4 bytes.
# It also pins the record's offsets, which no version from MIN on may move.
#
# SPDX-License-Identifier: MIT

Expand All @@ -19,7 +20,18 @@ endif()
set(_s2x_dir "${CMAKE_BINARY_DIR}/check-anxs2ext-abi")
file(MAKE_DIRECTORY "${_s2x_dir}")
file(WRITE "${_s2x_dir}/probe.c" [=[
#include <stddef.h>
#include <aminetxduo/anxs2ext.h>
/* The record's prefix is the same at every version from MIN on: a driver
accepting [MIN, VERSION] reads these offsets whichever one it is handed. */
_Static_assert(offsetof(AnxdS2Extension, Version) == 0, "Version");
_Static_assert(offsetof(AnxdS2Extension, Size) == 2, "Size");
_Static_assert(offsetof(AnxdS2Extension, Request) == 4, "Request");
_Static_assert(offsetof(AnxdS2Extension, Accepted) == 8, "Accepted");
_Static_assert(offsetof(AnxdS2Extension, RxDirect) == 12, "RxDirect");
_Static_assert(offsetof(AnxdS2Extension, RxFilled) == 16, "RxFilled");
_Static_assert(offsetof(AnxdS2Extension, TxFlags) == 20, "TxFlags");
_Static_assert(sizeof(AnxdS2Extension) == 24, "size");
UBYTE *probe_rx_direct(AnxdS2RxDirect f, APTR io, ULONG len)
{
return f(io, len) + 1;
Expand Down
27 changes: 27 additions & 0 deletions install/Install-AmiNetXDuo
Original file line number Diff line number Diff line change
Expand Up @@ -2350,6 +2350,33 @@
(safe))
))

; A KEPT FILE FOLLOWS THE ASSIGN TOO. One written before the drawer named
; its drivers through AmiNetXDuo: says DEVICE=SYS:AmiNetXDuo/Devs/Networks/...
; and would go on opening that drawer's drivers under a library from wherever
; the assign points next. The Installer cannot read the line, so
; InstallSameFile rewrites it: only a DEVICE line naming one of our drivers
; in this drawer, or the one the assign still names, and only its value.
; Another driver, or one of ours elsewhere, is the user's choice and stays.
(if (AND KEEP_OLD DRAWER_LAYOUT)
(foreach D_IFDIR "~(#?.info)"
(if (< @each-type 0)
(
(set KEPT_IF (tackon D_IFDIR @each-name))
(if (<> 0
(run ("\"%s\" \"%s\" \"%s\" \"%s\" DEVICES"
S_SAMEFILE KEPT_IF (tackon D_DEVS "Networks")
"AmiNetXDuo:Devs/Networks")
(prompt "Pointing the kept configuration at this "
"drawer's drivers")
(help "A kept interface file that names a driver "
"of this drawer by its full path is changed to "
"name it through AmiNetXDuo:. Nothing else in "
"the file changes.")))
(message
"\"" KEPT_IF "\" could not be updated. If its DEVICE line "
"names a driver by this drawer's full path, change it to "
"AmiNetXDuo:Devs/Networks/ followed by the driver's name."))))))

; --- the netdb files, only where there is nothing already ----------------
;
; A machine that has had Roadshow or AmiTCP on it already has these, very
Expand Down
13 changes: 12 additions & 1 deletion src/tools/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ aminetxduo_add_tool(tool_addnetinterface AddNetInterface
# object; dos.library can. The archive keeps this beside the Installer and
# does not copy it into C:.
aminetxduo_add_tool(tool_installsamefile InstallSameFile
SOURCES installsamefile.c)
SOURCES installsamefile.c devicehome.c)

# The other Installer-only primitive: identify Emu68's supported on-board
# network devices from its device tree without opening either device.
Expand Down Expand Up @@ -910,6 +910,16 @@ if(NOT CMAKE_CROSSCOMPILING)
target_compile_options(test_netprefs_text PRIVATE -Wall -Wextra)
set_target_properties(test_netprefs_text PROPERTIES C_STANDARD 11)

# A kept interface file's DEVICE line follows the AmiNetXDuo: assign
# (InstallSameFile DEVICES): only our drivers in this drawer move.
add_executable(test_devicehome
test/test_devicehome.c
devicehome.c)
target_include_directories(test_devicehome PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}")
target_compile_options(test_devicehome PRIVATE -Wall -Wextra)
set_target_properties(test_devicehome PROPERTIES C_STANDARD 11)

# NetPrefs lays itself out from the gadget font's metrics. Every page at
# topaz 8, 11, a proportional 13 and a wide 15 keeps labels off borders
# and gadgets apart; a font too wide for 640 reports that it does not fit.
Expand Down Expand Up @@ -1149,6 +1159,7 @@ if(NOT CMAKE_CROSSCOMPILING)
add_test(NAME fetchurl_rfc3986 COMMAND test_fetchurl)
add_test(NAME toolsock_connect_budget COMMAND test_toolbudget)
add_test(NAME netprefs_preserves_text COMMAND test_netprefs_text)
add_test(NAME devicehome_rewrites_only_ours COMMAND test_devicehome)
add_test(NAME netprefs_font_layout COMMAND test_netprefs_layout)
add_test(NAME httpframe_bodies COMMAND test_httpframe)
add_test(NAME httplock_rfc4918 COMMAND test_httplock)
Expand Down
139 changes: 139 additions & 0 deletions src/tools/devicehome.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/* SPDX-License-Identifier: MIT */
#include "devicehome.h"

/* Every driver an install writes into its Devs/Networks. */
static const char *const dh_drivers[] =
{
"anxnet.device",
"anxgenet.device",
"anxwifipi.device",
"anxzz9000.device",
};

#define DH_DRIVERS (sizeof(dh_drivers) / sizeof(dh_drivers[0]))

static size_t dh_len(const char *s)
{
size_t n = 0;
while (s[n] != '\0') n++;
return n;
}

static char dh_lower(char c)
{
return (c >= 'A' && c <= 'Z') ? (char)(c + 32) : c;
}

/* AmigaDOS names compare without case. */
static int dh_equal(const char *a, size_t alen, const char *b)
{
size_t i;
for (i = 0; i < alen; i++)
if (b[i] == '\0' || dh_lower(a[i]) != dh_lower(b[i])) return 0;
return b[alen] == '\0';
}

int dh_absolute_driver(const char *value, size_t len, char *dir,
size_t dir_cap, const char **driver)
{
size_t colon = 0, base = 0, dir_len, i, d;

while (colon < len && value[colon] != ':') colon++;
/* No volume (":Devs/..." is the current one), or the assign itself. */
if (colon == 0 || colon >= len || dh_equal(value, colon, "AmiNetXDuo"))
return 0;
for (i = colon; i < len; i++)
if (value[i] == ':' || value[i] == '/') base = i + 1;

for (d = 0; d < DH_DRIVERS; d++)
if (dh_equal(value + base, len - base, dh_drivers[d])) break;
if (d == DH_DRIVERS)
return 0;

dir_len = (value[base - 1] == '/') ? base - 1 : base;
if (dir_len + 1 > dir_cap)
return 0;
for (i = 0; i < dir_len; i++) dir[i] = value[i];
dir[dir_len] = '\0';
*driver = dh_drivers[d];
return 1;
}

static int dh_put(char *out, size_t cap, size_t *used, const char *s, size_t n)
{
size_t i;
if (n > cap - *used) return 0;
for (i = 0; i < n; i++) out[(*used)++] = s[i];
return 1;
}

/* The value of a DEVICE line, as src/config/config_text.c reads it: "DEVICE",
optional '=', then one token or a quoted string. A quoted value with an
AmigaDOS '*' escape is not offered: its bytes are not the name. */
static int dh_device_value(const char *line, size_t len, size_t *vbeg,
size_t *vend)
{
size_t p = 0, k;

while (p < len && (line[p] == ' ' || line[p] == '\t')) p++;
k = p;
while (p < len && line[p] != '=' && line[p] != ' ' && line[p] != '\t' &&
line[p] != '\r')
p++;
if (!dh_equal(line + k, p - k, "device")) return 0;
while (p < len && (line[p] == ' ' || line[p] == '\t')) p++;
if (p < len && line[p] == '=') p++;
while (p < len && (line[p] == ' ' || line[p] == '\t')) p++;

if (p < len && line[p] == '"')
{
*vbeg = ++p;
while (p < len && line[p] != '"')
if (line[p++] == '*') return 0;
if (p >= len) return 0;
}
else
{
*vbeg = p;
while (p < len && line[p] != ' ' && line[p] != '\t' && line[p] != '\r' &&
line[p] != '#' && line[p] != ';')
p++;
}
*vend = p;
return p > *vbeg;
}

long dh_rehome(const char *old, size_t oldlen, char *out, size_t cap,
size_t *newlen, DhOursFn ours, void *ctx)
{
size_t at = 0, used = 0;
long rewritten = 0;

while (at < oldlen)
{
size_t end = at, vbeg, vend;
char dir[128];
const char *driver;

while (end < oldlen && old[end] != '\n') end++;
if (dh_device_value(old + at, end - at, &vbeg, &vend) &&
dh_absolute_driver(old + at + vbeg, vend - vbeg, dir, sizeof(dir),
&driver) &&
ours(dir, ctx))
{
if (!dh_put(out, cap, &used, old + at, vbeg) ||
!dh_put(out, cap, &used, DH_ASSIGN_NETWORKS "/",
sizeof(DH_ASSIGN_NETWORKS "/") - 1) ||
!dh_put(out, cap, &used, driver, dh_len(driver)))
return -1;
at += vend;
rewritten++;
}
if (end < oldlen) end++;
if (!dh_put(out, cap, &used, old + at, end - at))
return -1;
at = end;
}
*newlen = used;
return rewritten;
}
28 changes: 28 additions & 0 deletions src/tools/devicehome.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* Where an interface file's DEVICE= finds one of this stack's drivers. Pure
text, used by InstallSameFile and tested on the host (test_devicehome). */
#ifndef AMINETXDUO_DEVICEHOME_H
#define AMINETXDUO_DEVICEHOME_H

#include <stddef.h>

/* The drawer layout's own name for its drivers. */
#define DH_ASSIGN_NETWORKS "AmiNetXDuo:Devs/Networks"

/* For a DEVICE value naming one of OUR drivers by an absolute path that does
not go through the AmiNetXDuo: assign: returns 1, the directory part in
dir (NUL-terminated; "Vol:" or "Vol:a/b") and the driver's own name.
Returns 0 for anything else, including a dir that does not fit. */
int dh_absolute_driver(const char *value, size_t len, char *dir,
size_t dir_cap, const char **driver);

/* Asked for each candidate directory: nonzero when it is this drawer's. */
typedef int (*DhOursFn)(const char *dir, void *ctx);

/* Copy old to out, replacing the value of every DEVICE line that
dh_absolute_driver() accepts and ours() claims by
AmiNetXDuo:Devs/Networks/<driver>. Every other byte is kept. Returns the
number of lines rewritten, or -1 when out is too small. */
long dh_rehome(const char *old, size_t oldlen, char *out, size_t cap,
size_t *newlen, DhOursFn ours, void *ctx);

#endif
Loading
Loading