|
|
f6ea51 |
From 3dfcac940930a8aa6779f5debea6ea6357372419 Mon Sep 17 00:00:00 2001
|
|
|
f6ea51 |
From: Daniel Dragan <bulk88@hotmail.com>
|
|
|
f6ea51 |
Date: Sun, 16 Aug 2015 04:30:23 -0400
|
|
|
f6ea51 |
Subject: [PATCH] fix do dir returning no $!
|
|
|
f6ea51 |
MIME-Version: 1.0
|
|
|
f6ea51 |
Content-Type: text/plain; charset=UTF-8
|
|
|
f6ea51 |
Content-Transfer-Encoding: 8bit
|
|
|
f6ea51 |
|
|
|
f6ea51 |
do()ing a directory was returning false/empty string in $!, which isn't
|
|
|
f6ea51 |
an error, yet documentation says $! should have the error code in it.
|
|
|
f6ea51 |
Fix this by returning EISDIR for dirs, and EINVAL for block devices.
|
|
|
f6ea51 |
[perl #125774]
|
|
|
f6ea51 |
|
|
|
f6ea51 |
Remove "errno = 0" and comment added in b2da7ead68, since now there is no
|
|
|
f6ea51 |
scenario where errno is uninitialized, since the dir and block device
|
|
|
f6ea51 |
failure branches now set errno, where previously they didn't.
|
|
|
f6ea51 |
|
|
|
f6ea51 |
Petr Písař: Ported to 5.26.1.
|
|
|
f6ea51 |
|
|
|
f6ea51 |
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
|
|
f6ea51 |
---
|
|
|
f6ea51 |
pp_ctl.c | 25 +++++++++++++++++--------
|
|
|
f6ea51 |
t/op/do.t | 14 +++++++++++++-
|
|
|
f6ea51 |
2 files changed, 30 insertions(+), 9 deletions(-)
|
|
|
f6ea51 |
|
|
|
f6ea51 |
diff --git a/pp_ctl.c b/pp_ctl.c
|
|
|
f6ea51 |
index e24d7b6..f136f91 100644
|
|
|
f6ea51 |
--- a/pp_ctl.c
|
|
|
f6ea51 |
+++ b/pp_ctl.c
|
|
|
f6ea51 |
@@ -3534,15 +3534,22 @@ S_check_type_and_open(pTHX_ SV *name)
|
|
|
f6ea51 |
errno EACCES, so only do a stat to separate a dir from a real EACCES
|
|
|
f6ea51 |
caused by user perms */
|
|
|
f6ea51 |
#ifndef WIN32
|
|
|
f6ea51 |
- /* we use the value of errno later to see how stat() or open() failed.
|
|
|
f6ea51 |
- * We don't want it set if the stat succeeded but we still failed,
|
|
|
f6ea51 |
- * such as if the name exists, but is a directory */
|
|
|
f6ea51 |
- errno = 0;
|
|
|
f6ea51 |
-
|
|
|
f6ea51 |
st_rc = PerlLIO_stat(p, &st);
|
|
|
f6ea51 |
|
|
|
f6ea51 |
- if (st_rc < 0 || S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode)) {
|
|
|
f6ea51 |
+ if (st_rc < 0)
|
|
|
f6ea51 |
return NULL;
|
|
|
f6ea51 |
+ else {
|
|
|
f6ea51 |
+ int eno;
|
|
|
f6ea51 |
+ if(S_ISBLK(st.st_mode)) {
|
|
|
f6ea51 |
+ eno = EINVAL;
|
|
|
f6ea51 |
+ goto not_file;
|
|
|
f6ea51 |
+ }
|
|
|
f6ea51 |
+ else if(S_ISDIR(st.st_mode)) {
|
|
|
f6ea51 |
+ eno = EISDIR;
|
|
|
f6ea51 |
+ not_file:
|
|
|
f6ea51 |
+ errno = eno;
|
|
|
f6ea51 |
+ return NULL;
|
|
|
f6ea51 |
+ }
|
|
|
f6ea51 |
}
|
|
|
f6ea51 |
#endif
|
|
|
f6ea51 |
|
|
|
f6ea51 |
@@ -3554,8 +3561,10 @@ S_check_type_and_open(pTHX_ SV *name)
|
|
|
f6ea51 |
int eno;
|
|
|
f6ea51 |
st_rc = PerlLIO_stat(p, &st);
|
|
|
f6ea51 |
if (st_rc >= 0) {
|
|
|
f6ea51 |
- if(S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode))
|
|
|
f6ea51 |
- eno = 0;
|
|
|
f6ea51 |
+ if(S_ISDIR(st.st_mode))
|
|
|
f6ea51 |
+ eno = EISDIR;
|
|
|
f6ea51 |
+ else if(S_ISBLK(st.st_mode))
|
|
|
f6ea51 |
+ eno = EINVAL;
|
|
|
f6ea51 |
else
|
|
|
f6ea51 |
eno = EACCES;
|
|
|
f6ea51 |
errno = eno;
|
|
|
f6ea51 |
diff --git a/t/op/do.t b/t/op/do.t
|
|
|
f6ea51 |
index 78d8800..1c54f0b 100644
|
|
|
f6ea51 |
--- a/t/op/do.t
|
|
|
f6ea51 |
+++ b/t/op/do.t
|
|
|
f6ea51 |
@@ -7,6 +7,7 @@ BEGIN {
|
|
|
f6ea51 |
}
|
|
|
f6ea51 |
use strict;
|
|
|
f6ea51 |
no warnings 'void';
|
|
|
f6ea51 |
+use Errno qw(ENOENT EISDIR);
|
|
|
f6ea51 |
|
|
|
f6ea51 |
my $called;
|
|
|
f6ea51 |
my $result = do{ ++$called; 'value';};
|
|
|
f6ea51 |
@@ -247,7 +248,7 @@ SKIP: {
|
|
|
f6ea51 |
my $saved_errno = $!;
|
|
|
f6ea51 |
ok(!$rv, "do returns false on io errror");
|
|
|
f6ea51 |
ok(!$saved_error, "\$\@ not set on io error");
|
|
|
f6ea51 |
- ok($saved_errno, "\$! set on io error");
|
|
|
f6ea51 |
+ ok($saved_errno == ENOENT, "\$! is ENOENT for nonexistent file");
|
|
|
f6ea51 |
}
|
|
|
f6ea51 |
|
|
|
f6ea51 |
# do subname should not be do "subname"
|
|
|
f6ea51 |
@@ -305,4 +306,15 @@ SKIP: {
|
|
|
f6ea51 |
}
|
|
|
f6ea51 |
|
|
|
f6ea51 |
|
|
|
f6ea51 |
+# do file $!s must be correct
|
|
|
f6ea51 |
+{
|
|
|
f6ea51 |
+ local @INC = ('.'); #want EISDIR not ENOENT
|
|
|
f6ea51 |
+ my $rv = do 'op'; # /t/op dir
|
|
|
f6ea51 |
+ my $saved_error = $@;
|
|
|
f6ea51 |
+ my $saved_errno = $!+0;
|
|
|
f6ea51 |
+ ok(!$rv, "do dir returns false");
|
|
|
f6ea51 |
+ ok(!$saved_error, "\$\@ is false on do dir");
|
|
|
f6ea51 |
+ ok($saved_errno == EISDIR, "\$! is EISDIR on do dir");
|
|
|
f6ea51 |
+}
|
|
|
f6ea51 |
+
|
|
|
f6ea51 |
done_testing();
|
|
|
f6ea51 |
--
|
|
|
f6ea51 |
2.13.6
|
|
|
f6ea51 |
|