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