Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

394 lines
9.0 KiB

  1. package File::Spec::Mac;
  2. use strict;
  3. use vars qw(@ISA $VERSION);
  4. require File::Spec::Unix;
  5. $VERSION = '1.2';
  6. @ISA = qw(File::Spec::Unix);
  7. =head1 NAME
  8. File::Spec::Mac - File::Spec for MacOS
  9. =head1 SYNOPSIS
  10. require File::Spec::Mac; # Done internally by File::Spec if needed
  11. =head1 DESCRIPTION
  12. Methods for manipulating file specifications.
  13. =head1 METHODS
  14. =over 2
  15. =item canonpath
  16. On MacOS, there's nothing to be done. Returns what it's given.
  17. =cut
  18. sub canonpath {
  19. my ($self,$path) = @_;
  20. return $path;
  21. }
  22. =item catdir
  23. Concatenate two or more directory names to form a complete path ending with
  24. a directory. Put a trailing : on the end of the complete path if there
  25. isn't one, because that's what's done in MacPerl's environment.
  26. The fundamental requirement of this routine is that
  27. File::Spec->catdir(split(":",$path)) eq $path
  28. But because of the nature of Macintosh paths, some additional
  29. possibilities are allowed to make using this routine give reasonable results
  30. for some common situations. Here are the rules that are used. Each
  31. argument has its trailing ":" removed. Each argument, except the first,
  32. has its leading ":" removed. They are then joined together by a ":".
  33. So
  34. File::Spec->catdir("a","b") = "a:b:"
  35. File::Spec->catdir("a:",":b") = "a:b:"
  36. File::Spec->catdir("a:","b") = "a:b:"
  37. File::Spec->catdir("a",":b") = "a:b"
  38. File::Spec->catdir("a","","b") = "a::b"
  39. etc.
  40. To get a relative path (one beginning with :), begin the first argument with :
  41. or put a "" as the first argument.
  42. If you don't want to worry about these rules, never allow a ":" on the ends
  43. of any of the arguments except at the beginning of the first.
  44. Under MacPerl, there is an additional ambiguity. Does the user intend that
  45. File::Spec->catfile("LWP","Protocol","http.pm")
  46. be relative or absolute? There's no way of telling except by checking for the
  47. existence of LWP: or :LWP, and even there he may mean a dismounted volume or
  48. a relative path in a different directory (like in @INC). So those checks
  49. aren't done here. This routine will treat this as absolute.
  50. =cut
  51. sub catdir {
  52. shift;
  53. my @args = @_;
  54. my $result = shift @args;
  55. $result =~ s/:\Z(?!\n)//;
  56. foreach (@args) {
  57. s/:\Z(?!\n)//;
  58. s/^://s;
  59. $result .= ":$_";
  60. }
  61. return "$result:";
  62. }
  63. =item catfile
  64. Concatenate one or more directory names and a filename to form a
  65. complete path ending with a filename. Since this uses catdir, the
  66. same caveats apply. Note that the leading : is removed from the filename,
  67. so that
  68. File::Spec->catfile($ENV{HOME},"file");
  69. and
  70. File::Spec->catfile($ENV{HOME},":file");
  71. give the same answer, as one might expect.
  72. =cut
  73. sub catfile {
  74. my $self = shift;
  75. my $file = pop @_;
  76. return $file unless @_;
  77. my $dir = $self->catdir(@_);
  78. $file =~ s/^://s;
  79. return $dir.$file;
  80. }
  81. =item curdir
  82. Returns a string representing the current directory.
  83. =cut
  84. sub curdir {
  85. return ":";
  86. }
  87. =item devnull
  88. Returns a string representing the null device.
  89. =cut
  90. sub devnull {
  91. return "Dev:Null";
  92. }
  93. =item rootdir
  94. Returns a string representing the root directory. Under MacPerl,
  95. returns the name of the startup volume, since that's the closest in
  96. concept, although other volumes aren't rooted there.
  97. =cut
  98. sub rootdir {
  99. #
  100. # There's no real root directory on MacOS. The name of the startup
  101. # volume is returned, since that's the closest in concept.
  102. #
  103. require Mac::Files;
  104. my $system = Mac::Files::FindFolder(&Mac::Files::kOnSystemDisk,
  105. &Mac::Files::kSystemFolderType);
  106. $system =~ s/:.*\Z(?!\n)/:/s;
  107. return $system;
  108. }
  109. =item tmpdir
  110. Returns a string representation of the first existing directory
  111. from the following list or '' if none exist:
  112. $ENV{TMPDIR}
  113. =cut
  114. my $tmpdir;
  115. sub tmpdir {
  116. return $tmpdir if defined $tmpdir;
  117. $tmpdir = $ENV{TMPDIR} if -d $ENV{TMPDIR};
  118. $tmpdir = '' unless defined $tmpdir;
  119. return $tmpdir;
  120. }
  121. =item updir
  122. Returns a string representing the parent directory.
  123. =cut
  124. sub updir {
  125. return "::";
  126. }
  127. =item file_name_is_absolute
  128. Takes as argument a path and returns true, if it is an absolute path. In
  129. the case where a name can be either relative or absolute (for example, a
  130. folder named "HD" in the current working directory on a drive named "HD"),
  131. relative wins. Use ":" in the appropriate place in the path if you want to
  132. distinguish unambiguously.
  133. As a special case, the file name '' is always considered to be absolute.
  134. =cut
  135. sub file_name_is_absolute {
  136. my ($self,$file) = @_;
  137. if ($file =~ /:/) {
  138. return ($file !~ m/^:/s);
  139. } elsif ( $file eq '' ) {
  140. return 1 ;
  141. } else {
  142. return (! -e ":$file");
  143. }
  144. }
  145. =item path
  146. Returns the null list for the MacPerl application, since the concept is
  147. usually meaningless under MacOS. But if you're using the MacPerl tool under
  148. MPW, it gives back $ENV{Commands} suitably split, as is done in
  149. :lib:ExtUtils:MM_Mac.pm.
  150. =cut
  151. sub path {
  152. #
  153. # The concept is meaningless under the MacPerl application.
  154. # Under MPW, it has a meaning.
  155. #
  156. return unless exists $ENV{Commands};
  157. return split(/,/, $ENV{Commands});
  158. }
  159. =item splitpath
  160. =cut
  161. sub splitpath {
  162. my ($self,$path, $nofile) = @_;
  163. my ($volume,$directory,$file) = ('','','');
  164. if ( $nofile ) {
  165. ( $volume, $directory ) = $path =~ m@((?:[^:]+(?::|\Z(?!\n)))?)(.*)@s;
  166. }
  167. else {
  168. $path =~
  169. m@^( (?: [^:]+: )? )
  170. ( (?: .*: )? )
  171. ( .* )
  172. @xs;
  173. $volume = $1;
  174. $directory = $2;
  175. $file = $3;
  176. }
  177. # Make sure non-empty volumes and directories end in ':'
  178. $volume .= ':' if $volume =~ m@[^:]\Z(?!\n)@ ;
  179. $directory .= ':' if $directory =~ m@[^:]\Z(?!\n)@ ;
  180. return ($volume,$directory,$file);
  181. }
  182. =item splitdir
  183. =cut
  184. sub splitdir {
  185. my ($self,$directories) = @_ ;
  186. #
  187. # split() likes to forget about trailing null fields, so here we
  188. # check to be sure that there will not be any before handling the
  189. # simple case.
  190. #
  191. if ( $directories !~ m@:\Z(?!\n)@ ) {
  192. return split( m@:@, $directories );
  193. }
  194. else {
  195. #
  196. # since there was a trailing separator, add a file name to the end,
  197. # then do the split, then replace it with ''.
  198. #
  199. my( @directories )= split( m@:@, "${directories}dummy" ) ;
  200. $directories[ $#directories ]= '' ;
  201. return @directories ;
  202. }
  203. }
  204. =item catpath
  205. =cut
  206. sub catpath {
  207. my $self = shift ;
  208. my $result = shift ;
  209. $result =~ s@^([^/])@/$1@s ;
  210. my $segment ;
  211. for $segment ( @_ ) {
  212. if ( $result =~ m@[^/]\Z(?!\n)@ && $segment =~ m@^[^/]@s ) {
  213. $result .= "/$segment" ;
  214. }
  215. elsif ( $result =~ m@/\Z(?!\n)@ && $segment =~ m@^/@s ) {
  216. $result =~ s@/+\Z(?!\n)@/@;
  217. $segment =~ s@^/+@@s;
  218. $result .= "$segment" ;
  219. }
  220. else {
  221. $result .= $segment ;
  222. }
  223. }
  224. return $result ;
  225. }
  226. =item abs2rel
  227. See L<File::Spec::Unix/abs2rel> for general documentation.
  228. Unlike C<File::Spec::Unix->abs2rel()>, this function will make
  229. checks against the local filesystem if necessary. See
  230. L</file_name_is_absolute> for details.
  231. =cut
  232. sub abs2rel {
  233. my($self,$path,$base) = @_;
  234. # Clean up $path
  235. if ( ! $self->file_name_is_absolute( $path ) ) {
  236. $path = $self->rel2abs( $path ) ;
  237. }
  238. # Figure out the effective $base and clean it up.
  239. if ( !defined( $base ) || $base eq '' ) {
  240. $base = cwd() ;
  241. }
  242. elsif ( ! $self->file_name_is_absolute( $base ) ) {
  243. $base = $self->rel2abs( $base ) ;
  244. }
  245. # Now, remove all leading components that are the same
  246. my @pathchunks = $self->splitdir( $path );
  247. my @basechunks = $self->splitdir( $base );
  248. while (@pathchunks && @basechunks && $pathchunks[0] eq $basechunks[0]) {
  249. shift @pathchunks ;
  250. shift @basechunks ;
  251. }
  252. $path = join( ':', @pathchunks );
  253. # @basechunks now contains the number of directories to climb out of.
  254. $base = ':' x @basechunks ;
  255. return "$base:$path" ;
  256. }
  257. =item rel2abs
  258. See L<File::Spec::Unix/rel2abs> for general documentation.
  259. Unlike C<File::Spec::Unix->rel2abs()>, this function will make
  260. checks against the local filesystem if necessary. See
  261. L</file_name_is_absolute> for details.
  262. =cut
  263. sub rel2abs {
  264. my ($self,$path,$base ) = @_;
  265. if ( ! $self->file_name_is_absolute( $path ) ) {
  266. if ( !defined( $base ) || $base eq '' ) {
  267. $base = cwd() ;
  268. }
  269. elsif ( ! $self->file_name_is_absolute( $base ) ) {
  270. $base = $self->rel2abs( $base ) ;
  271. }
  272. else {
  273. $base = $self->canonpath( $base ) ;
  274. }
  275. $path = $self->canonpath("$base$path") ;
  276. }
  277. return $path ;
  278. }
  279. =back
  280. =head1 SEE ALSO
  281. L<File::Spec>
  282. =cut
  283. 1;