Skip to content

Support files above 4 GiB (dos64.library, from AROS) - #163

Open
pulchart wants to merge 12 commits into
ApolloTeam-dev:masterfrom
pulchart:wip/jpu/dos64
Open

pulchart wants to merge 12 commits into
ApolloTeam-dev:masterfrom
pulchart:wip/jpu/dos64

Conversation

@pulchart

@pulchart pulchart commented Nov 5, 2026

Copy link
Copy Markdown

Brings 4 GiB+ file support from AROS to ApolloOS, with fixes.

  • 64-bit DOS structures in the MorphOS V51 layout and the new dos64.library
  • crt, List, ASL, reqtools, MUI Dirlist, Find, Wanderer, Info and copy use it and show sizes above 4G.
  • dos: a seek back from above 2G is no longer taken as an error.
  • m68k: linklib stubs for functions returning 64 bits.
  • Also carries three dos.library fixes from several authors.

Tested with a pfs3aio build with large file support. Without dos64.library the 32-bit behaviour stays.

pulchart and others added 12 commits November 5, 2026 19:27
dos64.library shares them with dos.library.
The linklib stubs of a function returning QUAD or UQUAD paste the return type into the call macro name. Map those names to the plain macros, which return d0/d1.
FileInfoBlock is a single structure; fib_Size64, fib_NumBlocks64 and fib_ActExtFlags overlay fib_Reserved at the MorphOS V51 offsets, 64 bit members are 2 byte aligned on 32 bit targets. FileInfoBlock32 and FileInfoBlock64 stay as names of it. ExAllData gets ed_Size64 and ED_SIZE64, RecordLock64 the MorphOS layout, InfoData64 is the standard InfoData followed by 64 bit block counts.
dos64.library has the 64 bit calls: Seek64(), SetFileSize64(), GetFilePosition64(), GetFileSize64(), ChangeFilePosition64(), ChangeFileSize64(), Read64() and Write64(), Examine64(), ExNext64(), ExamineFH64() and ExamineName64(), Info64(), the record locking calls and AllocDosObject64(). It is version 51.0 and takes the 64 bit arguments with AROS_LHAQUAD.

The examine calls send ACTION_EXAMINE_OBJECT64, _NEXT64 and _FH64 on all systems. A handler that does not know them gets the 32 bit calls, and for a file of 2 GiB or more ACTION_GET_FILE_SIZE64 is asked for the size: with DupLock and OpenFromLock in Examine64(), by name in the directory in ExNext64(). A file that cannot be opened keeps the clamped size.

ExamineName64() reads the entry from the parent directory when a file open for writing cannot be locked, so the size of a file being written is available.
* dos: MatchFirst()/MatchNext() with a zero current directory

A process whose current directory is the zero lock (the root of the
boot volume) is legal, but MatchNext() took DupLock() of it returning
zero as a failure and returned IoErr(), which is 0 when nothing has
failed: MatchFirst() on a wildcard in a missing directory then reported
success with no match, and every MatchNext() after it did the same.
Directory Opus 5 loops forever on that while scanning dopus5:groups/.

Only a non-zero current directory that cannot be duplicated is an
error. Checked with MatchFirst("RAM:x/nodir/#?.info") after
CurrentDir(NULL): ERROR_OBJECT_NOT_FOUND, as with a current directory.

* dos: ExNext() on a zero lock

A zero lock stands for the root of the boot volume. Examine() already
sends its packet to GetFileSysTask() for it, but ExNext() dereferenced
the lock unconditionally, so MatchFirst("#?") after CurrentDir(NULL),
whose base AChain keeps an_Lock 0, page-faulted on fl->fl_Task.

ExNext() now falls back to GetFileSysTask() the same way. Checked with
MatchFirst("#?") after CurrentDir(NULL): it returns 0, MatchNext()
walks the boot volume root and ends with ERROR_NO_MORE_ENTRIES.
FRead() always went through the handle buffer, so a large read cost one
ACTION_READ packet per buffer: 100 packets for 100 KiB with the 1 KiB
m68k-amiga buffer. FWrite() copied every byte into the buffer and
flushed it in pieces the same way.

Once the buffer is empty, a read at least one buffer long now goes
straight into the caller's memory with a single Read(). A fully
buffered write of at least one buffer flushes what is pending and is
sent with a single Write(); line-buffered handles keep flushing at each
newline, and append-mode handles still seek to the end first.
Seed the read buffer with the last successful direct-read byte so both UnGetC forms continue to work, and allocate it before consuming input. Clamp individual Read requests to the signed LONG limit.

Retry short direct writes, stop on zero progress, and batch FWrite blocks with overflow-safe signed-length chunks so byte-block calls use the fast path. Keep append, pending-output and line-buffer behavior.

Expand DOS regression tests for direct-read pushback, mixed-read seek positions and pending buffered append writes. Add sanitized host tests for oversized requests, partial/error writes, replaced buffers and packet batching. Update copyright years and dos.library revision to 50.82.
Seek returns the old position, which is negative as a LONG above 2G. FWrite and Flush after a read took that for a failure.
It goes into the ext bank (E0) after dos.library.
fopen, fseek, ftell, fseeko, ftello, lseek, ftruncate, read, write, stat, statfs and getfsstat go through helpers that use dos64.library when it is installed and the 32 bit calls otherwise. A value that does not fit fails with EOVERFLOW. File systems that answer the 64 bit packets are probed once per file.

stat64 and fstat64 return the whole st_size, stat and fstat fail with EOVERFLOW for a file above 2G.
A size that fills 32 bits is asked again with ExamineName64 when dos64.library is installed, also for a file that is open for writing, which cannot be locked. The size is no longer sign extended, and the total of blocks is printed as 32 bits.
ASL, reqtools, MUI Dirlist, find, the Wanderer icon list, status bar, copy and the Info tool read the 32 bit size as unsigned and keep sizes and totals in 64 bits. A file whose 32 bit size is 4G-1 is asked again with ExamineName64 when dos64.library is installed, also when it is open for writing. Sorting by size is unsigned and the volume percentage of the reqtools requester no longer overflows.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants