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