Sysdeftools additional support for merging misordered system definitions. More extensive validation. Minor bug fixes. Bash wrappers for perl scripts for unix installs.
# Copyright (c) 2000 Ned Konz. All rights reserved. This program is free
# software; you can redistribute it and/or modify it under the same terms
# as Perl itself.
# $Revision: 1.5 $
package Archive::Zip::Archive;
use File::Find ();
use Archive::Zip qw(:ERROR_CODES :UTILITY_METHODS);
=head1 NAME
Archive::Zip::Tree -- methods for adding/extracting trees using Archive::Zip
=head1 SYNOPSIS
use Archive::Zip;
use Archive::Zip::Tree;
my $zip = Archive::Zip->new();
# add all readable files and directories below . as xyz/*
$zip->addTree( '.', 'xyz' );
# add all readable plain files below /abc as /def/*
$zip->addTree( '/abc', '/def', sub { -f && -r } );
# add all .c files below /tmp as stuff/*
$zip->addTreeMatching( '/tmp', 'stuff', '\.c$' );
# add all .o files below /tmp as stuff/* if they aren't writable
$zip->addTreeMatching( '/tmp', 'stuff', '\.o$', sub { ! -w } );
# and write them into a file
$zip->writeToFile('xxx.zip');
# now extract the same files into /tmpx
$zip->extractTree( 'stuff', '/tmpx' );
=head1 METHODS
=over 4
=item $zip->addTree( $root, $dest [,$pred] )
$root is the root of the tree of files and directories to be added
$dest is the name for the root in the zip file (undef or blank means to use
relative pathnames)
C<$pred> is an optional subroutine reference to select files: it is passed the
name of the prospective file or directory using C<$_>,
and if it returns true, the file or
directory will be included. The default is to add all readable files and
directories.
For instance, using
my $pred = sub { /\.txt/ };
$zip->addTree( '.', '.', $pred );
will add all the .txt files in and below the current directory,
using relative names, and making the names identical in the zipfile:
original name zip member name
./xyz xyz
./a/ a/
./a/b a/b
To use absolute pathnames, just pass them in:
$zip->addTree( '/a/b', '/a/b' );
original name zip member name
/a/ /a/
/a/b /a/b
To translate relative to absolute pathnames, just pass them in:
$zip->addTree( '.', '/c/d' );
original name zip member name
./xyz /c/d/xyz
./a/ /c/d/a/
./a/b /c/d/a/b
To translate absolute to relative pathnames, just pass them in:
$zip->addTree( '/c/d', 'a' );
original name zip member name
/c/d/xyz a/xyz
/c/d/a/ a/a/
/c/d/a/b a/a/b
Returns AZ_OK on success.
Note that this will not follow symbolic links to directories.
Note also that this does not check for the validity of filenames.
=back
=cut
sub addTree
{
my $self = shift;
my $root = shift or return _error("root arg missing in call to addTree()");
my $dest = shift || '';
my $pred = shift || sub { -r };
$root =~ s{\\}{/}g; # normalize backslashes in case user is misguided
$root =~ s{([^/])$}{$1/}; # append slash if necessary
$dest =~ s{([^/])$}{$1/} if $dest; # append slash if necessary
my @files;
File::Find::find( sub { push( @files, $File::Find::name ) }, $root );
@files = grep { &$pred } @files; # pass arg via local $_
foreach my $fileName ( @files )
{
( my $archiveName = $fileName ) =~ s{^\Q$root}{$dest};
$archiveName =~ s{^\./}{};
next if $archiveName =~ m{^\.?/?$}; # skip current dir
my $member = ( -d $fileName )
? $self->addDirectory( $fileName, $archiveName )
: $self->addFile( $fileName, $archiveName );
return _error( "add $fileName failed in addTree()" ) if !$member;
}
return AZ_OK;
}
=over 4
=item $zip->addTreeMatching( $root, $dest, $pattern [,$pred] )
$root is the root of the tree of files and directories to be added
$dest is the name for the root in the zip file (undef means to use relative
pathnames)
$pattern is a (non-anchored) regular expression for filenames to match
$pred is an optional subroutine reference to select files: it is passed the
name of the prospective file or directory in C<$_>,
and if it returns true, the file or
directory will be included. The default is to add all readable files and
directories.
To add all files in and below the current dirctory
whose names end in C<.pl>, and make them extract into a subdirectory
named C<xyz>, do this:
$zip->addTreeMatching( '.', 'xyz', '\.pl$' )
To add all I<writable> files in and below the dirctory named C</abc>
whose names end in C<.pl>, and make them extract into a subdirectory
named C<xyz>, do this:
$zip->addTreeMatching( '/abc', 'xyz', '\.pl$', sub { -w } )
Returns AZ_OK on success.
Note that this will not follow symbolic links to directories.
=back
=cut
sub addTreeMatching
{
my $self = shift;
my $root = shift
or return _error("root arg missing in call to addTreeMatching()");
my $dest = shift || '';
my $pattern = shift
or return _error("pattern missing in call to addTreeMatching()");
my $pred = shift || sub { -r };
my $matcher = sub { m{$pattern} && &$pred };
return $self->addTree( $root, $dest, $matcher );
}
=over 4
=item $zip->extractTree( $root, $dest )
Extracts all the members below a given root. Will
translate that root to a given dest pathname.
For instance,
$zip->extractTree( '/a/', 'd/e/' );
when applied to a zip containing the files:
/a/x /a/b/c /d/e
will extract:
/a/x to d/e/x
/a/b/c to d/e/b/c
and ignore /d/e
=back
=cut
sub extractTree
{
my $self = shift();
my $root = shift();
return _error("root arg missing in call to extractTree()")
unless defined($root);
my $dest = shift || '.';
$root =~ s{\\}{/}g; # normalize backslashes in case user is misguided
$root =~ s{([^/])$}{$1/}; # append slash if necessary
my @members = $self->membersMatching( "^$root" );
foreach my $member ( @members )
{
my $fileName = $member->fileName();
$fileName =~ s{$root}{$dest};
my $status = $member->extractToFileNamed( $fileName );
return $status if $status != AZ_OK;
}
return AZ_OK;
}
1;
__END__
=head1 AUTHOR
Ned Konz, perl@bike-nomad.com
=head1 COPYRIGHT
Copyright (c) 2000 Ned Konz. All rights reserved. This program is free
software; you can redistribute it and/or modify it under the same terms
as Perl itself.
=head1 SEE ALSO
L<Compress::Zlib>
L<Archive::Zip>
=cut
# vim: ts=4 sw=4 columns=80