1/*
2 * Copyright (c) 2009-2013 Zmanda, Inc.  All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 *
18 * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
19 * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
20 */
21
22%perlcode %{
23
24=head1 NAME
25
26Amanda::Archive - Perl access to the  amanda archive library
27
28=head1 SYNOPSIS
29
30  use Amanda::Archive
31
32  # Write to the file descriptor or file handle $fd, and
33  # add /etc/hosts to it
34  my $archive = Amanda::Archive->new($fd, ">");
35  my $file = $archive->new_file("/etc/hosts");
36  my $attr = $file->new_attr(16);
37  open(my $fh, "<", "/etc/hosts");
38  $attr->add_data_fd($fh, 1);
39  $file->close();
40  $archive->close();
41
42  # Read from an archive
43  my $archive = Amanda::Archive->new($fd, "<");
44  $ar->read(
45      file_start => sub {
46	  my ($user_data, $filenum, $filename) = @_;
47	  # ...
48	  return "foo"; # this becomes $file_data
49      },
50      file_finish => sub {
51	  my ($user_data, $file_data, $filenum, $truncated) = @_;
52	  # ...
53      },
54      21 => [ 32768,	# buffer into 32k chunks
55	      sub {
56		  my ($user_data, $filenum, $file_data, $attrid,
57		      $attr_data, $data, $eoa, $truncated) = @_;
58		  return "pants"; # becomes the new $attr_data for
59				  # any subsequent fragments
60	      } ],
61      0 => sub {	# note no buffering here; attrid 0 is "default"
62	  my ($user_data, $filenum, $file_data, $attrid,
63	      $attr_data, $data, $eoa, $truncated) = @_;
64	  return "shorts"; # becomes the new $attr_data for
65			   # any subsequent fragments
66      },
67      user_data => [ "mydata" ], # sent to all callbacks
68  );
69
70=head1 WRITING
71
72=head2 Amanda::Archive::Archive Objects
73
74Note that C<< Amanda::Archive->new >> and C<<
75Amanda::Archive::Archive->new >> are equivalent.
76
77=over
78
79=item C<new($fd, $mode)>
80
81Create a new archive for reading ("<") or writing (">") from or to
82file C<$fd> (a file handle or integer file descriptor).
83
84=item C<size()>
85
86Return the number of bytes already written to the archive.
87
88=item C<new_file($filename, $want_posn)>
89
90Create a new C<Amanda::Archive::File> object with the given filename
91(writing only).  Equivalent to
92
93  Amanda::Archive::File->new($archive, $filename, $want_posn);
94
95if C<$want_posn> is false, then this method returns a new
96C<Amanda::Archive::File> object.  If C<$want_posn> is true, then it
97returns C<($file, $posn)> where C<$file> is the object and C<$posn> is
98the offset into the datastream at which this file begins.  This offset
99can be stored in an index and used later to seek into the file.
100
101=item C<read(..)>
102
103See I<READING>, below.
104
105=item C<close()>
106
107Flush all buffers and close this archive. This does not close the file
108descriptor.
109
110=back
111
112=head2 Amanda::Archive::File Objects
113
114=over
115
116=item C<new($archive, $filename, $want_posn)>
117
118Create a new file in the given archive.  See
119C<Amanda::Archive::Archive::new_file>, above.
120
121=item C<new_attr($attrid)>
122
123Create a new C<Amanda::Archive::Attribute> object.  Equivalent to
124
125  Amanda::Archive::Attr->new($file, $attrid);
126
127=item C<size()>
128
129Return the size on the archive of all attributes of the file.
130
131=item C<close()>
132
133Close this file, writing an EOF record.
134
135=back
136
137=head2 Amanda::Archive::Attribute Objects
138
139=over
140
141=item C<add_data($data, $eoa)>
142
143Add C<$data> to this attribute, adding an EOA (end-of-attribute) bit
144if C<$eoa> is true.
145
146=item C<add_data_fd($fh, $eoa)>
147
148Copy data from C<$fh> to this attribute, adding an EOA
149(end-of-attribute) bit if C<$eoa> is true.
150
151=item C<add_data_fd_in_thread($fh, $eoa)>
152
153Same as C<add_data_fd> but the copy is done in a newly created thread.
154This function return immediately.
155Nothing should be done on the archive while it is running.
156The next action on the archive must be $attr->close().
157
158=item C<size()>
159
160Return the size of the data of the attribute.
161
162=item C<close()>
163
164Close this attribute, adding an EOA bit if none has been written
165already.
166
167=back
168
169=head1 READING
170
171The C<Amanda::Archive::Archive> method C<read()> handles reading
172archives via a callback mechanism.  It takes its arguments in hash
173form, with the following keys:
174
175    file_start => sub {
176	my ($user_data, $filenum, $filename) = @_;
177	# ..
178    },
179
180C<file_start> gives a sub which is called for every file in the
181archive.  It can return an arbitrary value which will become the
182C<$file_data> for subsequent callbacks in this file, or the string
183"IGNORE" which will cause the reader to ignore all data for this file.
184In this case, no other callbacks will be made for the file (not even
185C<file_finish>).
186
187    file_finish => sub {
188	my ($user_data, $file_data, $filenum, $truncated) = @_;
189	# ..
190    },
191
192C<file_finish> gives a sub which is called when an EOF record appears.
193C<$file_data> comes from the return value of the C<file_start>
194callback.  C<$truncated> is true if the file may be missing data
195(e.g., when an early EOF is detected).
196
197    user_data => $my_object,
198
199C<user_data> gives an arbitrary value which is passed to each callback
200as C<$user_data>.
201
202    13 => sub {
203	my ($user_data, $filenum, $file_data, $attrid,
204	    $attr_data, $data, $eoa, $truncated) = @_;
205	# ...
206    },
207    19 => [ 10240, sub { ... } ],
208
209Any numeric key is treated as an attribute ID, and specifies the
210handling for that attribute.  Attribute ID zero is treated as a
211wildcard, and will match any attribute without an explicit handler.
212The handler can be specified as a sub (as for attribute ID 13 in the
213example above) or as an arrayref C<[$minsize, $sub]>.  In the latter
214case, the sub is only called when at least C<$minsize> bytes of data
215are available for the attribute, or at the end of the attribute data.
216
217The parameters to the callback include C<$file_data>, the value
218returned from C<file_start>, and C<$attr_data>, which is the return
219value of the last invocation of this sub for this attribute.  If this
220is the last fragment of data for this attribute, then C<$eoa> is true.
221The meaning of C<$truncated> is similar to that in C<file_finish>.
222
223=head2 EXAMPLE
224
225    sub read_to_files {
226	my ($arch_fh, $basedir) = @_;
227
228	my $arch = Amanda::Archive->new(fileno($arch_fh), "<");
229	$arch->read(
230	    file_start => sub {
231		my ($user_data, $filenum, $filename) = @_;
232		return "$basedir/$filenum"; # becomes $file_data
233	    },
234	    0 => [ 32768, sub {
235		my ($user_data, $filenum, $file_data, $attrid,
236		    $attr_data, $data, $eoa, $truncated) = @_;
237		warn("file $filename attribute $attrid is truncated")
238		    if ($truncated);
239		# store the open filehandle in $attr_data
240		if (!$attr_data) {
241		    open($attr_data, "$file_data.$attrid", ">")
242			or die("open: $!");
243		}
244		print $attr_data $data;
245		if ($eoa) {
246		    close($attr_data);
247		}
248		return $attr_data;
249	    },
250	);
251    }
252
253=cut
254
255
256%}
257