File: realpath.pl

package info (click to toggle)
tct 1.19-1
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 1,916 kB
  • ctags: 1,128
  • sloc: perl: 9,609; ansic: 5,347; makefile: 430; sh: 38
file content (141 lines) | stat: -rw-r--r-- 3,419 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#
#  All code here was taken from File::PathConvert, at:
#
# http://www.oasis.leo.org/perl/exts/filehandling/File-PathConvert.dsc.html
#
#  I ripped out the realpath stuff, made it a normal subroutine instead
# of all that module crap, fixed some spelling, added a one-line cwd
# function (for older perls) and otherwise changed it very slightly.  Thanks
# to Shigio for the code!  Original copyright:
#
# 	Copyright (c) 1996 Shigio Yamaguchi. All rights reserved.
# 	This program is free software; you can redistribute it and/or
#	modify it under the same terms as Perl itself.
#
#				23-Oct-1996 Shigio Yamaguchi
#
#
#  (last mods by zen@fish.com, mar 28, 2000)
#

require "command.pl";

@ISA = qw(Exporter);
@EXPORT_OK = qw(realpath abs2rel rel2abs);

#
# instant configuration
#
$maxsymlinks = 32;		# allowed symlink number in a path
# $debug = 0;			# 1: verbose on, 0: verbose off
$SL = '/';			# separator

#
# realpath: returns the canonicalized absolute path name
#
# Interface:
#	i)	$path	path
#	r)		resolved name on success else undef
#	go)	$resolved
#			resolved name on success else the path name which
#			caused the problem.
	$resolved = '';
#
#	Note: this implementation is based 4.4BSD version realpath(3).
#
sub realpath {
    ($resolved) = @_;
    my($backdir) = &cwd();
    my($dirname, $basename, $links, $reg);

    regularize($resolved);
LOOP:
    {
	#
	# Find the dirname and basename.
	# Change directory to the dirname component.
	#
	if ($resolved =~ /$SL/) {
	    $reg = '^(.*)' . $SL . '([^' . $SL . ']*)$';
	    ($dirname, $basename) = $resolved =~ /$reg/;
	    $dirname = $SL if (!$dirname);
	    $resolved = $dirname;
	    unless (chdir($dirname)) {
		warn("realpath: chdir($dirname) failed.") if $debug;
		chdir($backdir);
		return undef;
	    }
	} else {
	    $dirname = '';
	    $basename = $resolved;
	}
	#
	# If it is a symlink, read in the value and loop.
	# If it is a directory, then change to that directory.
	#
	if ($basename) {
	    if (-l $basename) {
		unless ($resolved = readlink($basename)) {
		    warn("realpath: readlink($basename) failed.") if $debug;
		    chdir($backdir);
		    return undef;
		}
		$basename = '';
		if (++$links > $maxsymlinks) {
		    warn("realpath: too many symbolic links.") if $debug;
		    chdir($backdir);
		    return undef;
		}
		redo LOOP;
	    } elsif (-d _) {
		unless (chdir($basename)) {
		    warn("realpath: chdir($basename) failed.") if $debug;
		    chdir($backdir);
		    return undef;
		}
		$basename = '';
	    }
	}
    }
    #
    # Get the current directory name and append the basename.
    #
    $resolved = &cwd();
    if ($basename) {
	$resolved .= $SL if ($resolved ne $SL);
	$resolved .= $basename
    }
    chdir($backdir);
    return $resolved;
}

#
# regularize a path.
#
sub regularize {
    my($reg);

    $reg = '^' . $SL . '\.\.' . $SL;
    while ($_[0] =~ /$reg/) {           # ^/../ -> /
        $_[0] =~ s/$reg/$SL/;
    }
    $reg = $SL . '\.' . $SL;
    while ($_[0] =~ /$reg/) {
        $_[0] =~ s/$reg/$SL/;           # /./ -> /
    }
    $reg = $SL . '+';
    $_[0] =~ s/$reg/$SL/g;              # ///  -> /
    $reg = '(.+)' . $SL . '$';
    $_[0] =~ s/$reg/$1/;                # remove last /
    $reg = '(.+)' . $SL . '\.$';
    $_[0] =~ s/$reg/$1/g;               # remove last /.
    $_[0] = '/' if $_[0] eq '/.';
}

sub cwd {
$string = &command_to_string($PWD);
chop($string);
return($string);
}

1;