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