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