source: trunk/soft/ObsData/ObsData/Archive.pm @ 154

Last change on this file since 154 was 154, checked in by thauvin, 18 years ago
  • add Zip file support
  • Property cvs2svn:cvs-rev set to 1.9
  • Property svn:keywords set to Author Date Id Revision
File size: 3.1 KB
Line 
1# $Id$
2
3package ObsData::Archive;
4
5use strict;
6use warnings;
7use File::Copy;
8use File::Temp qw/ tempfile /;
9use ObsData::Archive::Compressed;
10use ObsData::Archive::Tar;
11use ObsData::Archive::Zip;
12
13our $CVSID = q$Id$;
14our $CVSREV = (q$Revision$ =~ /^Revision: (.*) $/)[0];
15
16my $error = {};
17
18sub new {
19    my ($class, $archive, %options) = @_;
20    my $beclass;
21
22    if (!$archive) {
23        seterror("No archive to read");
24        return undef;
25    }
26    if (!-r $archive) {
27        seterror("No such file or directory");
28        return undef;
29    }
30    my $o;
31   
32    foreach (keys %options) {
33        $o->{$_} = $options{$_};
34    }
35    $o->{archive} = $archive;
36   
37    for ($archive) {
38        /\.tar(\.[^\.]*)?$/ and do {
39            $beclass = 'Tar';
40            last;
41        };
42        /\.(gz|bz2|Z)$/ and do {
43            $beclass = 'Compressed';
44            last;
45        };
46        /\.zip$/ and do {
47            $beclass = 'Zip';
48            last;
49        };
50    }
51   
52    if ($beclass) {
53        my $obj;
54        # eval("require $class\:\:$beclass;");
55        eval("\$obj = $class\:\:$beclass->new(\$o);");
56        return $obj;
57    } else {
58        bless($o, $class);
59    }
60}
61
62sub DESTROY {
63    my ($self) = @_;
64}
65
66sub ls {
67    my ($self) = @_;
68    my ($file) = $self->{archive} =~ m!^(?:.*/)?(.*)!;
69    return $file;
70}
71
72sub extract {
73    my ($self, $file, $dest) = @_;
74    # the devel should specify the file he want
75    # as the basic contains only 1 file... this does not matter
76
77    my ($fh, $fname);
78   
79    if ($dest) {
80        $fname = $dest;
81        if(!open($fh, '>', $dest)) {
82            $error = $!;
83            return undef;
84        }
85    } else {
86        ($fh, $fname) = tempfile(
87            DIR => $self->_tempdir,
88            UNLINK => 1,
89        ) or do {
90            seterror("Can't create tempfile: $!");
91            return undef;
92        };
93    }
94   
95    if(!copy($self->{archive}, $fh)) {
96        unlink($fname);
97        seterror("Cant copy the archive: $!");
98        return undef;
99    }
100   
101    close($fh);
102    $fname
103}
104
105sub error {
106    return $error->{error};
107}
108
109sub seterror {
110    my ($package, $filename, $line) = caller;
111    $error = {
112        'package' => $package,
113        'filename' => $filename,
114        'line' => $line,
115        'error' => $_[1] || $_[0],
116    };
117}
118
119### Private method
120
121sub _tempdir {
122    my ($self) = @_;
123    $self->{tmpdir} || $ENV{TMPDIR}
124}
125
1261;
127
128__END__
129
130=head1 NAME
131
132ObsData::Archive - Transparently extract files from arbitrary archives
133
134=head1 SYNOPSIS
135
136    use ObsData::Archive;
137    my $file = "foo.tar.gz";
138    my $oa = ObsData::Archive->new($file) or die ObsData::Archive->error;
139    my @content = $oa->ls;
140    foreach (@content) {
141        $oa->extract($_, "./$_") or die ObsData::Archive->error;
142    }
143
144=head1 METHODS
145
146=head2 new($file, %options)
147
148Create a new archive object by reading $file.
149
150Return undef on error and set error status.
151See L<error>.
152
153=head2 ls
154
155list the content of the archive
156
157=head2 extract
158
159Extract a file from the archive and return the filename of extract file
160
161=head1 CLASS METHODS
162
163=head2 error
164
165Return the last error encoutered
166
167=head1 AUTHORS
168
169Olivier Thauvin <olivier.thauvin@aerov.jussieu.fr>
170
171=cut
Note: See TracBrowser for help on using the repository browser.