File Coverage

FileCheck.xs
Criterion Covered Total %
statement 199 211 94.3
branch 180 432 41.6
condition n/a
subroutine n/a
pod n/a
total 379 643 58.9


line stmt bran cond sub pod time code
1             /*
2             *
3             * Copyright (c) 2018, cPanel, LLC.
4             * All rights reserved.
5             * http://cpanel.net
6             *
7             * This is free software; you can redistribute it and/or modify it under the
8             * same terms as Perl itself.
9             *
10             */
11              
12             #include
13             #include
14             #include
15             #include
16              
17             #include "FileCheck.h"
18              
19             /*
20             * Macro to make the moking process easier
21             * for now keep them there, so we can hack them in the same file
22             */
23              
24             /* generic macro with args */
25             #define _CALL_REAL_PP(zOP) (* ( gl_overload_ft->op[zOP].real_pp ) )(aTHX)
26             #define _RETURN_CALL_REAL_PP_IF_UNMOCK(zOP) if (!gl_overload_ft->op[zOP].is_mocked) return _CALL_REAL_PP(zOP);
27              
28             /* simplified versions for our custom usage */
29             #define CALL_REAL_OP() _CALL_REAL_PP(PL_op->op_type)
30             #define RETURN_CALL_REAL_OP_IF_UNMOCK() _RETURN_CALL_REAL_PP_IF_UNMOCK(PL_op->op_type)
31              
32             #define INIT_FILECHECK_MOCK(op_name, op_type, f) \
33             newCONSTSUB(stash, op_name, newSViv(op_type) ); \
34             gl_overload_ft->op[op_type].real_pp = PL_ppaddr[op_type]; \
35             PL_ppaddr[op_type] = f;
36              
37             /* TODO: need to improve for Perl <= 5.014 */
38             #define RETURN_CALL_REAL_OP_IF_CALL_WITH_DEFGV() STMT_START { \
39             if (gl_overload_ft->op[OP_STAT].is_mocked) { \
40             SV *arg = *PL_stack_sp; GV *gv; \
41             if ( SvTYPE(arg) == SVt_PVAV ) arg = arg + AvMAX( arg ); \
42             /* GV *gv = MAYBE_DEREF_GV(arg); */ \
43             if ( PL_op->op_flags & OPf_REF ) \
44             gv = cGVOP_gv; \
45             else { \
46             gv = MAYBE_DEREF_GV(arg); \
47             } \
48             /* printf ("### XXX ---> arg %d %p vs GV %p vs defgv %p \n", SvFLAGS(arg), *PL_stack_sp, gv, PL_defgv ); */ \
49             /* get the GV from the arg if it s not a GV */ \
50             if ( SvTYPE(arg) == SVt_NULL || gv == PL_defgv ) { \
51             return CALL_REAL_OP(); \
52             } \
53             } \
54             } STMT_END
55              
56             /* a Stat_t struct has 13 elements */
57             #define STAT_T_MAX 13
58              
59             /* ----------- start there --------------- */
60              
61             OverloadFTOps *gl_overload_ft = 0;
62              
63             /*
64             * common helper to callback the pure perl function Overload::FileCheck::_check
65             * and get the mocked value for the -X check
66             *
67             * 1 check is true -> OP returns Yes
68             * 0 check is false -> OP returns No
69             * TODO: -> OP returns undef
70             * -1 fallback to the original OP
71             */
72 780           int _overload_ft_ops() {
73 780           SV *const arg = *PL_stack_sp;
74 780           int optype = PL_op->op_type; /* this is the current op_type we are mocking */
75 780           int check_status = -1; /* 1 -> YES ; 0 -> FALSE ; -1 -> delegate */
76             int count;
77              
78 780           dSP;
79              
80 780           ENTER;
81 780           SAVETMPS;
82              
83 780 50         PUSHMARK(SP);
84 780 50         EXTEND(SP, 2);
85 780           PUSHs(sv_2mortal(newSViv(optype)));
86 780           PUSHs(arg);
87              
88 780           PUTBACK;
89              
90 780           count = call_pv("Overload::FileCheck::_check", G_SCALAR);
91              
92 780           SPAGAIN;
93              
94 780 50         if (count != 1)
95 0           croak("No return value from Overload::FileCheck::_check for OP #%d\n", optype);
96              
97 780 100         check_status = POPi; /* TOOO pop on SV* for true / false & co */
98              
99             /* printf ("######## The result is %d /// OPTYPE is %d\n", check_status, optype); */
100              
101 780           PUTBACK;
102 780 50         FREETMPS;
103 780           LEAVE;
104              
105 780           return check_status;
106             }
107              
108 68           SV* _overload_ft_ops_sv() {
109 68           SV *const arg = *PL_stack_sp;
110 68           int optype = PL_op->op_type; /* this is the current op_type we are mocking */
111             SV *status; /* 1 -> YES ; 0 -> FALSE ; -1 -> delegate */
112              
113 68           dSP;
114             int count;
115              
116 68           ENTER;
117 68           SAVETMPS;
118              
119 68 50         PUSHMARK(SP);
120 68 50         EXTEND(SP, 2);
121 68           PUSHs(sv_2mortal(newSViv(optype)));
122 68           PUSHs(arg);
123              
124 68           PUTBACK;
125              
126 68           count = call_pv("Overload::FileCheck::_check", G_SCALAR);
127              
128 68           SPAGAIN;
129              
130 68 50         if (count != 1)
131 0           croak("No return value from Overload::FileCheck::_check for OP #%d\n", optype);
132              
133 68           status = POPs;
134 68           SvREFCNT_inc( status );
135              
136             /* printf ("######## The result is %d /// OPTYPE is %d\n", check_status, optype); */
137              
138 68           PUTBACK;
139 68 50         FREETMPS;
140 68           LEAVE;
141              
142 68           return status;
143             }
144              
145             /*
146             * view perldoc to call SVs, method, ...
147             *
148             * https://perldoc.perl.org/perlcall.html
149             *
150             * but also https://perldoc.perl.org/perlguts.html
151             */
152              
153             #define set_stat_from_aryix(st, ix) \
154             rsv = ary[ix]; \
155             if (SvROK(rsv)) croak("Overload::FileCheck - Item %d should not be one RV\n", ix); \
156             if (SvIOK(rsv)) st = SvIV( rsv ); \
157             else if (SvUOK(rsv)) st = SvUV( rsv ); \
158             else if (SvNOK(rsv)) st = SvNV( rsv ); \
159             else croak("Overload::FileCheck - Item %d is not numeric...\n", ix);
160              
161              
162             /*
163             * similar to _overload_ft_ops but expect more args from _check
164             * which returns values for a fake stat
165             *
166             * Note: we could also call a dedicated function as _check_stat
167             */
168 359           int _overload_ft_stat(Stat_t *stat, int *size) {
169 359           SV *const arg = *PL_stack_sp;
170 359           int optype = PL_op->op_type; /* this is the current op_type we are mocking */
171 359           int check_status = -1; /* 1 -> YES ; 0 -> FALSE ; -1 -> delegate */
172              
173 359           dSP;
174             int count;
175             SV *sv;
176              
177 359           ENTER;
178 359           SAVETMPS;
179              
180 359 50         PUSHMARK(SP);
181 359 50         EXTEND(SP, 2);
182 359           PUSHs(sv_2mortal(newSViv(optype)));
183 359           PUSHs(arg);
184 359           PUTBACK;
185              
186 359           count = call_pv("Overload::FileCheck::_check", G_ARRAY);
187              
188 351           SPAGAIN;
189              
190 351 50         if (count < 1)
191 0           croak("Overload::FileCheck::_check for stat OP #%d should return at least one SV.\n", optype);
192 351 50         if (count > 2)
193 0           croak("Overload::FileCheck::_check for stat OP #%d should return no more than two SVs.\n", optype);
194              
195             /* popping the stack from last entry to first */
196 351 100         if (count == 2) sv = POPs; /* RvAV */
197 351 50         check_status = POPi; /* TOOO pop on SV* for true / false & co */
198              
199 351           *size = -1; /* by default it fails */
200              
201 351 100         if ( check_status == 1 ) {
202             AV *stat_array;
203             SV **ary;
204             SV *rsv;
205             int av_size;
206              
207 348 50         if (count != 2)
208 0           croak("Overload::FileCheck::_check for stat OP #%d should return two SVs on success.\n", optype);
209              
210 348 50         if ( ! SvROK(sv) )
211 0           croak( "Overload::FileCheck::_check need to return an array ref" );
212              
213 348           stat_array = MUTABLE_AV( SvRV( sv ) );
214 348 50         if ( SvTYPE(stat_array) != SVt_PVAV )
215 0           croak( "Overload::FileCheck::_check need to return an array ref" );
216              
217 348 50         av_size = AvFILL(stat_array);
218 348 100         if ( av_size > 0 && av_size != ( STAT_T_MAX - 1 ) )
    50          
219 0           croak( "Overload::FileCheck::_check: Array should contain 13 elements" );
220              
221 348           *size = av_size; /* store the av_size */
222 348 100         if ( av_size > 0 ) {
223              
224 340           ary = AvARRAY(stat_array);
225              
226             /* fill the stat struct */
227 340 50         set_stat_from_aryix( stat->st_dev, 0 ); /* IV */
    100          
    50          
    50          
    0          
    50          
    0          
228 336 50         set_stat_from_aryix( stat->st_ino, 1 ); /* IV or UV : neg = PL_statcache.st_ino < 0 */
    50          
    50          
    0          
    0          
    0          
    0          
229 336 50         set_stat_from_aryix( stat->st_mode, 2 ); /* UV */
    50          
    50          
    0          
    0          
    0          
    0          
230 336 50         set_stat_from_aryix( stat->st_nlink, 3 ); /* UV */
    50          
    50          
    0          
    0          
    0          
    0          
231 336 50         set_stat_from_aryix( stat->st_uid, 4 ); /* IV ? */
    50          
    50          
    0          
    0          
    0          
    0          
232 336 50         set_stat_from_aryix( stat->st_gid, 5 ); /* IV ? */
    50          
    50          
    0          
    0          
    0          
    0          
233 336 50         set_stat_from_aryix( stat->st_rdev, 6 ); /* IV or PV */
    50          
    50          
    0          
    0          
    0          
    0          
234 336 50         set_stat_from_aryix( stat->st_size, 7 ); /* NV or IV */
    50          
    50          
    0          
    0          
    0          
    0          
235 336 50         set_stat_from_aryix( stat->st_atime, 8 ); /* NV or IV */
    50          
    50          
    0          
    0          
    0          
    0          
236 336 50         set_stat_from_aryix( stat->st_mtime, 9 ); /* NV or IV */
    50          
    50          
    0          
    0          
    0          
    0          
237 336 50         set_stat_from_aryix( stat->st_ctime, 10 ); /* NV or IV */
    50          
    50          
    0          
    0          
    0          
    0          
238 336 50         set_stat_from_aryix( stat->st_blksize, 11 ); /* UV or PV */
    50          
    50          
    0          
    0          
    0          
    0          
239 336 50         set_stat_from_aryix( stat->st_blocks, 12 ); /* UV or PV */
    100          
    50          
    50          
    0          
    50          
    0          
240             }
241              
242             }
243              
244 345           PUTBACK;
245 345 50         FREETMPS;
246 345           LEAVE;
247              
248 345           return check_status;
249             }
250              
251              
252             /* a generic OP to overload the FT OPs returning yes or no */
253             /* FIXME also need to handle undef */
254 1556           PP(pp_overload_ft_yes_no) {
255             int check_status;
256              
257             assert( gl_overload_ft );
258              
259             /* not currently mocked */
260 1556 100         RETURN_CALL_REAL_OP_IF_UNMOCK();
261 775 100         RETURN_CALL_REAL_OP_IF_CALL_WITH_DEFGV();
    50          
    100          
    50          
    0          
    50          
    0          
    0          
    100          
    50          
    50          
    0          
    50          
    50          
    0          
    50          
    100          
    100          
262              
263 742           check_status = _overload_ft_ops();
264              
265             {
266             FT_SETUP_dSP_IF_NEEDED;
267              
268 742 100         if ( check_status == 1 ) FT_RETURNYES;
269 334 100         if ( check_status == 0 ) FT_RETURNUNDEF;
270             /* if ( check_status == -1 ) FT_RETURNUNDEF; */ /* TODO */
271             }
272              
273             /* fallback */
274 134           return CALL_REAL_OP();
275             }
276              
277 75           PP(pp_overload_ft_int) {
278             int check_status;
279              
280             assert( gl_overload_ft );
281              
282             /* not currently mocked */
283 75 100         RETURN_CALL_REAL_OP_IF_UNMOCK();
284 44 100         RETURN_CALL_REAL_OP_IF_CALL_WITH_DEFGV();
    100          
    100          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    100          
    100          
285              
286 38           check_status = _overload_ft_ops();
287              
288             /* SETERRNO(EEXIST,RMS_FEX); */ /* TODO */
289 38 100         if ( check_status == -1 )
290 8           return CALL_REAL_OP();
291              
292             {
293 30           dTARGET;
294             FT_SETUP_dSP_IF_NEEDED;
295              
296             /* TODO this is over simplistic some OPs can return one NV instead of IV */
297 30           sv_setiv(TARG, (IV) check_status);
298 30           FT_RETURN_TARG;
299             }
300             }
301              
302 143           PP(pp_overload_ft_nv) {
303             SV *status;
304              
305             assert( gl_overload_ft );
306              
307             /* not currently mocked */
308 143 100         RETURN_CALL_REAL_OP_IF_UNMOCK();
309 68 100         RETURN_CALL_REAL_OP_IF_CALL_WITH_DEFGV();
    50          
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
310              
311 68           status = _overload_ft_ops_sv();
312              
313 68 100         if ( SvIOK(status) && SvIV(status) == -1 )
    50          
    50          
314 0           return CALL_REAL_OP();
315              
316 68 100         if ( SvNOK(status) && SvNV(status) == -1 )
    50          
    100          
317 16           return CALL_REAL_OP();
318              
319             {
320 52           dTARGET;
321             FT_SETUP_dSP_IF_NEEDED;
322              
323 52 100         if ( SvNOK(status) )
324 40 50         sv_setnv(TARG, (NV) SvNV(status) );
325 12 50         else if ( SvIOK(status) )
326 12 50         sv_setiv(TARG, (IV) SvIV(status) );
327              
328 52           FT_RETURN_TARG;
329             }
330             }
331              
332 463           PP(pp_overload_stat) { /* stat & lstat */
333 463           Stat_t mocked_stat = { 0 }; /* fake stats */
334 463           int check_status = 0;
335             int size;
336              
337              
338             assert( gl_overload_ft );
339              
340             /* not currently mocked */
341 463 100         RETURN_CALL_REAL_OP_IF_UNMOCK();
342 365 50         RETURN_CALL_REAL_OP_IF_CALL_WITH_DEFGV();
    50          
    100          
    100          
    50          
    100          
    50          
    0          
    100          
    50          
    50          
    0          
    50          
    50          
    0          
    50          
    100          
    100          
343              
344             /* calling with our own tmp stat struct, instead of passing directly PL_statcache: more control */
345 359           check_status = _overload_ft_stat(&mocked_stat, &size);
346              
347             /* explicit ask for fallback */
348 345 100         if ( check_status == -1 )
349 3           return CALL_REAL_OP();
350              
351             /*
352             * The idea is too fool the stat function
353             * like if it was called by passing _ or *_
354             *
355             * We are setting these values as if stat was previously called
356             * - PL_laststype
357             * - PL_statcache
358             * - PL_laststatval
359             * - PL_statname
360             *
361             */
362              
363             {
364 342           dSP;
365              
366             /* drop & replace our stack first element with *_ */
367             /* Unexpected warning: Attempt to free unreferenced scalar: SV 0x119bd80. */
368             //SV *previous_stack = sv_2mortal(POPs); /* what do we want to do with this ? */
369 342           SV *previous_stack = POPs;
370              
371             /* copy the content of mocked_stat to PL_statcache */
372 342           memcpy(&PL_statcache, &mocked_stat, sizeof(PL_statcache));
373              
374 342 100         if ( size >= 0) { /* yes it succeeds */
375 334           PL_laststatval = 0;
376             } else { /* the stat call fails */
377 8           PL_laststatval = -1;
378             }
379              
380 342           PL_laststype = PL_op->op_type; /* this was for our OP */
381              
382             /* Here, we cut early when stat() returned no values
383             * In such a case, we set the statcache, but do not call
384             * the real op (CALL_REAL_OP)
385             */
386 342 100         if ( size < 0 )
387 8           RETURN;
388              
389 334           PUSHs( MUTABLE_SV( PL_defgv ) ); /* add *_ to the stack */
390              
391             /* probably not real necesseary, make warning messages nicer */
392 334 50         if ( previous_stack && SvPOK(previous_stack) )
    100          
393 331 100         sv_setpv(PL_statname, SvPV_nolen(previous_stack) );
394              
395 449           return CALL_REAL_OP();
396             }
397              
398             }
399              
400             /*
401             * extract from https://perldoc.perl.org/functions/-X.html
402             *
403             * -r File is readable by effective uid/gid.
404             * -w File is writable by effective uid/gid.
405             * -x File is executable by effective uid/gid.
406             * -o File is owned by effective uid.
407             * -R File is readable by real uid/gid.
408             * -W File is writable by real uid/gid.
409             * -X File is executable by real uid/gid.
410             * -O File is owned by real uid.
411             * -e File exists.
412             * -z File has zero size (is empty).
413             * -s File has nonzero size (returns size in bytes).
414             * -f File is a plain file.
415             * -d File is a directory.
416             * -l File is a symbolic link (false if symlinks aren't
417             * supported by the file system).
418             * -p File is a named pipe (FIFO), or Filehandle is a pipe.
419             * -S File is a socket.
420             * -b File is a block special file.
421             * -c File is a character special file.
422             * -t Filehandle is opened to a tty.
423             * -u File has setuid bit set.
424             * -g File has setgid bit set.
425             * -k File has sticky bit set.
426             * -T File is an ASCII or UTF-8 text file (heuristic guess).
427             * -B File is a "binary" file (opposite of -T).
428             * -M Script start time minus file modification time, in days.
429             * -A Same for access time.
430             * -C Same for inode change time
431             */
432              
433             MODULE = Overload__FileCheck PACKAGE = Overload::FileCheck
434              
435             SV*
436             mock_op(optype)
437             SV* optype;
438             ALIAS:
439             Overload::FileCheck::_xs_mock_op = 1
440             Overload::FileCheck::_xs_unmock_op = 2
441             CODE:
442             {
443             /* mylogger = INT2PTR(MyLogger*, SvIV(SvRV(self))); */
444 916           int opid = 0;
445              
446 916 50         if ( ! SvIOK(optype) )
447 0           croak("first argument to _xs_mock_op / _xs_unmock_op must be one integer");
448              
449 916 50         opid = SvIV( optype );
450 916 50         if ( !opid || opid < 0 || opid >= OP_MAX )
    50          
    50          
451 0           croak( "Invalid opid value %d", opid );
452              
453 916           switch (ix) {
454             case 1: /* _xs_mock_op */
455 616           gl_overload_ft->op[opid].is_mocked = 1;
456 616           break;
457             case 2: /* _xs_unmock_op */
458 300           gl_overload_ft->op[opid].is_mocked = 0;
459 300           break;
460             default:
461 0           croak("Unsupported function at index %d", ix);
462             XSRETURN_EMPTY;
463             }
464              
465 916           XSRETURN_EMPTY;
466             }
467             OUTPUT:
468             RETVAL
469              
470              
471             SV*
472             get_basetime()
473             CODE:
474 22           RETVAL = newSViv(PL_basetime);
475             OUTPUT:
476             RETVAL
477              
478              
479             BOOT:
480 48 50         if (!gl_overload_ft) {
481             HV *stash;
482             SV *sv;
483 48           int ix = 0;
484              
485 48           Newxz( gl_overload_ft, 1, OverloadFTOps);
486              
487 48           stash = gv_stashpvn("Overload::FileCheck", 19, TRUE);
488              
489 48           newCONSTSUB(stash, "_loaded", newSViv(1) );
490              
491             /* provide constants to standardize return values from mocked functions */
492 48           newCONSTSUB(stash, "CHECK_IS_TRUE", &PL_sv_yes ); /* could use newSViv(1) or &PL_sv_yes */
493 48           newCONSTSUB(stash, "CHECK_IS_FALSE", &PL_sv_no ); /* could use newSViv(0) or &PL_sv_no */
494 48           newCONSTSUB(stash, "CHECK_IS_NULL", &PL_sv_undef ); /* FIXME: need to handle this as a valid answer */
495 48           newCONSTSUB(stash, "FALLBACK_TO_REAL_OP", newSVnv(-1) );
496              
497             /* provide constants to add entry in a fake stat array */
498              
499 48           newCONSTSUB(stash, "ST_DEV", newSViv(ix++) );
500 48           newCONSTSUB(stash, "ST_INO", newSViv(ix++) );
501 48           newCONSTSUB(stash, "ST_MODE", newSViv(ix++) );
502 48           newCONSTSUB(stash, "ST_NLINK", newSViv(ix++) );
503 48           newCONSTSUB(stash, "ST_UID", newSViv(ix++) );
504 48           newCONSTSUB(stash, "ST_GID", newSViv(ix++) );
505 48           newCONSTSUB(stash, "ST_RDEV", newSViv(ix++) );
506 48           newCONSTSUB(stash, "ST_SIZE", newSViv(ix++) );
507 48           newCONSTSUB(stash, "ST_ATIME", newSViv(ix++) );
508 48           newCONSTSUB(stash, "ST_MTIME", newSViv(ix++) );
509 48           newCONSTSUB(stash, "ST_CTIME", newSViv(ix++) );
510 48           newCONSTSUB(stash, "ST_BLKSIZE", newSViv(ix++) );
511 48           newCONSTSUB(stash, "ST_BLOCKS", newSViv(ix++) );
512             assert(STAT_T_MAX == ix);
513 48           newCONSTSUB(stash, "STAT_T_MAX", newSViv(STAT_T_MAX) );
514              
515             /* copy the original OP then plug our own custom OP function */
516             /* view pp_sys.c for complete list */
517              
518             /* PP(pp_ftrread) - yes/no/undef */
519 48           INIT_FILECHECK_MOCK( "OP_FTRREAD", OP_FTRREAD, &Perl_pp_overload_ft_yes_no); /* -R */
520 48           INIT_FILECHECK_MOCK( "OP_FTRWRITE", OP_FTRWRITE, &Perl_pp_overload_ft_yes_no); /* -W */
521 48           INIT_FILECHECK_MOCK( "OP_FTREXEC", OP_FTREXEC, &Perl_pp_overload_ft_yes_no); /* -X */
522 48           INIT_FILECHECK_MOCK( "OP_FTEREAD", OP_FTEREAD, &Perl_pp_overload_ft_yes_no); /* -r */
523 48           INIT_FILECHECK_MOCK( "OP_FTEWRITE", OP_FTEWRITE, &Perl_pp_overload_ft_yes_no); /* -w */
524 48           INIT_FILECHECK_MOCK( "OP_FTEEXEC", OP_FTEEXEC, &Perl_pp_overload_ft_yes_no); /* -x */
525              
526             /* PP(pp_ftis) - yes/undef/true/false */
527 48           INIT_FILECHECK_MOCK( "OP_FTIS", OP_FTIS, &Perl_pp_overload_ft_yes_no); /* -e */
528 48           INIT_FILECHECK_MOCK( "OP_FTSIZE", OP_FTSIZE, &Perl_pp_overload_ft_int); /* -s */
529 48           INIT_FILECHECK_MOCK( "OP_FTMTIME", OP_FTMTIME, &Perl_pp_overload_ft_nv); /* -M */
530 48           INIT_FILECHECK_MOCK( "OP_FTCTIME", OP_FTCTIME, &Perl_pp_overload_ft_nv); /* -C */
531 48           INIT_FILECHECK_MOCK( "OP_FTATIME", OP_FTATIME, &Perl_pp_overload_ft_nv); /* -A */
532              
533             /* PP(pp_ftrowned) yes/no/undef */
534 48           INIT_FILECHECK_MOCK( "OP_FTROWNED", OP_FTROWNED, &Perl_pp_overload_ft_yes_no); /* -O */
535 48           INIT_FILECHECK_MOCK( "OP_FTEOWNED", OP_FTEOWNED, &Perl_pp_overload_ft_yes_no); /* -o */
536 48           INIT_FILECHECK_MOCK( "OP_FTZERO", OP_FTZERO, &Perl_pp_overload_ft_yes_no); /* -z */
537 48           INIT_FILECHECK_MOCK( "OP_FTSOCK", OP_FTSOCK, &Perl_pp_overload_ft_yes_no); /* -S */
538 48           INIT_FILECHECK_MOCK( "OP_FTCHR", OP_FTCHR, &Perl_pp_overload_ft_yes_no); /* -c */
539 48           INIT_FILECHECK_MOCK( "OP_FTBLK", OP_FTBLK, &Perl_pp_overload_ft_yes_no); /* -b */
540 48           INIT_FILECHECK_MOCK( "OP_FTFILE", OP_FTFILE, &Perl_pp_overload_ft_yes_no); /* -f */
541 48           INIT_FILECHECK_MOCK( "OP_FTDIR", OP_FTDIR, &Perl_pp_overload_ft_yes_no); /* -d */
542 48           INIT_FILECHECK_MOCK( "OP_FTPIPE", OP_FTPIPE, &Perl_pp_overload_ft_yes_no); /* -p */
543 48           INIT_FILECHECK_MOCK( "OP_FTSUID", OP_FTSUID, &Perl_pp_overload_ft_yes_no); /* -u */
544 48           INIT_FILECHECK_MOCK( "OP_FTSGID", OP_FTSGID, &Perl_pp_overload_ft_yes_no); /* -g */
545 48           INIT_FILECHECK_MOCK( "OP_FTSVTX", OP_FTSVTX, &Perl_pp_overload_ft_yes_no); /* -k */
546              
547             /* PP(pp_ftlink) - yes/no/undef */
548 48           INIT_FILECHECK_MOCK( "OP_FTLINK", OP_FTLINK, &Perl_pp_overload_ft_yes_no); /* -l */
549              
550             /* PP(pp_fttty) - yes/no/undef */
551 48           INIT_FILECHECK_MOCK( "OP_FTTTY", OP_FTTTY, &Perl_pp_overload_ft_yes_no); /* -t */
552              
553             /* PP(pp_fttext) - yes/no/undef */
554 48           INIT_FILECHECK_MOCK( "OP_FTTEXT", OP_FTTEXT, &Perl_pp_overload_ft_yes_no); /* -T */
555 48           INIT_FILECHECK_MOCK( "OP_FTBINARY", OP_FTBINARY, &Perl_pp_overload_ft_yes_no); /* -B */
556              
557             /* PP(pp_stat) also used for: pp_lstat() */
558 48           INIT_FILECHECK_MOCK( "OP_STAT", OP_STAT, &Perl_pp_overload_stat); /* stat */
559 48           INIT_FILECHECK_MOCK( "OP_LSTAT", OP_LSTAT, &Perl_pp_overload_stat); /* lstat */
560              
561             }
562              
563