#!perl -l use strict; use warnings; use File::Spec; my %seen; # Find the last symlink in the path # Find the absolute path to that symlink # Tack on whatever is after it # squeeze out .. entries sub true_path { my ($path, $base, $stuff_to_tack_on) = @_; $path = File::Spec->rel2abs( $path, $base ) ; #print "*** Checking <$path>"; die "Circular!" if $seen{$path}++; my $last_symlink = ''; my $stuff_after_last_symlink = ''; my $built_path = ''; for my $dir (File::Spec->splitdir($path)) { my $test_path = File::Spec->catdir($built_path, $dir); if (-l $test_path) { #print "Found symlink $test_path"; $base = $built_path; $last_symlink = readlink $test_path; $stuff_after_last_symlink = ''; } else { #print "non-symlink $test_path"; $stuff_after_last_symlink = File::Spec->catdir($stuff_afte +r_last_symlink, $dir); } $built_path = $test_path; } if ($last_symlink ne '') { #print "Symlink=$last_symlink; Base=$base"; true_path($last_symlink, $base, File::Spec->catdir($stuff_afte +r_last_symlink, $stuff_to_tack_on)); } else { # Safe from symlinks, strip out foo/.. my @dirlist = (); for my $dir (File::Spec->splitdir(File::Spec->catdir($built_pa +th, $stuff_to_tack_on))) { if ($dir eq '..') { pop @dirlist } else { push @dirlist, $dir }; } $path = @dirlist ? File::Spec->catdir(@dirlist) : ''; } } s/\s+$//, %seen=(), print "$_\n -->", true_path($_, '', '') while <DAT +A>; __DATA__ /var/log/../../home/poletti/../../etc/passwd . /var/../..
In reply to Re: Cleaning up a path
by Roy Johnson
in thread Cleaning up a path
by polettix
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |