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

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