summaryrefslogtreecommitdiff
path: root/pp_ctl.c
diff options
context:
space:
mode:
authorDaniel Dragan <bulk88@hotmail.com>2015-01-08 00:10:13 -0500
committerTony Cook <tony@develop-help.com>2015-01-12 10:06:45 +1100
commitd345f4877521ed3ad5ad337f7e87a95625df05c0 (patch)
treec98631660cd22af4416b1ff2c948d2692209a17c /pp_ctl.c
parent020d3472f2f73e041f3a99c9639a52f24c2022ed (diff)
downloadperl-d345f4877521ed3ad5ad337f7e87a95625df05c0.tar.gz
Win32: stat() only after a failed open() on a module
See RT ticket for this patch for details.
Diffstat (limited to 'pp_ctl.c')
-rw-r--r--pp_ctl.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index f2c9856cff..d69710ca18 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -3578,6 +3578,7 @@ S_check_type_and_open(pTHX_ SV *name)
{
Stat_t st;
STRLEN len;
+ PerlIO * retio;
const char *p = SvPV_const(name, len);
int st_rc;
@@ -3592,6 +3593,11 @@ S_check_type_and_open(pTHX_ SV *name)
if (!IS_SAFE_PATHNAME(p, len, "require"))
return NULL;
+ /* on Win32 stat is expensive (it does an open() and close() twice and
+ a couple other IO calls), the open will fail with a dir on its own with
+ errno EACCES, so only do a stat to separate a dir from a real EACCES
+ caused by user perms */
+#ifndef WIN32
/* we use the value of errno later to see how stat() or open() failed.
* We don't want it set if the stat succeeded but we still failed,
* such as if the name exists, but is a directory */
@@ -3602,12 +3608,29 @@ S_check_type_and_open(pTHX_ SV *name)
if (st_rc < 0 || S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode)) {
return NULL;
}
+#endif
#if !defined(PERLIO_IS_STDIO)
- return PerlIO_openn(aTHX_ ":", PERL_SCRIPT_MODE, -1, 0, 0, NULL, 1, &name);
+ retio = PerlIO_openn(aTHX_ ":", PERL_SCRIPT_MODE, -1, 0, 0, NULL, 1, &name);
#else
- return PerlIO_open(p, PERL_SCRIPT_MODE);
+ retio = PerlIO_open(p, PERL_SCRIPT_MODE);
+#endif
+#ifdef WIN32
+ /* EACCES stops the INC search early in pp_require to implement
+ feature RT #113422 */
+ if(!retio && errno == EACCES) { /* exists but probably a directory */
+ int eno;
+ st_rc = PerlLIO_stat(p, &st);
+ if (st_rc >= 0) {
+ if(S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode))
+ eno = 0;
+ else
+ eno = EACCES;
+ errno = eno;
+ }
+ }
#endif
+ return retio;
}
#ifndef PERL_DISABLE_PMC