On systems where dirent provides a `d_type` field, we currently fall
back to stat() only for DT_UNKNOWN values.
Do so for all unexpected `d_type` values instead (that is, anything
different from DT_DIR, DT_REG and DT_LNK).
This is because there's no guarantee that `d_type` will be meaningful
for all OSes and filesystems. One such example is macOS Tiger, where
`d_type` will hold bogus values for the .aiff files of cddafs mount
points (as triggered by MacOSXAudioCDManager). (This bug appears to
have been fixed in cddafs-242.0.1, around the Snow Leopard area.)
When using stat() over the same files, the proper file type is
returned, though. Hence the need for the stat() fallback to be
triggered in more cases than DT_UNKNOWN.
This fixes Indy3 FM-TOWNS music being silent on macOS Tiger, when
playing from the original CD.
The JNI global references are limited in count and we overflow it for
games with a huge number of files (like Zork Nemesis).
Instead, track all the nodes from Java side using a unique identifier
generated using an atomic counter.
Then, all JNI calls either use a temporary local reference to access
node data or use the unique identifier.
This makes us use a single global reference per tree instead of
duplicating them on each filesystem node creation.
Thanks to the SharedPtr, the global reference is automatically
deallocated when needed.
This is the first step to avoid global references overflow.
Atari only support 8.3 file names and adding a tmp suffix for atomic
writes breaks this.
Make the WriteMode_WriteAtomic flag available in all cases and fall back
on unatomic write in this case.
This implementation creates a temporary file (suffixed with .tmp) and
renames it to the expected file name when the file is closed.
If the renaming fails, the destination file is removed and renaming is
tried again to handle cases where renaming over an existing file is not
supported by the underlying OS.
When creating an atomic write stream, the file is only created once it
is closed.
This can be done using a temporary file.
This commit only adds the API but not the proper implementation.
This reverts commit 99dc7641a9.
This causes bug #15392, a build failure on Dreamcast and changes too
much the semantics.
A better approach will need to be found, especially for streaming files
like logs.
A temporary file is used to write the data and the file is renamed when
it is closed.
The string containing the destination path is a stored as a pointer to
limit the size of the object (which is already doubled).
In most cases they are the same, but in the case of a sandboxed filesystem,
they may be different. Mapping to the full system path allows using the
path with system functions, such as fopen() or third party libraries (for
example to pass a soundfont path to the fluidsynth library).