aboutsummaryrefslogtreecommitdiff
path: root/libgloss/m68k/atari/atari-open.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgloss/m68k/atari/atari-open.c')
-rw-r--r--libgloss/m68k/atari/atari-open.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/libgloss/m68k/atari/atari-open.c b/libgloss/m68k/atari/atari-open.c
new file mode 100644
index 0000000..c610718
--- /dev/null
+++ b/libgloss/m68k/atari/atari-open.c
@@ -0,0 +1,78 @@
+/*
+ Copyright (C) 2025 Mikael Hildenborg
+ SPDX-License-Identifier: BSD-2-Clause
+*/
+
+#include <unistd.h>
+#include <_ansi.h>
+#include "atari-gem_errno.h"
+#include "atari-traps.h"
+
+// I really don't like having these defines here,
+// fcntl.h where they are, also defines a function for "open",
+// that is different from the one libgloss is supposed to provide...
+#ifndef O_CREAT
+#define O_CREAT 0x0200
+#endif // O_CREAT
+#ifndef O_APPEND
+#define O_APPEND 0x0008
+#endif // O_APPEND
+#ifndef O_EXCL
+#define O_EXCL 0x0800
+#endif // O_EXCL
+#ifndef O_TRUNC
+#define O_TRUNC 0x0400
+#endif // O_TRUNC
+
+// mode is ignored. Those kind of settings is not supported by the st.
+int open(const char *buf, int flags, int mode)
+{
+ int bios_handle = -1;
+ unsigned short bios_mode = (unsigned short)(flags & 0x3); // bits 0-1 the same for st and linux.
+ int create = flags & O_CREAT;
+ int append = flags & O_APPEND; // open doc says that seek end should be done before each write call. We assume that newlib handles that.
+ int excl = flags & O_EXCL; // File must be created by this call.
+ int trunc = flags & O_TRUNC; // File is forced to be created and thus truncated.
+
+ const char *bios_path = buf;
+ if (!trunc)
+ {
+ bios_handle = trap1_3d(bios_path, bios_mode);
+ }
+ if (bios_handle < 0 && (create || trunc))
+ {
+ unsigned short bios_attrib = 0;
+ bios_handle = trap1_3c(bios_path, bios_attrib);
+ }
+ else if (create && excl)
+ {
+ // We explicitly specified that file must be created, and it already existed, so error!
+ gem_error_to_errno(GEM_EACCDN);
+ // Close file.
+ trap1_3e((unsigned short)bios_handle);
+ return -1;
+ }
+
+ if (bios_handle >= 0 && append)
+ {
+ // Seek to end.
+ int new_file_pos = trap1_42(0, (unsigned short)bios_handle, 2);
+ if (new_file_pos < 0)
+ {
+ gem_error_to_errno(new_file_pos);
+ // Close file.
+ trap1_3e((unsigned short)bios_handle);
+ return -1;
+ }
+ }
+
+ if (bios_handle < 0)
+ {
+ gem_error_to_errno(bios_handle);
+ bios_handle = -1;
+ }
+ /*
+ If bios_handle is positive, then the low word is the gemdos handle, and the high word is zero.
+ */
+ return bios_handle;
+}