File Coverage

blib/lib/Perl/Critic/Policy/ValuesAndExpressions/ProhibitFiletest_f.pm
Criterion Covered Total %
statement 32 32 100.0
branch 2 2 100.0
condition n/a
subroutine 11 11 100.0
pod 1 1 100.0
total 46 46 100.0


line stmt bran cond sub pod time code
1             # Copyright 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Kevin Ryde
2              
3             # Perl-Critic-Pulp is free software; you can redistribute it and/or modify
4             # it under the terms of the GNU General Public License as published by the
5             # Free Software Foundation; either version 3, or (at your option) any later
6             # version.
7             #
8             # Perl-Critic-Pulp is distributed in the hope that it will be useful, but
9             # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10             # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11             # for more details.
12             #
13             # You should have received a copy of the GNU General Public License along
14             # with Perl-Critic-Pulp. If not, see <http://www.gnu.org/licenses/>.
15              
16              
17             package Perl::Critic::Policy::ValuesAndExpressions::ProhibitFiletest_f;
18 40     40   33206 use 5.006;
  40         153  
19 40     40   219 use strict;
  40         87  
  40         857  
20 40     40   201 use warnings;
  40         107  
  40         1233  
21              
22 40     40   214 use base 'Perl::Critic::Policy';
  40         82  
  40         4979  
23 40     40   184824 use Perl::Critic::Utils;
  40         112  
  40         746  
24 40     40   36533 use Perl::Critic::Pulp;
  40         94  
  40         1982  
25              
26             our $VERSION = 99;
27              
28 40     40   299 use constant supported_parameters => ();
  40         94  
  40         2689  
29 40     40   316 use constant default_severity => $Perl::Critic::Utils::SEVERITY_MEDIUM;
  40         109  
  40         2400  
30 40     40   295 use constant default_themes => qw(pulp bugs);
  40         108  
  40         2407  
31 40     40   269 use constant applies_to => 'PPI::Token::Operator';
  40         116  
  40         5204  
32              
33             sub violates {
34 12     12 1 586306 my ($self, $elem, $document) = @_;
35              
36 12 100       44 return if ($elem->content ne '-f');
37 6         48 return $self->violation ("Don't use the -f file test", '', $elem);
38             }
39              
40             1;
41             __END__
42              
43             =for stopwords seekable filename Ryde
44              
45             =head1 NAME
46              
47             Perl::Critic::Policy::ValuesAndExpressions::ProhibitFiletest_f - don't use the -f file test
48              
49             =head1 DESCRIPTION
50              
51             This policy is part of the L<C<Perl::Critic::Pulp>|Perl::Critic::Pulp>
52             add-on. It asks you not to use the C<-f> file test because doing so is
53             usually wrong or unnecessarily restrictive. On that basis this policy is
54             under the "bugs" theme and medium severity, see L<Perl::Critic/POLICY
55             THEMES>.
56              
57             =over 4
58              
59             =item C<-f> is not the opposite of C<-d>
60              
61             If you're traversing a tree and want to distinguish files from directories
62             to descend into, then C<-d> should be used so device files or named pipes
63             can be processed.
64              
65             if (-f $filename) { # bad
66             process ($filename);
67             } else {
68             descend ($filename);
69             }
70              
71             if (-d $filename) { # better
72             descend ($filename);
73             } else {
74             process ($filename);
75             }
76              
77             =item C<-f> doesn't mean readable/writable/seekable
78              
79             Char specials and named pipes are perfectly good for reading and writing,
80             and char specials can support seeking. Demanding C<-f> is an unnecessary
81             restriction. You might only ever use ordinary files normally, but there's
82             no need to prevent someone else running it on a tape drive, F</dev/null>,
83             etc. You always have to test each C<seek()> etc for success anyway, and
84             that will tell you if a file is seekable.
85              
86             seek HANDLE, 123, 0
87             or die "Cannot seek: $!";
88              
89             =item C<-e> is better than C<-f>
90              
91             A few inflexible functions or operations may not have good "file not found"
92             behaviour and may force you to check for a file before invoking. Using
93             C<-e> is better than C<-f> since as described above it doesn't unnecessarily
94             disallow device files.
95              
96             if (-f $filename) { # bad
97             require $filename;
98             }
99              
100             if (-e $filename) { # better
101             require $filename;
102             }
103              
104             =item C<-f> before opening is a race condition
105              
106             Testing a filename before opening is bad. Any test before opening is
107             useless because the file can change or be removed in between the test and
108             the open (L<perlfunc/-X>, and L<filetest/Consider this carefully>, note this
109             about C<-r> etc too).
110              
111             if (-f $filename) { # bad
112             open HANDLE, '<', $filename
113             }
114              
115             If you want to know if the file can be opened then open the file! The error
116             return from C<open()> must be checked, so a test beforehand only duplicates
117             that, and is an opportunity to wrongly presume what the system or the user's
118             permissions can or can't do.
119              
120             When opening, C<ENOENT> will say if there was no such file, or C<EISDIR> if
121             it's in fact a directory.
122              
123             if (! open HANDLE, '<', $filename) { # better
124             if ($! == POSIX::ENOENT()) {
125             ...
126             }
127             }
128              
129             If you really do want to enquire into the nature of the file, in order to
130             only accept ordinary files, then open first and C<-f> on the handle. But
131             that's unusual except for an archiving or backup program.
132              
133             Incidentally, the error message in C<$!> is normally the best thing to
134             print. It can be slightly technical, but its wording will at least be
135             familiar from other programs and is translated into the user's locale
136             language.
137              
138             =back
139              
140             =head2 Disabling
141              
142             Most uses of C<-f> tend to shell script style code written in Perl. In the
143             shell, it's usually not possible to do better than such tests (though C<-d>
144             or C<-e> are still generally better than C<-f>), but Perl can do the right
145             thing.
146              
147             A blanket prohibition like this policy is harsh, but is meant as a building
148             block or at least to make you think carefully whether C<-f> is really right.
149             As always you can disable C<ProhibitFiletest_f> from your F<.perlcriticrc>
150             in the usual way (see L<Perl::Critic/CONFIGURATION>),
151              
152             [-ValuesAndExpressions::ProhibitFiletest_f]
153              
154             =head1 SEE ALSO
155              
156             L<Perl::Critic::Pulp>,
157             L<Perl::Critic>,
158             L<perlfunc/open>,
159             L<POSIX/ERRNO>,
160             L<Errno>,
161             L<errno(3)>
162              
163             =head1 HOME PAGE
164              
165             http://user42.tuxfamily.org/perl-critic-pulp/index.html
166              
167             =head1 COPYRIGHT
168              
169             Copyright 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Kevin Ryde
170              
171             Perl-Critic-Pulp is free software; you can redistribute it and/or modify it
172             under the terms of the GNU General Public License as published by the Free
173             Software Foundation; either version 3, or (at your option) any later
174             version.
175              
176             Perl-Critic-Pulp is distributed in the hope that it will be useful, but
177             WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
178             or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
179             more details.
180              
181             You should have received a copy of the GNU General Public License along with
182             Perl-Critic-Pulp. If not, see <http://www.gnu.org/licenses>.
183              
184             =cut