summaryrefslogtreecommitdiff
path: root/doio.c
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2014-03-02 08:14:13 +0100
committerNicholas Clark <nick@ccl4.org>2014-03-19 10:57:53 +0100
commita6fc70e55b0240c99a09f1d7185e5c59ffd57206 (patch)
tree6bd60b47014920e973d0438f4b24854a4a229ee0 /doio.c
parenta2b41d5ca668b3be2860093f464392277e1d0034 (diff)
downloadperl-a6fc70e55b0240c99a09f1d7185e5c59ffd57206.tar.gz
Extract the cleanup code of Perl_do_openn() into S_openn_cleanup().
A 12 parameter function is extremely ugly (as demonstrated by the need to add macros for it to perl.h), but it's private, and it will permit the two-headed public interface of Perl_do_openn() to be simplified.
Diffstat (limited to 'doio.c')
-rw-r--r--doio.c28
1 files changed, 26 insertions, 2 deletions
diff --git a/doio.c b/doio.c
index 49f1e1683a..85b3a2de90 100644
--- a/doio.c
+++ b/doio.c
@@ -136,7 +136,6 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw,
IO * const io = openn_setup(gv, mode, &saveifp, &saveofp, &savefd, &savetype);
int writing = 0;
PerlIO *fp;
- int fd;
bool was_fdopen = FALSE;
char *type = NULL;
@@ -234,13 +233,16 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw,
Perl_warner(aTHX_ packWARN(WARN_IO),
"Can't open a reference");
SETERRNO(EINVAL, LIB_INVARG);
+ fp = NULL;
goto say_false;
}
#endif /* USE_STDIO */
p = (SvOK(*svp) || SvGMAGICAL(*svp)) ? SvPV(*svp, nlen) : NULL;
- if (p && !IS_SAFE_PATHNAME(p, nlen, "open"))
+ if (p && !IS_SAFE_PATHNAME(p, nlen, "open")) {
+ fp = NULL;
goto say_false;
+ }
name = p ? savepvn(p, nlen) : savepvs("");
@@ -279,6 +281,7 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw,
if (ckWARN(WARN_PIPE))
Perl_warner(aTHX_ packWARN(WARN_PIPE), "Missing command in piped open");
errno = EPIPE;
+ fp = NULL;
goto say_false;
}
if (!(*name == '-' && name[1] == '\0') || num_svs)
@@ -304,6 +307,7 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw,
if (num_svs) {
if (*type) {
if (PerlIO_apply_layers(aTHX_ fp, mode, type) != 0) {
+ fp = NULL;
goto say_false;
}
}
@@ -371,6 +375,7 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw,
#ifdef EINVAL
SETERRNO(EINVAL,SS_IVCHAN);
#endif
+ fp = NULL;
goto say_false;
}
if ((that_fp = IoIFP(thatio))) {
@@ -497,6 +502,7 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw,
if (ckWARN(WARN_PIPE))
Perl_warner(aTHX_ packWARN(WARN_PIPE), "Missing command in piped open");
errno = EPIPE;
+ fp = NULL;
goto say_false;
}
if (!(*name == '-' && name[1] == '\0') || num_svs)
@@ -521,6 +527,7 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw,
type++;
if (*type) {
if (PerlIO_apply_layers(aTHX_ fp, mode, type) != 0) {
+ fp = NULL;
goto say_false;
}
}
@@ -556,6 +563,23 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw,
}
}
}
+
+ say_false:
+ return openn_cleanup(gv, io, fp, mode, oname, saveifp, saveofp, savefd,
+ savetype, writing, was_fdopen, type);
+}
+
+/* Yes, this is ugly, but it's private, and I don't see a cleaner way to
+ simplify the two-headed public interface of do_openn. */
+static bool
+S_openn_cleanup(pTHX_ GV *gv, IO *io, PerlIO *fp, char *mode, const char *oname,
+ PerlIO *saveifp, PerlIO *saveofp, int savefd, char savetype,
+ int writing, bool was_fdopen, const char *type)
+{
+ int fd;
+
+ PERL_ARGS_ASSERT_OPENN_CLEANUP;
+
if (!fp) {
if (IoTYPE(io) == IoTYPE_RDONLY && ckWARN(WARN_NEWLINE)
&& strchr(oname, '\n')