[COMMITTED] a68: Fix POSIX fopen flags

Pietro Monteiro pietro@sociotechnical.xyz
Fri Nov 14 05:20:47 GMT 2025


Caught while testing the lseek patch.

From: Pietro Monteiro <pietro@sociotechnical.xyz>
Subject: [PATCH] a68: Fix POSIX fopen flags

There was no check for the file_o_default flag, so add one.
Use the same values as glibc and musl for read only, read write, write
only and truncate flags.

gcc/ChangeLog:

	* algol68/a68-low-prelude.cc (a68_lower_posixfileodefault): Sync
	with libga68/ga68-posix.c.
	(a68_lower_posixfileordwr): Likewise
	(a68_lower_posixfileordonly): Likewise
	(a68_lower_posixfileowronly): Likewise
	(a68_lower_posixfileotrunc): Likewise

ChangeLog:

	* libga68/ga68-posix.c (FILE_O_DEFAULT): Change to 0x99999999.
	(FILE_O_RDONLY): Change to 0x0.
	(FILE_O_WRONLY): Change to 0x1.
	(FILE_O_RDWR): Change to 0x2.
	(FILE_O_TRUNC): Change to 0x8.
	(_libga68_open): New function.
	(_libga68_posixfopen): When the default flag is passed try to
	open the file read/write. Failing that, try write only,
	failing that read only.
	* libga68/ga68.h (_libga68_posixfopen): Adjust prototype.

Signed-off-by: Pietro Monteiro <pietro@sociotechnical.xyz>
---
 gcc/algol68/a68-low-prelude.cc | 10 +++----
 libga68/ga68-posix.c           | 55 ++++++++++++++++++++++++++--------
 libga68/ga68.h                 |  3 +-
 3 files changed, 50 insertions(+), 18 deletions(-)

diff --git a/gcc/algol68/a68-low-prelude.cc b/gcc/algol68/a68-low-prelude.cc
index 727dfd4e8ea..9181d1bb720 100644
--- a/gcc/algol68/a68-low-prelude.cc
+++ b/gcc/algol68/a68-low-prelude.cc
@@ -2036,7 +2036,7 @@ a68_lower_posixfileodefault (NODE_T *p ATTRIBUTE_UNUSED,
 			     LOW_CTX_T ctx ATTRIBUTE_UNUSED)
 {
   /* Please keep in sync with libga68/ga68-posix.c  */
-  return build_int_cst (a68_bits_type, 0x0);
+  return build_int_cst (a68_bits_type, 0x99999999);
 }
 
 tree
@@ -2044,7 +2044,7 @@ a68_lower_posixfileordwr (NODE_T *p ATTRIBUTE_UNUSED,
 			  LOW_CTX_T ctx ATTRIBUTE_UNUSED)
 {
   /* Please keep in sync with libga68/ga68-posix.c  */
-  return build_int_cst (a68_bits_type, 0x3);
+  return build_int_cst (a68_bits_type, 0x2);
 }
 
 tree
@@ -2052,7 +2052,7 @@ a68_lower_posixfileordonly (NODE_T *p ATTRIBUTE_UNUSED,
 			    LOW_CTX_T ctx ATTRIBUTE_UNUSED)
 {
   /* Please keep in sync with libga68/ga68-posix.c  */
-  return build_int_cst (a68_bits_type, 0x1);
+  return build_int_cst (a68_bits_type, 0x0);
 }
 
 tree
@@ -2060,7 +2060,7 @@ a68_lower_posixfileowronly (NODE_T *p ATTRIBUTE_UNUSED,
 			    LOW_CTX_T ctx ATTRIBUTE_UNUSED)
 {
   /* Please keep in sync with libga68/ga68-posix.c  */
-  return build_int_cst (a68_bits_type, 0x2);
+  return build_int_cst (a68_bits_type, 0x1);
 }
 
 tree
@@ -2068,7 +2068,7 @@ a68_lower_posixfileotrunc (NODE_T *p ATTRIBUTE_UNUSED,
 			   LOW_CTX_T ctx ATTRIBUTE_UNUSED)
 {
   /* Please keep in sync with libga68/ga68-posix.c  */
-  return build_int_cst (a68_bits_type, 0x4);
+  return build_int_cst (a68_bits_type, 0x8);
 }
 
 tree
diff --git a/libga68/ga68-posix.c b/libga68/ga68-posix.c
index 51c92f1cdfe..108bb97f24c 100644
--- a/libga68/ga68-posix.c
+++ b/libga68/ga68-posix.c
@@ -73,19 +73,54 @@ _libga68_posixstrerror (int errnum, size_t *len)
   return _libga68_u8_to_u32 ((const uint8_t *)str, strlen (str), NULL, len);
 }
 
-#define FILE_O_DEFAULT 0x0
-#define FILE_O_RDONLY  0x1
-#define FILE_O_WRONLY  0x2
-#define FILE_O_RDWR    0x3
-#define FILE_O_TRUNC   0x4
+/* Helper for _libga68_posixfopen.  */
+static int
+_libga68_open (const char *path, unsigned int flags)
+{
+  int fd = open (path, flags);
+  _libga68_errno = errno;
+  return fd;
+}
+
+#define FILE_O_DEFAULT 0x99999999
+#define FILE_O_RDONLY  0x0
+#define FILE_O_WRONLY  0x1
+#define FILE_O_RDWR    0x2
+#define FILE_O_TRUNC   0x8
 
 int
-_libga68_posixfopen (uint32_t *pathname, size_t len, size_t stride,
+_libga68_posixfopen (const uint32_t *pathname, size_t len, size_t stride,
 		     unsigned int flags)
 {
+  int fd;
   int openflags = 0;
   size_t u8len;
-  uint8_t *u8pathname = _libga68_u32_to_u8 (pathname, len, stride, NULL, &u8len);
+  const uint8_t *u8pathname = _libga68_u32_to_u8 (pathname, len, stride, NULL,
+						  &u8len);
+  char *filepath = (char *) _libga68_malloc_internal (u8len + 1);
+  memcpy (filepath, u8pathname, u8len);
+  filepath[u8len] = '\0';
+
+  /* Default mode: try read-write initially.
+     If that fails, then try read-only.
+     If that fails, then try write-only.  */
+  if (flags == FILE_O_DEFAULT)
+    {
+      openflags = O_RDWR;
+      if ((fd = _libga68_open (filepath, openflags)) < 0)
+	{
+	  openflags = O_RDONLY;
+	  if ((fd = _libga68_open (filepath, openflags)) < 0)
+	    {
+	      openflags = O_WRONLY;
+	      fd = _libga68_open (filepath, openflags);
+	      _libga68_free_internal (filepath);
+	      return fd;
+	    }
+	}
+      _libga68_free_internal (filepath);
+      return fd;
+    }
 
   if (flags & FILE_O_RDONLY)
     openflags |= O_RDONLY;
@@ -96,11 +131,7 @@ _libga68_posixfopen (uint32_t *pathname, size_t len, size_t stride,
   if (flags & FILE_O_TRUNC)
     openflags |= O_TRUNC;
 
-  char *filepath = _libga68_malloc_internal (u8len + 1);
-  memcpy (filepath, u8pathname, u8len);
-  filepath[u8len] = '\0';
-  int fd = open (filepath, openflags);
-  _libga68_errno = errno;
+  fd = _libga68_open (filepath, openflags);
   _libga68_free_internal (filepath);
   return fd;
 }
diff --git a/libga68/ga68.h b/libga68/ga68.h
index 4149d81c484..a7e4080c730 100644
--- a/libga68/ga68.h
+++ b/libga68/ga68.h
@@ -78,7 +78,8 @@ int _libga68_posixerrno (void);
 void _libga68_posixperror (uint32_t *s, size_t len, size_t stride);
 uint32_t *_libga68_posixstrerror (int errnum, size_t *len);
 long long int _libga68_posixfsize (int fd);
-int _libga68_posixfopen (uint32_t *pathname, size_t len, size_t stride, unsigned int flags);
+int _libga68_posixfopen (const uint32_t *pathname, size_t len, size_t stride,
+			 unsigned int flags);
 int _libga68_posixcreat (uint32_t *pathname, size_t len, size_t stride, uint32_t mode);
 int _libga68_posixclose (int fd);
 int _libga68_posixargc (void);
-- 
2.43.0



More information about the Algol68 mailing list