--- a/UnixOperatingSystem.st Wed Aug 21 16:57:08 2019 +0200
+++ b/UnixOperatingSystem.st Wed Aug 21 16:58:46 2019 +0200
@@ -5670,71 +5670,71 @@
This method needs the path to be valid
(i.e. all directories must exist, be readable and executable).
Notice: if symbolic links are involved, the result may look different
- from what you expect."
+ from what you expect (i.e. the path will be expanded)."
|p path command|
pathName = '.' ifTrue:[
- ^ self getCurrentDirectory.
+ ^ self getCurrentDirectory.
].
"some systems have a convenient function for this ..."
path := self primPathNameOf:(self encodePath:pathName).
path notNil ifTrue:[
- path := self decodePath:path.
- ] ifFalse:[
- (self isValidPath:pathName) ifFalse:[
- p := pathName.
- [(p size > 1)
- and:[p endsWith:(self fileSeparator)]
- ] whileTrue:[
- p := p copyButLast.
- ].
- ^ p
- ].
-
- (SlowFork==true or:[PipeFailed==true]) ifFalse:[
- |directoryName fileBaseName|
-
- (self isDirectory:pathName) ifTrue:[
- directoryName := pathName.
- fileBaseName := nil.
- ] ifFalse:[
- |pathFilename|
- pathFilename := pathName asFilename.
- directoryName := pathFilename directoryName.
- fileBaseName := pathFilename baseName.
- ].
-
- PipeStream openErrorSignal handle:[:ex |
- PipeFailed := true.
- 'UnixOperatingSystem [warning]: cannot fork/popen' errorPrintCR.
- ex return.
- ] do:[
- "have to fall back ..."
- command := 'cd "' , directoryName , '"; pwd'.
- p := PipeStream readingFrom:command.
- ].
-
- (p isNil or:[p atEnd]) ifTrue:[
- ('UnixOperatingSystem [warning]: PipeStream for <' , command , '> failed') errorPrintCR.
- ] ifFalse:[
- path := p nextLine.
- p close.
- ].
- fileBaseName notNil ifTrue:[
- path := path, '/', fileBaseName.
- ].
- ].
- path isNil ifTrue:[
- "/
- "/ return the original - there is nothing else can we do
- "/
- path := pathName
- ].
- (SlowFork==true or:[ForkFailed==true]) ifTrue:[
- path := self compressPath:path
- ]
+ ^ self decodePath:path.
+ ].
+
+ (self isValidPath:pathName) ifFalse:[
+ p := pathName.
+ [(p size > 1)
+ and:[p endsWith:(self fileSeparator)]
+ ] whileTrue:[
+ p := p copyButLast.
+ ].
+ ^ p
+ ].
+
+ (SlowFork==true or:[PipeFailed==true]) ifFalse:[
+ |directoryName fileBaseName|
+
+ (self isDirectory:pathName) ifTrue:[
+ directoryName := pathName.
+ fileBaseName := nil.
+ ] ifFalse:[
+ |pathFilename|
+ pathFilename := pathName asFilename.
+ directoryName := pathFilename directoryName.
+ fileBaseName := pathFilename baseName.
+ ].
+
+ PipeStream openErrorSignal handle:[:ex |
+ PipeFailed := true.
+ 'UnixOperatingSystem [warning]: cannot fork/popen' errorPrintCR.
+ ex return.
+ ] do:[
+ "have to fall back ..."
+ command := 'cd "' , directoryName , '"; pwd'.
+ p := PipeStream readingFrom:command.
+ ].
+
+ (p isNil or:[p atEnd]) ifTrue:[
+ ('UnixOperatingSystem [warning]: PipeStream for <' , command , '> failed') errorPrintCR.
+ ] ifFalse:[
+ path := p nextLine.
+ p close.
+ ].
+ fileBaseName notNil ifTrue:[
+ path := path, '/', fileBaseName.
+ ].
+ ].
+ path isNil ifTrue:[
+ "/
+ "/ return the original - there is nothing else can we do
+ "/
+ path := pathName
+ ].
+ (SlowFork==true or:[ForkFailed==true]) ifTrue:[
+ path := self compressPath:path
].
^ path.
@@ -5754,6 +5754,44 @@
"Modified: / 12-07-2018 / 18:48:57 / Claus Gittinger"
!
+pathNameOfFileOrSymbolicLink:pathName
+ "return the pathName of the argument, aPathString, canonicalized.
+ That's the full pathname of the directory, starting at '/'.
+ In contrast to pathNameOf:file, this does NOT resolve symbolic links.
+ Instead, the realPath of the bottomMost non-symlink is returned,
+ with the rest appended."
+
+ |p pathes idx lastNonSymLink|
+
+ pathName = '.' ifTrue:[
+ ^ self getCurrentDirectory.
+ ].
+ pathes := OrderedCollection new.
+ p := pathName asFilename.
+ [p notNil] whileTrue:[
+ pathes add:p.
+ p isRootDirectory ifTrue:[
+ p := nil
+ ] ifFalse:[
+ p := p directory.
+ ].
+ ].
+ idx := pathes findLast:[:p | p isSymbolicLink].
+ idx == 0 ifTrue:[^ self pathNameOf:pathName ].
+ lastNonSymLink := pathes at:idx+1.
+ ^ lastNonSymLink / (pathName asFilename pathNameRelativeFrom:lastNonSymLink name)
+
+ "here, 'Applications' is a symlink to '/Applications'.
+
+ self primPathNameOf:'/Users/exept/cg_work/exept/expecco/application/expecco_dmg/Applications'
+ self pathNameOfFileOrSymbolicLink:'/Users/exept/cg_work/exept/expecco/application/expecco_dmg/Applications'
+ "
+
+ "Modified: / 29-11-1996 / 18:02:12 / stefan"
+ "Modified: / 05-06-1998 / 18:37:15 / cg"
+ "Modified: / 12-07-2018 / 18:48:57 / Claus Gittinger"
+!
+
primGetCurrentDirectory
"return the raw name of the current directory (nil if failed - can this ever happen?).
Warning:
@@ -5822,50 +5860,59 @@
This method here returns nil, if the OS does not provide a
realPath library function.
Notice: if symbolic links are involved, the result may look different
- from what you expect."
+ from what you expect (i.e. the path will be expanded)."
|error|
%{ /* UNLIMITEDSTACK */
#ifdef __SCHTEAM__
if (pathName.isStringLike()) {
- java.io.File file = new java.io.File( pathName.asString() );
-
- if (file.exists()) {
- return __c__._RETURN( new STString( file.getAbsolutePath() ));
- }
+ java.io.File file = new java.io.File( pathName.asString() );
+
+ if (file.exists()) {
+ return __c__._RETURN( new STString( file.getAbsolutePath() ));
+ }
}
#else
if (__isStringLike(pathName)) {
# ifdef HAS_REALPATH
- extern char *realpath();
-
- // POSIX-2008 says, that a NULL namebuffer causes realPath to malloc()
- // the required memory. But this does not work as of 2013-04
- char nameBuffer[MAXPATHLEN+1];
- char *nameP = realpath(__stringVal(pathName), nameBuffer);
- if (nameP) {
- OBJ ret = __MKSTRING(nameP);
- // free(nameP);
- RETURN ( ret );
- }
- // fprintf(stderr, "stx[warning]: realpath(\"%s\") failed: %s\n", __stringVal(pathName), strerror(errno));
+ extern char *realpath();
+ char *nameP;
+
+ // POSIX-2008 says, that a NULL namebuffer causes realPath to malloc()
+ // the required memory (which we shoudl free).
+ // But this does not work as of 2013-04
+
+# ifdef __osx__ // HAS_REALPATH_WITH_NULL_ARG
+ nameP = realpath(__stringVal(pathName), NULL);
+ if (nameP) {
+ OBJ ret = __MKSTRING(nameP);
+ free(nameP);
+ RETURN ( ret );
+ }
+# else
+ char nameBuffer[MAXPATHLEN+1+1024];
+ nameP = realpath(__stringVal(pathName), nameBuffer);
+ if (nameP) {
+ OBJ ret = __MKSTRING(nameP);
+ // free(nameP);
+ RETURN ( ret );
+ }
+# endif /* ! HAS_REALPATH_WITH_NULL_ARG */
+ // fprintf(stderr, "stx[warning]: realpath(\"%s\") failed: %s\n", __stringVal(pathName), strerror(errno));
# endif /* ! HAS_REALPATH */
} else {
- error = @symbol(argument); // argument is not a string
- }
-#endif
-%}.
-"/ Does not work as of 2013-04 (UNLIMITEDSTACK problem?)
-"/ error notNil ifTrue:[
-"/ ^ self primitiveFailed:error.
-"/ ].
+ error = @symbol(argument); // argument is not a string
+ }
+#endif
+%}.
^ nil
"
- self primPathNameOf:'.'
- self primPathNameOf:'/murks/quatsch/bla/.'
- self primPathNameOf:5555
+ self primPathNameOf:'/Users/exept/cg_work/exept/expecco/application/expecco_dmg/Applications'
+ self primPathNameOf:'.'
+ self primPathNameOf:'/murks/quatsch/bla/.'
+ self primPathNameOf:5555
"
!