Re: symlinks in Archive::Tar?
by Aristotle (Chancellor) on Feb 19, 2003 at 22:48 UTC
|
| [reply] |
|
|
| [reply] |
|
|
It actually took me a while to work this out -- very educational, and I'm glad to have learned it. A simple, bone-head example that should show the way (tested on linux, with perl 5.8.0):
#!/usr/bin/perl
use strict;
use Archive::Tar;
# begin by creating a test directory to tar up:
BEGIN {
mkdir "test_dir",0755;
for my $i ( 1 .. 3 ) {
open( TEST, ">test_dir/test$i.txt" );
print TEST "This is test data file number $i\n";
close TEST;
symlink "test$i.txt", "test_dir/test$i.lnk" unless ( $i % 2 );
}
}
my $tar = Archive::Tar->new();
opendir( DIR, "test_dir" ) or die $!;
my @files = grep /\w/, readdir DIR;
foreach my $f ( @files )
{
next unless ( $f =~ /test2/ ); # just for the sake of being select
+ive
# UPDATE: this doesn't actually work as hoped for:
# if ( -l "test_dir/$f" )
# { # it's a symlink!!
# my $targ_path = readlink "test_dir/$f";
# my %opt_hash = ( linkname => $targ_path );
# $tar->add_data( "test_dir/$f", '', \%opt_hash ) or
# die "failed to add $f: $!\n";
# }
# else
# { # it's just a plain file
#
# BUT: this actually does what the OP wants, and seems to
# disagree with heezy's findings:
$tar->add_files( "test_dir/$f" ) or die "failed to add $f: $!\n";
# }
}
$tar->write( "test_dir.tar", 0 ) or die "failed to write tar file: $!\
+n";
# let's end with a report of how we did
END {
my $report = `tar tvf test_dir.tar`;
print $report;
}
For me, though, the most typical case is having to make sure that I don't create tar sets that contain symlinks whose targets happen not to be contained elsewhere in the same tar set... But I presume you have that issue covered in your case.
comment on updated code: My initial post had a dumb mistake, doing (-l $f) instead of (-l "test_dir/$f") in the portion that was commented out by the update -- that is, after it produced the desired result, I looked closer and realized that it shouldn't have worked. It wasn't till I took out all the conditional stuff and just used the "add_files()" method on each iteration, that I got the desired result again. Seems like that stuff in the Archive::Tar man page about the "linkname" option for "add_data()" is just bunk. | [reply] [d/l] [select] |
Re: symlinks in Archive::Tar?
by submersible_toaster (Chaplain) on Feb 20, 2003 at 03:27 UTC
|
Some cursory source scanning reveals this module should carp if
it is unable to read symlinks. And the author notes in the CPAN POD that several bugs
with symlinks have been 'fixed' without specifying what exactly was the problem. It seems
Archive::Tar is an perl implementation rather than a wrapper around tar , as such maybe its not surprising that some
features are missing, though I would call this a pretty serious one.
Talking out of my hat , the case may be that when putting the symlink entry into the tarfile,
the symlink is opened and sysread ... which I guess depending on the underlying IO layer - would be reading the contents
of the linked file.
Update: heezy Can you update your Archive::Tar , 0.07 is way down
the list of revisions to this module, the symlink problem I speak of above is listed in the revisions for 0.07 but
the most current version is 0.23
I can't believe it's not psellchecked
| [reply] |
Re: symlinks in Archive::Tar?
by steves (Curate) on Feb 20, 2003 at 08:53 UTC
|
This works for me as expected on Solaris using Archive::Tar version 0.22. The only odd thing is that the last file name sometimes does not show when I run GNU tar from the command line. But when I extract using either GNU tar or Archive::Tar, symlinks come out named as they were put in and linked to whatever they were linked to when they went in, and no files are missing. The only thing is, if I unpack in a directory where the files linked to do not exist, I get symlinks that point to nothing -- but that's the same behavior as GNU tar. I put debug in and it's doing what I'd expect when it finds symlinks.
Maybe upgrade for starters and post some more complete code samples if you still have problems?
| [reply] |
Re: symlinks in Archive::Tar?
by Tomte (Priest) on Feb 19, 2003 at 21:17 UTC
|
A quick search on CPAN revealed no results.
You can use standard tar -cfv from perl via system or backticks to create the archive, while having tight control on which files to add.
tars -r switch might be of interest to you in this case.
regards,
tomte
| [reply] |
Re: symlinks in Archive::Tar?
by heezy (Monk) on Feb 19, 2003 at 21:24 UTC
|
here's a bit more info...
Basically I have a directory of around 15,000 files. Some of these files get updated each day. I have writen a PERL script that check sums all the files and works out what has changed each night.
I then want to take these updated files (where the file names are stored in an arrary) and tar them up so they can be pushed onto my companies website.
As the symlink thingy doesn't work at the moment I currently have to tar up all 15,000 files each day as I must maintain the symlinks
hth
| [reply] |
Re: symlinks in Archive::Tar?
by steves (Curate) on Feb 19, 2003 at 21:30 UTC
|
Don't you have to add the symlink to the archive -- not what it's linked to? i.e., what happens when you try this:
tar->add_files("/webroot/service/servicelist/ss/rasprofile-fr-eng.pdf"
+);
I believe it needs to see that symlink file mode setting for it to even try. Looking at the code, it should work, but I'm not convinced it will work for relative paths (not an issue here).
| [reply] [d/l] |
|
|
Apologies, I should of been clearer, I actually do exactally what you said already, I just shortend the paths to improve the look & feel on perl monks and forgot to shorten one of them in my original question.
All files are indeed under the path:
/webroot/service/servicelist/ss/
I am adding the symlink name and not the file to the archive already as...
tar->add_files("/webroot/service/servicelist/ss/rasprofile-fr-eng.pdf"
+);
Sorry for the confusion, there is actually no file at...
/webroot/rasprofile-fr-eng.pdf
| [reply] [d/l] [select] |
|
|
Okay ... so where is the real file the symlink points to (what directory)? And do you get any errors at all? Looking at the code I see attempts to symlink if the file being extracted has a file mode setting indicating it's a symbolic link. There's a warning if that fails. Can you easily check the file mode settings and see if the file that ends up in the archive has the symlink bit set?
Looking at the code, I can see they do (on UNIX) a -l check when the file is added; set a SYMLINK file type and save the file its linked to if that's set; then try to call symlink if they see the SYMLINK entry type during extraction using the saved values. The reason I think you'll have problems with relative path names is that I don't see any path information being stored with the link name ... not sure if that matters if it's relative since you'd want it relative on the way out? I'd need to see what directory they think they're in though ...
If you have access to the source and can modify it I'd probably just copy it and put some debug in there. It may make it very clear with a smaller amount of effort than debugging around the module.
| [reply] |