Add built local::lib
[catagits/Gitalist.git] / local-lib5 / lib / perl5 / IO / AtomicFile.pm
CommitLineData
3fea05b9 1package IO::AtomicFile;
2
3### DOCUMENTATION AT BOTTOM OF FILE
4
5# Be strict:
6use strict;
7
8# External modules:
9use IO::File;
10
11
12#------------------------------
13#
14# GLOBALS...
15#
16#------------------------------
17use vars qw($VERSION @ISA);
18
19# The package version, both in 1.23 style *and* usable by MakeMaker:
20$VERSION = "2.110";
21
22# Inheritance:
23@ISA = qw(IO::File);
24
25
26#------------------------------
27# new ARGS...
28#------------------------------
29# Class method, constructor.
30# Any arguments are sent to open().
31#
32sub new {
33 my $class = shift;
34 my $self = $class->SUPER::new();
35 ${*$self}{'io_atomicfile_suffix'} = '';
36 $self->open(@_) if @_;
37 $self;
38}
39
40#------------------------------
41# DESTROY
42#------------------------------
43# Destructor.
44#
45sub DESTROY {
46 shift->close(1); ### like close, but raises fatal exception on failure
47}
48
49#------------------------------
50# open PATH, MODE
51#------------------------------
52# Class/instance method.
53#
54sub open {
55 my ($self, $path, $mode) = @_;
56 ref($self) or $self = $self->new; ### now we have an instance!
57
58 ### Create tmp path, and remember this info:
59 my $temp = "${path}..TMP" . ${*$self}{'io_atomicfile_suffix'};
60 ${*$self}{'io_atomicfile_temp'} = $temp;
61 ${*$self}{'io_atomicfile_path'} = $path;
62
63 ### Open the file! Returns filehandle on success, for use as a constructor:
64 $self->SUPER::open($temp, $mode) ? $self : undef;
65}
66
67#------------------------------
68# _closed [YESNO]
69#------------------------------
70# Instance method, private.
71# Are we already closed? Argument sets new value, returns previous one.
72#
73sub _closed {
74 my $self = shift;
75 my $oldval = ${*$self}{'io_atomicfile_closed'};
76 ${*$self}{'io_atomicfile_closed'} = shift if @_;
77 $oldval;
78}
79
80#------------------------------
81# close
82#------------------------------
83# Instance method.
84# Close the handle, and rename the temp file to its final name.
85#
86sub close {
87 my ($self, $die) = @_;
88 unless ($self->_closed(1)) { ### sentinel...
89 $self->SUPER::close();
90 rename(${*$self}{'io_atomicfile_temp'},
91 ${*$self}{'io_atomicfile_path'})
92 or ($die ? die "close atomic file: $!\n" : return undef);
93 }
94 1;
95}
96
97#------------------------------
98# delete
99#------------------------------
100# Instance method.
101# Close the handle, and delete the temp file.
102#
103sub delete {
104 my $self = shift;
105 unless ($self->_closed(1)) { ### sentinel...
106 $self->SUPER::close();
107 return unlink(${*$self}{'io_atomicfile_temp'});
108 }
109 1;
110}
111
112#------------------------------
113# detach
114#------------------------------
115# Instance method.
116# Close the handle, but DO NOT delete the temp file.
117#
118sub detach {
119 my $self = shift;
120 $self->SUPER::close() unless ($self->_closed(1));
121 1;
122}
123
124#------------------------------
1251;
126__END__
127
128
129=head1 NAME
130
131IO::AtomicFile - write a file which is updated atomically
132
133
134=head1 SYNOPSIS
135
136 use IO::AtomicFile;
137
138 ### Write a temp file, and have it install itself when closed:
139 my $FH = IO::AtomicFile->open("bar.dat", "w");
140 print $FH "Hello!\n";
141 $FH->close || die "couldn't install atomic file: $!";
142
143 ### Write a temp file, but delete it before it gets installed:
144 my $FH = IO::AtomicFile->open("bar.dat", "w");
145 print $FH "Hello!\n";
146 $FH->delete;
147
148 ### Write a temp file, but neither install it nor delete it:
149 my $FH = IO::AtomicFile->open("bar.dat", "w");
150 print $FH "Hello!\n";
151 $FH->detach;
152
153
154=head1 DESCRIPTION
155
156This module is intended for people who need to update files
157reliably in the face of unexpected program termination.
158
159For example, you generally don't want to be halfway in the middle of
160writing I</etc/passwd> and have your program terminate! Even
161the act of writing a single scalar to a filehandle is I<not> atomic.
162
163But this module gives you true atomic updates, via rename().
164When you open a file I</foo/bar.dat> via this module, you are I<actually>
165opening a temporary file I</foo/bar.dat..TMP>, and writing your
166output there. The act of closing this file (either explicitly
167via close(), or implicitly via the destruction of the object)
168will cause rename() to be called... therefore, from the point
169of view of the outside world, the file's contents are updated
170in a single time quantum.
171
172To ensure that problems do not go undetected, the "close" method
173done by the destructor will raise a fatal exception if the rename()
174fails. The explicit close() just returns undef.
175
176You can also decide at any point to trash the file you've been
177building.
178
179
180=head1 AUTHOR
181
182=head2 Primary Maintainer
183
184David F. Skoll (F<dfs@roaringpenguin.com>).
185
186=head2 Original Author
187
188Eryq (F<eryq@zeegee.com>).
189President, ZeeGee Software Inc (F<http://www.zeegee.com>).
190
191
192=head1 REVISION
193
194$Revision: 1.2 $
195
196=cut