XFile.pm 7.6 KB

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