summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pp.h27
-rw-r--r--pp_sys.c42
2 files changed, 54 insertions, 15 deletions
diff --git a/pp.h b/pp.h
index 5c25b5513b..a0714e9550 100644
--- a/pp.h
+++ b/pp.h
@@ -471,19 +471,20 @@ Does not use C<TARG>. See also C<XPUSHu>, C<mPUSHu> and C<PUSHu>.
#define tryAMAGICunDEREF_var(meth_enum) \
tryAMAGICunW_var(meth_enum,setAGAIN,0,(void)0)
-#define tryAMAGICftest(chr) \
- STMT_START { \
- if (SvAMAGIC(TOPs)) { \
- SV * const tmpsv = amagic_call(TOPs, \
- newSVpvn_flags(&chr, 1, SVs_TEMP), \
- ftest_amg, 0); \
- \
- if (tmpsv) { \
- SPAGAIN; \
- SETs(tmpsv); \
- RETURN; \
- } \
- } \
+#define tryAMAGICftest(chr) \
+ STMT_START { \
+ if (SvAMAGIC(TOPs)) { \
+ const char tmpchr = (chr); \
+ SV * const tmpsv = amagic_call(TOPs, \
+ newSVpvn_flags(&tmpchr, 1, SVs_TEMP), \
+ ftest_amg, 0); \
+ \
+ if (tmpsv) { \
+ SPAGAIN; \
+ SETs(tmpsv); \
+ RETURN; \
+ } \
+ } \
} STMT_END
diff --git a/pp_sys.c b/pp_sys.c
index 1945b13d9e..374e5c12c8 100644
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -2983,7 +2983,7 @@ PP(pp_ftrread)
int stat_mode = S_IRUSR;
bool effective = FALSE;
- char opchar;
+ char opchar = '?';
dSP;
STACKED_FTEST_CHECK;
@@ -3090,8 +3090,19 @@ PP(pp_ftis)
dVAR;
I32 result;
const int op_type = PL_op->op_type;
+ char opchar = '?';
dSP;
STACKED_FTEST_CHECK;
+
+ switch (op_type) {
+ case OP_FTIS: opchar = 'e'; break;
+ case OP_FTSIZE: opchar = 's'; break;
+ case OP_FTMTIME: opchar = 'M'; break;
+ case OP_FTCTIME: opchar = 'C'; break;
+ case OP_FTATIME: opchar = 'A'; break;
+ }
+ tryAMAGICftest(opchar);
+
result = my_stat();
SPAGAIN;
if (result < 0)
@@ -3128,10 +3139,12 @@ PP(pp_ftrowned)
{
dVAR;
I32 result;
+ char opchar = '?';
dSP;
/* I believe that all these three are likely to be defined on most every
system these days. */
+ if (!SvAMAGIC(TOPs)) {
#ifndef S_ISUID
if(PL_op->op_type == OP_FTSUID)
RETPUSHNO;
@@ -3144,8 +3157,26 @@ PP(pp_ftrowned)
if(PL_op->op_type == OP_FTSVTX)
RETPUSHNO;
#endif
+ }
STACKED_FTEST_CHECK;
+
+ switch (PL_op->op_type) {
+ case OP_FTROWNED: opchar = 'O'; break;
+ case OP_FTEOWNED: opchar = 'o'; break;
+ case OP_FTZERO: opchar = 'z'; break;
+ case OP_FTSOCK: opchar = 'S'; break;
+ case OP_FTCHR: opchar = 'c'; break;
+ case OP_FTBLK: opchar = 'b'; break;
+ case OP_FTFILE: opchar = 'f'; break;
+ case OP_FTDIR: opchar = 'd'; break;
+ case OP_FTPIPE: opchar = 'p'; break;
+ case OP_FTSUID: opchar = 'u'; break;
+ case OP_FTSGID: opchar = 'g'; break;
+ case OP_FTSVTX: opchar = 'k'; break;
+ }
+ tryAMAGICftest(opchar);
+
result = my_stat();
SPAGAIN;
if (result < 0)
@@ -3212,8 +3243,11 @@ PP(pp_ftrowned)
PP(pp_ftlink)
{
dVAR;
- I32 result = my_lstat();
+ I32 result;
dSP;
+
+ tryAMAGICftest('l');
+ result = my_lstat();
if (result < 0)
RETPUSHUNDEF;
if (S_ISLNK(PL_statcache.st_mode))
@@ -3231,6 +3265,8 @@ PP(pp_fttty)
STACKED_FTEST_CHECK;
+ tryAMAGICftest('t');
+
if (PL_op->op_flags & OPf_REF)
gv = cGVOP_gv;
else if (isGV(TOPs))
@@ -3280,6 +3316,8 @@ PP(pp_fttext)
STACKED_FTEST_CHECK;
+ tryAMAGICftest(PL_op->op_type == OP_FTTEXT ? 'T' : 'B');
+
if (PL_op->op_flags & OPf_REF)
gv = cGVOP_gv;
else if (isGV(TOPs))