summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Fulton <mikefultonpersonal@gmail.com>2021-12-31 13:50:32 -0800
committerKarl Williamson <khw@cpan.org>2022-01-01 18:09:35 -0700
commit1c267c880abb4d52f0dc23c70636b5f2e80253be (patch)
treedb658be8b12abcaefadb5cc012cb985e69a73b4f
parent7643f9bc98b3e5397ff14343c1c5f1ee3e00a8d9 (diff)
downloadperl-1c267c880abb4d52f0dc23c70636b5f2e80253be.tar.gz
Provide asciiopen and asciiopen3 for z/OS ASCII I/O
- Provide an _asciiopen_ and _asciiopen3_ pair of functions for opening files on z/OS. These services do a standard open and then, if the open is successful, update the CCSID of the file descriptor to 819 (ASCII) iff the oflag has ``O_CREAT`` set (e.g. a file is being created). We could consider printing out a warning if a file is untagged - right now this will _work correctly_ if the file in encoded as ASCII (CCSID 819) but will fail if the file is EBCDIC. - Provide a wrapper _Perl_mkstemp_cloexec_ which not only creates a temporary file using mkstemp but will also tag the file as CCSID 819. The tagging is only performed if ``__CHARSET_LIB == 1``, i.e. the code is compiled with -qascii. - Define _PerlIO_open_ and _PerlLIO_open3_ as _asciiopen_ and _asciiopen3_ respectively, when the code is built for ASCII ``#if (__CHARSET_LIB == 1)`` on z/OS ``#if defined(OEMVS)``.
-rw-r--r--doio.c80
-rw-r--r--iperlsys.h18
2 files changed, 95 insertions, 3 deletions
diff --git a/doio.c b/doio.c
index 9233b9a1e1..92a9d04da4 100644
--- a/doio.c
+++ b/doio.c
@@ -218,6 +218,57 @@ Perl_PerlLIO_dup2_cloexec(pTHX_ int oldfd, int newfd)
#endif
}
+#if defined(OEMVS)
+ #if (__CHARSET_LIB == 1)
+# include <stdio.h>
+# include <stdlib.h>
+
+ static int setccsid(int fd, int ccsid)
+ {
+ attrib_t attr;
+ int rc;
+
+ memset(&attr, 0, sizeof(attr));
+ attr.att_filetagchg = 1;
+ attr.att_filetag.ft_ccsid = ccsid;
+ attr.att_filetag.ft_txtflag = 1;
+
+ rc = __fchattr(fd, &attr, sizeof(attr));
+ return rc;
+ }
+
+ static void updateccsid(int fd, const char* path, int oflag, int perm)
+ {
+ int rc;
+ if (oflag & O_CREAT) {
+ rc = setccsid(fd, 819);
+ }
+ }
+
+ int asciiopen(const char* path, int oflag)
+ {
+ int rc;
+ int fd = open(path, oflag);
+ if (fd == -1) {
+ return fd;
+ }
+ updateccsid(fd, path, oflag, -1);
+ return fd;
+ }
+
+ int asciiopen3(const char* path, int oflag, int perm)
+ {
+ int rc;
+ int fd = open(path, oflag, perm);
+ if (fd == -1) {
+ return fd;
+ }
+ updateccsid(fd, path, oflag, perm);
+ return fd;
+ }
+ #endif
+#endif
+
int
Perl_PerlLIO_open_cloexec(pTHX_ const char *file, int flag)
{
@@ -246,8 +297,34 @@ Perl_PerlLIO_open3_cloexec(pTHX_ const char *file, int flag, int perm)
#endif
}
+#if defined(OEMVS)
+ #if (__CHARSET_LIB == 1)
+ #define TEMP_CCSID 819
+ #endif
+static int Internal_Perl_my_mkstemp_cloexec(char *templte)
+{
+ PERL_ARGS_ASSERT_MY_MKSTEMP_CLOEXEC;
+#if defined(O_CLOEXEC)
+ DO_ONEOPEN_EXPERIMENTING_CLOEXEC(
+ PL_strategy_mkstemp,
+ Perl_my_mkostemp(templte, O_CLOEXEC),
+ Perl_my_mkstemp(templte));
+#else
+ DO_ONEOPEN_THEN_CLOEXEC(Perl_my_mkstemp(templte));
+#endif
+}
int
-Perl_my_mkstemp_cloexec(char *templte)
+Perl_my_mkstemp_cloexec(char *templte)
+{
+ int tempfd = Internal_Perl_my_mkstemp_cloexec(templte);
+#if defined(TEMP_CCSID)
+ setccsid(tempfd, TEMP_CCSID);
+#endif
+ return tempfd;
+}
+
+#else /* OEMVS */
+Perl_my_mkstemp_cloexec(char *templte)
{
PERL_ARGS_ASSERT_MY_MKSTEMP_CLOEXEC;
#if defined(O_CLOEXEC)
@@ -259,6 +336,7 @@ Perl_my_mkstemp_cloexec(char *templte)
DO_ONEOPEN_THEN_CLOEXEC(Perl_my_mkstemp(templte));
#endif
}
+#endif
int
Perl_my_mkostemp_cloexec(char *templte, int flags)
diff --git a/iperlsys.h b/iperlsys.h
index edf9d50c44..b27764555c 100644
--- a/iperlsys.h
+++ b/iperlsys.h
@@ -49,6 +49,7 @@
*/
#include "perlio.h"
+
typedef Signal_t (*Sighandler1_t) (int);
typedef Signal_t (*Sighandler3_t) (int, Siginfo_t*, void*);
@@ -776,8 +777,21 @@ struct IPerlLIOInfo
# define PerlLIO_lstat(name, buf) PerlLIO_stat((name), (buf))
#endif
#define PerlLIO_mktemp(file) mktemp((file))
-#define PerlLIO_open(file, flag) open((file), (flag))
-#define PerlLIO_open3(file, flag, perm) open((file), (flag), (perm))
+#if defined(OEMVS)
+ #if (__CHARSET_LIB == 1)
+ int asciiopen(const char* path, int oflag);
+ int asciiopen3(const char* path, int oflag, int perm);
+
+ #define PerlLIO_open(file, flag) asciiopen((file), (flag))
+ #define PerlLIO_open3(file, flag, perm) asciiopen3((file), (flag), (perm))
+ #else
+ #define PerlLIO_open(file, flag) open((file), (flag))
+ #define PerlLIO_open3(file, flag, perm) open((file), (flag), (perm))
+ #endif
+#else
+# define PerlLIO_open(file, flag) open((file), (flag))
+# define PerlLIO_open3(file, flag, perm) open((file), (flag), (perm))
+#endif
#define PerlLIO_read(fd, buf, count) read((fd), (buf), (count))
#define PerlLIO_rename(old, new) rename((old), (new))
#define PerlLIO_setmode(fd, mode) setmode((fd), (mode))