04bfb0
From 74b421cc877e412c4eda06757396a1e19fc756ba Mon Sep 17 00:00:00 2001
04bfb0
From: Tony Cook <tony@develop-help.com>
04bfb0
Date: Mon, 15 Jul 2019 11:53:23 +1000
04bfb0
Subject: [PATCH 3/3] (perl #134221) support O_APPEND for open ..., undef on
04bfb0
 VMS
04bfb0
MIME-Version: 1.0
04bfb0
Content-Type: text/plain; charset=UTF-8
04bfb0
Content-Transfer-Encoding: 8bit
04bfb0
04bfb0
VMS doesn't allow you to delete an open file like POSIXish systems
04bfb0
do, but you can mark a file to be deleted once it's closed, but
04bfb0
only when you open it.
04bfb0
04bfb0
Since VMS doesn't (yet) have mkostemp() we can add our own flag to
04bfb0
our mkostemp() emulation to pass the necessary magic to open() call
04bfb0
to delete the file on close.
04bfb0
04bfb0
Signed-off-by: Petr Písař <ppisar@redhat.com>
04bfb0
---
04bfb0
 perlio.c | 10 ++++++----
04bfb0
 util.c   | 15 ++++++++++++++-
04bfb0
 util.h   | 11 +++++++++++
04bfb0
 3 files changed, 31 insertions(+), 5 deletions(-)
04bfb0
04bfb0
diff --git a/perlio.c b/perlio.c
04bfb0
index 81ebc156ad..805959f840 100644
04bfb0
--- a/perlio.c
04bfb0
+++ b/perlio.c
04bfb0
@@ -5062,7 +5062,7 @@ PerlIO_tmpfile_flags(int imode)
04bfb0
      const int fd = win32_tmpfd_mode(imode);
04bfb0
      if (fd >= 0)
04bfb0
 	  f = PerlIO_fdopen(fd, "w+b");
04bfb0
-#elif ! defined(VMS) && ! defined(OS2)
04bfb0
+#elif ! defined(OS2)
04bfb0
      int fd = -1;
04bfb0
      char tempname[] = "/tmp/PerlIO_XXXXXX";
04bfb0
      const char * const tmpdir = TAINTING_get ? NULL : PerlEnv_getenv("TMPDIR");
04bfb0
@@ -5073,19 +5073,19 @@ PerlIO_tmpfile_flags(int imode)
04bfb0
 	 /* if TMPDIR is set and not empty, we try that first */
04bfb0
 	 sv = newSVpv(tmpdir, 0);
04bfb0
 	 sv_catpv(sv, tempname + 4);
04bfb0
-	 fd = Perl_my_mkostemp_cloexec(SvPVX(sv), imode);
04bfb0
+	 fd = Perl_my_mkostemp_cloexec(SvPVX(sv), imode | O_VMS_DELETEONCLOSE);
04bfb0
      }
04bfb0
      if (fd < 0) {
04bfb0
 	 SvREFCNT_dec(sv);
04bfb0
 	 sv = NULL;
04bfb0
 	 /* else we try /tmp */
04bfb0
-	 fd = Perl_my_mkostemp_cloexec(tempname, imode);
04bfb0
+	 fd = Perl_my_mkostemp_cloexec(tempname, imode | O_VMS_DELETEONCLOSE);
04bfb0
      }
04bfb0
      if (fd < 0) {
04bfb0
          /* Try cwd */
04bfb0
          sv = newSVpvs(".");
04bfb0
          sv_catpv(sv, tempname + 4);
04bfb0
-         fd = Perl_my_mkostemp_cloexec(SvPVX(sv), imode);
04bfb0
+         fd = Perl_my_mkostemp_cloexec(SvPVX(sv), imode | O_VMS_DELETEONCLOSE);
04bfb0
      }
04bfb0
      umask(old_umask);
04bfb0
      if (fd >= 0) {
04bfb0
@@ -5096,7 +5096,9 @@ PerlIO_tmpfile_flags(int imode)
04bfb0
          f = PerlIO_fdopen(fd, mode);
04bfb0
 	  if (f)
04bfb0
 	       PerlIOBase(f)->flags |= PERLIO_F_TEMP;
04bfb0
+#   ifndef VMS
04bfb0
 	  PerlLIO_unlink(sv ? SvPVX_const(sv) : tempname);
04bfb0
+#   endif
04bfb0
      }
04bfb0
      SvREFCNT_dec(sv);
04bfb0
 #else	/* !HAS_MKSTEMP, fallback to stdio tmpfile(). */
04bfb0
diff --git a/util.c b/util.c
04bfb0
index e6863f6dfe..165d13a39e 100644
04bfb0
--- a/util.c
04bfb0
+++ b/util.c
04bfb0
@@ -5712,6 +5712,11 @@ S_my_mkostemp(char *templte, int flags) {
04bfb0
     STRLEN len = strlen(templte);
04bfb0
     int fd;
04bfb0
     int attempts = 0;
04bfb0
+#ifdef VMS
04bfb0
+    int delete_on_close = flags & O_VMS_DELETEONCLOSE;
04bfb0
+
04bfb0
+    flags &= ~O_VMS_DELETEONCLOSE;
04bfb0
+#endif
04bfb0
 
04bfb0
     if (len < 6 ||
04bfb0
         templte[len-1] != 'X' || templte[len-2] != 'X' || templte[len-3] != 'X' ||
04bfb0
@@ -5725,7 +5730,15 @@ S_my_mkostemp(char *templte, int flags) {
04bfb0
         for (i = 1; i <= 6; ++i) {
04bfb0
             templte[len-i] = TEMP_FILE_CH[(int)(Perl_internal_drand48() * TEMP_FILE_CH_COUNT)];
04bfb0
         }
04bfb0
-        fd = PerlLIO_open3(templte, O_RDWR | O_CREAT | O_EXCL | flags, 0600);
04bfb0
+#ifdef VMS
04bfb0
+        if (delete_on_close) {
04bfb0
+            fd = open(templte, O_RDWR | O_CREAT | O_EXCL | flags, 0600, "fop=dlt");
04bfb0
+        }
04bfb0
+        else
04bfb0
+#endif
04bfb0
+        {
04bfb0
+            fd = PerlLIO_open3(templte, O_RDWR | O_CREAT | O_EXCL | flags, 0600);
04bfb0
+        }
04bfb0
     } while (fd == -1 && errno == EEXIST && ++attempts <= 100);
04bfb0
 
04bfb0
     return fd;
04bfb0
diff --git a/util.h b/util.h
04bfb0
index d8fa3e8396..d9df7b39c6 100644
04bfb0
--- a/util.h
04bfb0
+++ b/util.h
04bfb0
@@ -248,6 +248,17 @@ means arg not present, 1 is empty string/null byte */
04bfb0
 int mkstemp(char*);
04bfb0
 #endif
04bfb0
 
04bfb0
+#ifdef PERL_CORE
04bfb0
+#   if defined(VMS)
04bfb0
+/* only useful for calls to our mkostemp() emulation */
04bfb0
+#       define O_VMS_DELETEONCLOSE 0x40000000
04bfb0
+#       ifdef HAS_MKOSTEMP
04bfb0
+#           error 134221 will need a new solution for VMS
04bfb0
+#       endif
04bfb0
+#   else
04bfb0
+#       define O_VMS_DELETEONCLOSE 0
04bfb0
+#   endif
04bfb0
+#endif
04bfb0
 #if defined(HAS_MKOSTEMP) && defined(PERL_CORE)
04bfb0
 #   define Perl_my_mkostemp(templte, flags) mkostemp(templte, flags)
04bfb0
 #endif
04bfb0
-- 
04bfb0
2.20.1
04bfb0