home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / share / perl / 5.8.8 / File / Spec / Unix.pm < prev    next >
Encoding:
Perl POD Document  |  2006-07-07  |  6.7 KB  |  260 lines

  1. package File::Spec::Unix;
  2.  
  3. use strict;
  4. use vars qw($VERSION);
  5.  
  6. $VERSION = '1.5';
  7.  
  8. sub canonpath {
  9.     my ($self,$path) = @_;
  10.     
  11.     # Handle POSIX-style node names beginning with double slash (qnx, nto)
  12.     # Handle network path names beginning with double slash (cygwin)
  13.     # (POSIX says: "a pathname that begins with two successive slashes
  14.     # may be interpreted in an implementation-defined manner, although
  15.     # more than two leading slashes shall be treated as a single slash.")
  16.     my $node = '';
  17.     if ( $^O =~ m/^(?:qnx|nto|cygwin)$/ && $path =~ s:^(//[^/]+)(/|\z):/:s ) {
  18.       $node = $1;
  19.     }
  20.     # This used to be
  21.     # $path =~ s|/+|/|g unless($^O eq 'cygwin');
  22.     # but that made tests 29, 30, 35, 46, and 213 (as of #13272) to fail
  23.     # (Mainly because trailing "" directories didn't get stripped).
  24.     # Why would cygwin avoid collapsing multiple slashes into one? --jhi
  25.     $path =~ s|/+|/|g;                             # xx////xx  -> xx/xx
  26.     $path =~ s@(/\.)+(/|\Z(?!\n))@/@g;             # xx/././xx -> xx/xx
  27.     $path =~ s|^(\./)+||s unless $path eq "./";    # ./xx      -> xx
  28.     $path =~ s|^/(\.\./)+|/|;                      # /../../xx -> xx
  29.     $path =~ s|^/\.\.$|/|;                         # /..       -> /
  30.     $path =~ s|/\Z(?!\n)|| unless $path eq "/";          # xx/       -> xx
  31.     return "$node$path";
  32. }
  33.  
  34. sub catdir {
  35.     my $self = shift;
  36.  
  37.     $self->canonpath(join('/', @_, '')); # '' because need a trailing '/'
  38. }
  39.  
  40. sub catfile {
  41.     my $self = shift;
  42.     my $file = $self->canonpath(pop @_);
  43.     return $file unless @_;
  44.     my $dir = $self->catdir(@_);
  45.     $dir .= "/" unless substr($dir,-1) eq "/";
  46.     return $dir.$file;
  47. }
  48.  
  49. sub curdir () { '.' }
  50.  
  51. sub devnull () { '/dev/null' }
  52.  
  53. sub rootdir () { '/' }
  54.  
  55. my $tmpdir;
  56. sub _tmpdir {
  57.     return $tmpdir if defined $tmpdir;
  58.     my $self = shift;
  59.     my @dirlist = @_;
  60.     {
  61.     no strict 'refs';
  62.     if (${"\cTAINT"}) { # Check for taint mode on perl >= 5.8.0
  63.             require Scalar::Util;
  64.         @dirlist = grep { ! Scalar::Util::tainted($_) } @dirlist;
  65.     }
  66.     }
  67.     foreach (@dirlist) {
  68.     next unless defined && -d && -w _;
  69.     $tmpdir = $_;
  70.     last;
  71.     }
  72.     $tmpdir = $self->curdir unless defined $tmpdir;
  73.     $tmpdir = defined $tmpdir && $self->canonpath($tmpdir);
  74.     return $tmpdir;
  75. }
  76.  
  77. sub tmpdir {
  78.     return $tmpdir if defined $tmpdir;
  79.     $tmpdir = $_[0]->_tmpdir( $ENV{TMPDIR}, "/tmp" );
  80. }
  81.  
  82. sub updir () { '..' }
  83.  
  84. sub no_upwards {
  85.     my $self = shift;
  86.     return grep(!/^\.{1,2}\Z(?!\n)/s, @_);
  87. }
  88.  
  89. sub case_tolerant () { 0 }
  90.  
  91. sub file_name_is_absolute {
  92.     my ($self,$file) = @_;
  93.     return scalar($file =~ m:^/:s);
  94. }
  95.  
  96. sub path {
  97.     return () unless exists $ENV{PATH};
  98.     my @path = split(':', $ENV{PATH});
  99.     foreach (@path) { $_ = '.' if $_ eq '' }
  100.     return @path;
  101. }
  102.  
  103. sub join {
  104.     my $self = shift;
  105.     return $self->catfile(@_);
  106. }
  107.  
  108. sub splitpath {
  109.     my ($self,$path, $nofile) = @_;
  110.  
  111.     my ($volume,$directory,$file) = ('','','');
  112.  
  113.     if ( $nofile ) {
  114.         $directory = $path;
  115.     }
  116.     else {
  117.         $path =~ m|^ ( (?: .* / (?: \.\.?\Z(?!\n) )? )? ) ([^/]*) |xs;
  118.         $directory = $1;
  119.         $file      = $2;
  120.     }
  121.  
  122.     return ($volume,$directory,$file);
  123. }
  124.  
  125. sub splitdir {
  126.     return split m|/|, $_[1], -1;  # Preserve trailing fields
  127. }
  128.  
  129. sub catpath {
  130.     my ($self,$volume,$directory,$file) = @_;
  131.  
  132.     if ( $directory ne ''                && 
  133.          $file ne ''                     && 
  134.          substr( $directory, -1 ) ne '/' && 
  135.          substr( $file, 0, 1 ) ne '/' 
  136.     ) {
  137.         $directory .= "/$file" ;
  138.     }
  139.     else {
  140.         $directory .= $file ;
  141.     }
  142.  
  143.     return $directory ;
  144. }
  145.  
  146. sub abs2rel {
  147.     my($self,$path,$base) = @_;
  148.  
  149.     # Clean up $path
  150.     if ( ! $self->file_name_is_absolute( $path ) ) {
  151.         $path = $self->rel2abs( $path ) ;
  152.     }
  153.     else {
  154.         $path = $self->canonpath( $path ) ;
  155.     }
  156.  
  157.     # Figure out the effective $base and clean it up.
  158.     if ( !defined( $base ) || $base eq '' ) {
  159.         $base = $self->_cwd();
  160.     }
  161.     elsif ( ! $self->file_name_is_absolute( $base ) ) {
  162.         $base = $self->rel2abs( $base ) ;
  163.     }
  164.     else {
  165.         $base = $self->canonpath( $base ) ;
  166.     }
  167.  
  168.     # Now, remove all leading components that are the same
  169.     my @pathchunks = $self->splitdir( $path);
  170.     my @basechunks = $self->splitdir( $base);
  171.  
  172.     while (@pathchunks && @basechunks && $pathchunks[0] eq $basechunks[0]) {
  173.         shift @pathchunks ;
  174.         shift @basechunks ;
  175.     }
  176.  
  177.     $path = CORE::join( '/', @pathchunks );
  178.     $base = CORE::join( '/', @basechunks );
  179.  
  180.     # $base now contains the directories the resulting relative path 
  181.     # must ascend out of before it can descend to $path_directory.  So, 
  182.     # replace all names with $parentDir
  183.     $base =~ s|[^/]+|..|g ;
  184.  
  185.     # Glue the two together, using a separator if necessary, and preventing an
  186.     # empty result.
  187.     if ( $path ne '' && $base ne '' ) {
  188.         $path = "$base/$path" ;
  189.     } else {
  190.         $path = "$base$path" ;
  191.     }
  192.  
  193.     return $self->canonpath( $path ) ;
  194. }
  195.  
  196. sub rel2abs {
  197.     my ($self,$path,$base ) = @_;
  198.  
  199.     # Clean up $path
  200.     if ( ! $self->file_name_is_absolute( $path ) ) {
  201.         # Figure out the effective $base and clean it up.
  202.         if ( !defined( $base ) || $base eq '' ) {
  203.         $base = $self->_cwd();
  204.         }
  205.         elsif ( ! $self->file_name_is_absolute( $base ) ) {
  206.             $base = $self->rel2abs( $base ) ;
  207.         }
  208.         else {
  209.             $base = $self->canonpath( $base ) ;
  210.         }
  211.  
  212.         # Glom them together
  213.         $path = $self->catdir( $base, $path ) ;
  214.     }
  215.  
  216.     return $self->canonpath( $path ) ;
  217. }
  218.  
  219. # Internal routine to File::Spec, no point in making this public since
  220. # it is the standard Cwd interface.  Most of the platform-specific
  221. # File::Spec subclasses use this.
  222. sub _cwd {
  223.     require Cwd;
  224.     Cwd::cwd();
  225. }
  226.  
  227. # Internal method to reduce xx\..\yy -> yy
  228. sub _collapse {
  229.     my($fs, $path) = @_;
  230.  
  231.     my $updir  = $fs->updir;
  232.     my $curdir = $fs->curdir;
  233.  
  234.     my($vol, $dirs, $file) = $fs->splitpath($path);
  235.     my @dirs = $fs->splitdir($dirs);
  236.  
  237.     my @collapsed;
  238.     foreach my $dir (@dirs) {
  239.         if( $dir eq $updir              and   # if we have an updir
  240.             @collapsed                  and   # and something to collapse
  241.             length $collapsed[-1]       and   # and its not the rootdir
  242.             $collapsed[-1] ne $updir    and   # nor another updir
  243.             $collapsed[-1] ne $curdir         # nor the curdir
  244.           ) 
  245.         {                                     # then
  246.             pop @collapsed;                   # collapse
  247.         }
  248.         else {                                # else
  249.             push @collapsed, $dir;            # just hang onto it
  250.         }
  251.     }
  252.  
  253.     return $fs->catpath($vol,
  254.                         $fs->catdir(@collapsed),
  255.                         $file
  256.                        );
  257. }
  258.  
  259. 1;
  260.