1*d874e919Schristos# Copyright (C) 2001-2012 Free Software Foundation, Inc. 2*d874e919Schristos 3*d874e919Schristos# This program is free software; you can redistribute it and/or modify 4*d874e919Schristos# it under the terms of the GNU General Public License as published by 5*d874e919Schristos# the Free Software Foundation; either version 2, or (at your option) 6*d874e919Schristos# any later version. 7*d874e919Schristos 8*d874e919Schristos# This program is distributed in the hope that it will be useful, 9*d874e919Schristos# but WITHOUT ANY WARRANTY; without even the implied warranty of 10*d874e919Schristos# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11*d874e919Schristos# GNU General Public License for more details. 12*d874e919Schristos 13*d874e919Schristos# You should have received a copy of the GNU General Public License 14*d874e919Schristos# along with this program. If not, see <http://www.gnu.org/licenses/>. 15*d874e919Schristos 16*d874e919Schristos# Written by Akim Demaille <akim@freefriends.org>. 17*d874e919Schristos 18*d874e919Schristos############################################################### 19*d874e919Schristos# The main copy of this file is in Automake's git repository. # 20*d874e919Schristos# Updates should be sent to automake-patches@gnu.org. # 21*d874e919Schristos############################################################### 22*d874e919Schristos 23*d874e919Schristospackage Autom4te::XFile; 24*d874e919Schristos 25*d874e919Schristos=head1 NAME 26*d874e919Schristos 27*d874e919SchristosAutom4te::XFile - supply object methods for filehandles with error handling 28*d874e919Schristos 29*d874e919Schristos=head1 SYNOPSIS 30*d874e919Schristos 31*d874e919Schristos use Autom4te::XFile; 32*d874e919Schristos 33*d874e919Schristos $fh = new Autom4te::XFile; 34*d874e919Schristos $fh->open ("< file"); 35*d874e919Schristos # No need to check $FH: we died if open failed. 36*d874e919Schristos print <$fh>; 37*d874e919Schristos $fh->close; 38*d874e919Schristos # No need to check the return value of close: we died if it failed. 39*d874e919Schristos 40*d874e919Schristos $fh = new Autom4te::XFile "> file"; 41*d874e919Schristos # No need to check $FH: we died if new failed. 42*d874e919Schristos print $fh "bar\n"; 43*d874e919Schristos $fh->close; 44*d874e919Schristos 45*d874e919Schristos $fh = new Autom4te::XFile "file", "r"; 46*d874e919Schristos # No need to check $FH: we died if new failed. 47*d874e919Schristos defined $fh 48*d874e919Schristos print <$fh>; 49*d874e919Schristos undef $fh; # automatically closes the file and checks for errors. 50*d874e919Schristos 51*d874e919Schristos $fh = new Autom4te::XFile "file", O_WRONLY | O_APPEND; 52*d874e919Schristos # No need to check $FH: we died if new failed. 53*d874e919Schristos print $fh "corge\n"; 54*d874e919Schristos 55*d874e919Schristos $pos = $fh->getpos; 56*d874e919Schristos $fh->setpos ($pos); 57*d874e919Schristos 58*d874e919Schristos undef $fh; # automatically closes the file and checks for errors. 59*d874e919Schristos 60*d874e919Schristos autoflush STDOUT 1; 61*d874e919Schristos 62*d874e919Schristos=head1 DESCRIPTION 63*d874e919Schristos 64*d874e919SchristosC<Autom4te::XFile> inherits from C<IO::File>. It provides the method 65*d874e919SchristosC<name> returning the file name. It provides dying versions of the 66*d874e919Schristosmethods C<close>, C<lock> (corresponding to C<flock>), C<new>, 67*d874e919SchristosC<open>, C<seek>, and C<truncate>. It also overrides the C<getline> 68*d874e919Schristosand C<getlines> methods to translate C<\r\n> to C<\n>. 69*d874e919Schristos 70*d874e919Schristos=cut 71*d874e919Schristos 72*d874e919Schristosuse 5.006; 73*d874e919Schristosuse strict; 74*d874e919Schristosuse vars qw($VERSION @EXPORT @EXPORT_OK $AUTOLOAD @ISA); 75*d874e919Schristosuse Carp; 76*d874e919Schristosuse Errno; 77*d874e919Schristosuse IO::File; 78*d874e919Schristosuse File::Basename; 79*d874e919Schristosuse Autom4te::ChannelDefs; 80*d874e919Schristosuse Autom4te::Channels qw(msg); 81*d874e919Schristosuse Autom4te::FileUtils; 82*d874e919Schristos 83*d874e919Schristosrequire Exporter; 84*d874e919Schristosrequire DynaLoader; 85*d874e919Schristos 86*d874e919Schristos@ISA = qw(IO::File Exporter DynaLoader); 87*d874e919Schristos 88*d874e919Schristos$VERSION = "1.2"; 89*d874e919Schristos 90*d874e919Schristos@EXPORT = @IO::File::EXPORT; 91*d874e919Schristos 92*d874e919Schristoseval { 93*d874e919Schristos # Make all Fcntl O_XXX and LOCK_XXX constants available for importing 94*d874e919Schristos require Fcntl; 95*d874e919Schristos my @O = grep /^(LOCK|O)_/, @Fcntl::EXPORT, @Fcntl::EXPORT_OK; 96*d874e919Schristos Fcntl->import (@O); # first we import what we want to export 97*d874e919Schristos push (@EXPORT, @O); 98*d874e919Schristos}; 99*d874e919Schristos 100*d874e919Schristos=head2 Methods 101*d874e919Schristos 102*d874e919Schristos=over 103*d874e919Schristos 104*d874e919Schristos=item C<$fh = new Autom4te::XFile ([$expr, ...]> 105*d874e919Schristos 106*d874e919SchristosConstructor a new XFile object. Additional arguments 107*d874e919Schristosare passed to C<open>, if any. 108*d874e919Schristos 109*d874e919Schristos=cut 110*d874e919Schristos 111*d874e919Schristossub new 112*d874e919Schristos{ 113*d874e919Schristos my $type = shift; 114*d874e919Schristos my $class = ref $type || $type || "Autom4te::XFile"; 115*d874e919Schristos my $fh = $class->SUPER::new (); 116*d874e919Schristos if (@_) 117*d874e919Schristos { 118*d874e919Schristos $fh->open (@_); 119*d874e919Schristos } 120*d874e919Schristos $fh; 121*d874e919Schristos} 122*d874e919Schristos 123*d874e919Schristos=item C<$fh-E<gt>open ([$file, ...])> 124*d874e919Schristos 125*d874e919SchristosOpen a file, passing C<$file> and further arguments to C<IO::File::open>. 126*d874e919SchristosDie if opening fails. Store the name of the file. Use binmode for writing. 127*d874e919Schristos 128*d874e919Schristos=cut 129*d874e919Schristos 130*d874e919Schristossub open 131*d874e919Schristos{ 132*d874e919Schristos my $fh = shift; 133*d874e919Schristos my ($file) = @_; 134*d874e919Schristos 135*d874e919Schristos # WARNING: Gross hack: $FH is a typeglob: use its hash slot to store 136*d874e919Schristos # the 'name' of the file we are opening. See the example with 137*d874e919Schristos # io_socket_timeout in IO::Socket for more, and read Graham's 138*d874e919Schristos # comment in IO::Handle. 139*d874e919Schristos ${*$fh}{'autom4te_xfile_file'} = "$file"; 140*d874e919Schristos 141*d874e919Schristos if (!$fh->SUPER::open (@_)) 142*d874e919Schristos { 143*d874e919Schristos fatal "cannot open $file: $!"; 144*d874e919Schristos } 145*d874e919Schristos 146*d874e919Schristos # In case we're running under MSWindows, don't write with CRLF. 147*d874e919Schristos # (This circumvents a bug in at least Cygwin bash where the shell 148*d874e919Schristos # parsing fails on lines ending with the continuation character '\' 149*d874e919Schristos # and CRLF). 150*d874e919Schristos binmode $fh if $file =~ /^\s*>/; 151*d874e919Schristos} 152*d874e919Schristos 153*d874e919Schristos=item C<$fh-E<gt>close> 154*d874e919Schristos 155*d874e919SchristosClose the file, handling errors. 156*d874e919Schristos 157*d874e919Schristos=cut 158*d874e919Schristos 159*d874e919Schristossub close 160*d874e919Schristos{ 161*d874e919Schristos my $fh = shift; 162*d874e919Schristos if (!$fh->SUPER::close (@_)) 163*d874e919Schristos { 164*d874e919Schristos my $file = $fh->name; 165*d874e919Schristos Autom4te::FileUtils::handle_exec_errors $file 166*d874e919Schristos unless $!; 167*d874e919Schristos fatal "cannot close $file: $!"; 168*d874e919Schristos } 169*d874e919Schristos} 170*d874e919Schristos 171*d874e919Schristos=item C<$line = $fh-E<gt>getline> 172*d874e919Schristos 173*d874e919SchristosRead and return a line from the file. Ensure C<\r\n> is translated to 174*d874e919SchristosC<\n> on input files. 175*d874e919Schristos 176*d874e919Schristos=cut 177*d874e919Schristos 178*d874e919Schristos# Some native Windows/perl installations fail to translate \r\n to \n on 179*d874e919Schristos# input so we do that here. 180*d874e919Schristossub getline 181*d874e919Schristos{ 182*d874e919Schristos local $_ = $_[0]->SUPER::getline; 183*d874e919Schristos # Perform a _global_ replacement: $_ may can contains many lines 184*d874e919Schristos # in slurp mode ($/ = undef). 185*d874e919Schristos s/\015\012/\n/gs if defined $_; 186*d874e919Schristos return $_; 187*d874e919Schristos} 188*d874e919Schristos 189*d874e919Schristos=item C<@lines = $fh-E<gt>getlines> 190*d874e919Schristos 191*d874e919SchristosSlurp lines from the files. 192*d874e919Schristos 193*d874e919Schristos=cut 194*d874e919Schristos 195*d874e919Schristossub getlines 196*d874e919Schristos{ 197*d874e919Schristos my @res = (); 198*d874e919Schristos my $line; 199*d874e919Schristos push @res, $line while $line = $_[0]->getline; 200*d874e919Schristos return @res; 201*d874e919Schristos} 202*d874e919Schristos 203*d874e919Schristos=item C<$name = $fh-E<gt>name> 204*d874e919Schristos 205*d874e919SchristosReturn the name of the file. 206*d874e919Schristos 207*d874e919Schristos=cut 208*d874e919Schristos 209*d874e919Schristossub name 210*d874e919Schristos{ 211*d874e919Schristos my $fh = shift; 212*d874e919Schristos return ${*$fh}{'autom4te_xfile_file'}; 213*d874e919Schristos} 214*d874e919Schristos 215*d874e919Schristos=item C<$fh-E<gt>lock> 216*d874e919Schristos 217*d874e919SchristosLock the file using C<flock>. If locking fails for reasons other than 218*d874e919SchristosC<flock> being unsupported, then error out if C<$ENV{'MAKEFLAGS'}> indicates 219*d874e919Schristosthat we are spawned from a parallel C<make>. 220*d874e919Schristos 221*d874e919Schristos=cut 222*d874e919Schristos 223*d874e919Schristossub lock 224*d874e919Schristos{ 225*d874e919Schristos my ($fh, $mode) = @_; 226*d874e919Schristos # Cannot use @_ here. 227*d874e919Schristos 228*d874e919Schristos # Unless explicitly configured otherwise, Perl implements its 'flock' with the 229*d874e919Schristos # first of flock(2), fcntl(2), or lockf(3) that works. These can fail on 230*d874e919Schristos # NFS-backed files, with ENOLCK (GNU/Linux) or EOPNOTSUPP (FreeBSD); we 231*d874e919Schristos # usually ignore these errors. If $ENV{MAKEFLAGS} suggests that a parallel 232*d874e919Schristos # invocation of 'make' has invoked the tool we serve, report all locking 233*d874e919Schristos # failures and abort. 234*d874e919Schristos # 235*d874e919Schristos # On Unicos, flock(2) and fcntl(2) over NFS hang indefinitely when 'lockd' is 236*d874e919Schristos # not running. NetBSD NFS clients silently grant all locks. We do not 237*d874e919Schristos # attempt to defend against these dangers. 238*d874e919Schristos # 239*d874e919Schristos # -j is for parallel BSD make, -P is for parallel HP-UX make. 240*d874e919Schristos if (!flock ($fh, $mode)) 241*d874e919Schristos { 242*d874e919Schristos my $make_j = (exists $ENV{'MAKEFLAGS'} 243*d874e919Schristos && " -$ENV{'MAKEFLAGS'}" =~ / (-[BdeikrRsSw]*[jP]|--[jP]|---?jobs)/); 244*d874e919Schristos my $note = "\nforgo \"make -j\" or use a file system that supports locks"; 245*d874e919Schristos my $file = $fh->name; 246*d874e919Schristos 247*d874e919Schristos msg ($make_j ? 'fatal' : 'unsupported', 248*d874e919Schristos "cannot lock $file with mode $mode: $!" . ($make_j ? $note : "")) 249*d874e919Schristos if $make_j || !($!{ENOLCK} || $!{EOPNOTSUPP}); 250*d874e919Schristos } 251*d874e919Schristos} 252*d874e919Schristos 253*d874e919Schristos=item C<$fh-E<gt>seek ($position, [$whence])> 254*d874e919Schristos 255*d874e919SchristosSeek file to C<$position>. Die if seeking fails. 256*d874e919Schristos 257*d874e919Schristos=cut 258*d874e919Schristos 259*d874e919Schristossub seek 260*d874e919Schristos{ 261*d874e919Schristos my $fh = shift; 262*d874e919Schristos # Cannot use @_ here. 263*d874e919Schristos if (!seek ($fh, $_[0], $_[1])) 264*d874e919Schristos { 265*d874e919Schristos my $file = $fh->name; 266*d874e919Schristos fatal "cannot rewind $file with @_: $!"; 267*d874e919Schristos } 268*d874e919Schristos} 269*d874e919Schristos 270*d874e919Schristos=item C<$fh-E<gt>truncate ($len)> 271*d874e919Schristos 272*d874e919SchristosTruncate the file to length C<$len>. Die on failure. 273*d874e919Schristos 274*d874e919Schristos=cut 275*d874e919Schristos 276*d874e919Schristossub truncate 277*d874e919Schristos{ 278*d874e919Schristos my ($fh, $len) = @_; 279*d874e919Schristos if (!truncate ($fh, $len)) 280*d874e919Schristos { 281*d874e919Schristos my $file = $fh->name; 282*d874e919Schristos fatal "cannot truncate $file at $len: $!"; 283*d874e919Schristos } 284*d874e919Schristos} 285*d874e919Schristos 286*d874e919Schristos=back 287*d874e919Schristos 288*d874e919Schristos=head1 SEE ALSO 289*d874e919Schristos 290*d874e919SchristosL<perlfunc>, 291*d874e919SchristosL<perlop/"I/O Operators">, 292*d874e919SchristosL<IO::File> 293*d874e919SchristosL<IO::Handle> 294*d874e919SchristosL<IO::Seekable> 295*d874e919Schristos 296*d874e919Schristos=head1 HISTORY 297*d874e919Schristos 298*d874e919SchristosDerived from IO::File.pm by Akim Demaille E<lt>F<akim@freefriends.org>E<gt>. 299*d874e919Schristos 300*d874e919Schristos=cut 301*d874e919Schristos 302*d874e919Schristos1; 303*d874e919Schristos 304*d874e919Schristos### Setup "GNU" style for perl-mode and cperl-mode. 305*d874e919Schristos## Local Variables: 306*d874e919Schristos## perl-indent-level: 2 307*d874e919Schristos## perl-continued-statement-offset: 2 308*d874e919Schristos## perl-continued-brace-offset: 0 309*d874e919Schristos## perl-brace-offset: 0 310*d874e919Schristos## perl-brace-imaginary-offset: 0 311*d874e919Schristos## perl-label-offset: -2 312*d874e919Schristos## cperl-indent-level: 2 313*d874e919Schristos## cperl-brace-offset: 0 314*d874e919Schristos## cperl-continued-brace-offset: 0 315*d874e919Schristos## cperl-label-offset: -2 316*d874e919Schristos## cperl-extra-newline-before-brace: t 317*d874e919Schristos## cperl-merge-trailing-else: nil 318*d874e919Schristos## cperl-continued-statement-offset: 2 319*d874e919Schristos## End: 320