UnixOperatingSystem.st
changeset 14568 ca342ae94cb7
parent 14564 2f373e43fd1a
child 14575 c696ca8d05bd
--- a/UnixOperatingSystem.st	Thu Dec 13 14:19:37 2012 +0100
+++ b/UnixOperatingSystem.st	Thu Dec 13 14:20:12 2012 +0100
@@ -3410,12 +3410,16 @@
      Return true if successful (or the directory existed already), false if failed.
      This is a low-level entry - use Filename protocol for compatibility."
 
-%{
-    if (__isStringLike(aPathName) && __isSmallInteger(umask)) {
-	if (mkdir(__stringVal(aPathName), __smallIntegerVal(umask)) >= 0) {
-	    RETURN(true);
-	}
-	@global(LastErrorNumber) = __mkSmallInteger(errno);
+    |encodedPathName|
+
+    encodedPathName := self encodePath:aPathName.
+
+%{
+    if (__isStringLike(encodedPathName) && __isSmallInteger(umask)) {
+        if (mkdir(__stringVal(encodedPathName), __smallIntegerVal(umask)) >= 0) {
+            RETURN(true);
+        }
+        @global(LastErrorNumber) = __mkSmallInteger(errno);
     }
 %}.
     "/ could not create - if it already existed this is ok
@@ -3448,20 +3452,25 @@
     "link the file 'oldPath' to 'newPath'. The link will be a hard link.
      Return true if successful, false if not."
 
+    |encodedOldPathName encodedNewPathName|
+
+    encodedOldPathName := self encodePath:oldPath.
+    encodedNewPathName := self encodePath:newPath.
+
 %{
     int ret;
 
-    if (__isStringLike(oldPath) && __isStringLike(newPath)) {
-	__BEGIN_INTERRUPTABLE__
-	do {
-	    ret = link((char *) __stringVal(oldPath), (char *) __stringVal(newPath));
-	} while (ret < 0 && errno == EINTR);
-	__END_INTERRUPTABLE__
-	if (ret < 0) {
-	    @global(LastErrorNumber) = __mkSmallInteger(errno);
-	    RETURN ( false );
-	}
-	RETURN (true);
+    if (__isStringLike(encodedOldPathName) && __isStringLike(encodedNewPathName)) {
+        __BEGIN_INTERRUPTABLE__
+        do {
+            ret = link((char *) __stringVal(encodedOldPathName), (char *) __stringVal(encodedNewPathName));
+        } while (ret < 0 && errno == EINTR);
+        __END_INTERRUPTABLE__
+        if (ret < 0) {
+            @global(LastErrorNumber) = __mkSmallInteger(errno);
+            RETURN ( false );
+        }
+        RETURN (true);
     }
 %}.
     "/
@@ -3479,29 +3488,33 @@
      The link will be a soft (symbolic) link.
      Return true if successful, false if not."
 
+    |encodedOldPathName encodedNewPathName|
+
+    encodedOldPathName := self encodePath:oldPath.
+    encodedNewPathName := self encodePath:newPath.
 %{
 #ifdef S_IFLNK
     int ret;
 
-    if (__isStringLike(oldPath) && __isStringLike(newPath)) {
-	__BEGIN_INTERRUPTABLE__
-	do {
-	    ret = symlink((char *) __stringVal(oldPath), (char *) __stringVal(newPath));
-	} while (ret < 0 && errno == EINTR);
-	__END_INTERRUPTABLE__
-	if (ret < 0) {
-	    @global(LastErrorNumber) = __mkSmallInteger(errno);
-	    RETURN ( false );
-	}
-	RETURN (true);
-    }
-#endif
-%}.
-    (oldPath isString not or:[newPath isString not]) ifTrue:[
-	"/
-	"/ bad argument(s) given
-	"/
-	^ self primitiveFailed
+    if (__isStringLike(encodedOldPathName) && __isStringLike(encodedNewPathName)) {
+        __BEGIN_INTERRUPTABLE__
+        do {
+            ret = symlink((char *) __stringVal(encodedOldPathName), (char *) __stringVal(encodedNewPathName));
+        } while (ret < 0 && errno == EINTR);
+        __END_INTERRUPTABLE__
+        if (ret < 0) {
+            @global(LastErrorNumber) = __mkSmallInteger(errno);
+            RETURN ( false );
+        }
+        RETURN (true);
+    }
+#endif
+%}.
+    (encodedOldPathName isString not or:[encodedNewPathName isString not]) ifTrue:[
+        "/
+        "/ bad argument(s) given
+        "/
+        ^ self primitiveFailed
     ].
 
     "/
@@ -3518,18 +3531,20 @@
     "open a file, return an os specific fileHandle.
      openmode is a symbol defining the way to open
      valid modes are:
-	#O_RDONLY
-	#O_RDWR
-	#O_WRONLY
-	#O_CREAT
-	#O_APPEND
-	#O_SYNC
-	#O_LARGEFILE
+        #O_RDONLY
+        #O_RDWR
+        #O_WRONLY
+        #O_CREAT
+        #O_APPEND
+        #O_SYNC
+        #O_LARGEFILE
 
      This is a private entry, but maybe useful to open/create a file in a special mode,
      which is proprietrary to the operatingSystem."
 
-    |error fileDescriptor|
+    |error fileDescriptor encodedPathName|
+
+    encodedPathName := self encodePath:path.
 
 %{
     OBJ *ap;
@@ -3538,56 +3553,56 @@
     int mode, openFlags = 0;
     int n;
 
-    if (!__isStringLike(path)) {
-	error = @symbol(badArgument1);
-	goto err;
+    if (!__isStringLike(encodedPathName)) {
+        error = @symbol(badArgument1);
+        goto err;
     }
     if (!__isArrayLike(attributes)) {
-	error = @symbol(badArgument2);
-	goto err;
+        error = @symbol(badArgument2);
+        goto err;
     }
     if (modeInteger == nil) {
-	mode = 0644;
+        mode = 0644;
     } else if (__isSmallInteger(modeInteger)) {
-	mode = __intVal(modeInteger);
+        mode = __intVal(modeInteger);
     } else {
-	error = @symbol(badArgument3);
-	goto err;
+        error = @symbol(badArgument3);
+        goto err;
     }
 
     nAttributes = __arraySize(attributes);
     for (n = 0, ap = __arrayVal(attributes); n < nAttributes; n++) {
-	OBJ attribute = ap[n];
-
-	if (attribute == @symbol(O_RDONLY)) {
-	    openFlags |= O_RDONLY;
-	} else if (attribute == @symbol(O_RDWR)) {
-	    openFlags |= O_RDWR;
-	} else if (attribute == @symbol(O_WRONLY)) {
-	    openFlags |= O_WRONLY;
-	} else if (attribute == @symbol(O_CREAT)) {
-	    openFlags |= O_CREAT;
-	} else if (attribute == @symbol(O_APPEND)) {
-	    openFlags |= O_APPEND;
-	} else if (attribute == @symbol(O_EXCL)) {
-	    openFlags |= O_EXCL;
-	} else if (attribute == @symbol(O_TRUNC)) {
-	    openFlags |= O_TRUNC;
-	} else if (attribute == @symbol(O_LARGEFILE)) {
+        OBJ attribute = ap[n];
+
+        if (attribute == @symbol(O_RDONLY)) {
+            openFlags |= O_RDONLY;
+        } else if (attribute == @symbol(O_RDWR)) {
+            openFlags |= O_RDWR;
+        } else if (attribute == @symbol(O_WRONLY)) {
+            openFlags |= O_WRONLY;
+        } else if (attribute == @symbol(O_CREAT)) {
+            openFlags |= O_CREAT;
+        } else if (attribute == @symbol(O_APPEND)) {
+            openFlags |= O_APPEND;
+        } else if (attribute == @symbol(O_EXCL)) {
+            openFlags |= O_EXCL;
+        } else if (attribute == @symbol(O_TRUNC)) {
+            openFlags |= O_TRUNC;
+        } else if (attribute == @symbol(O_LARGEFILE)) {
 #ifdef O_LARGEFILE
-	    openFlags |= O_LARGEFILE;
+            openFlags |= O_LARGEFILE;
 #else
-	    error = @symbol(badArgument2);
-	    goto err;
-#endif
-	} else if (attribute == @symbol(O_SYNC)) {
+            error = @symbol(badArgument2);
+            goto err;
+#endif
+        } else if (attribute == @symbol(O_SYNC)) {
 #ifdef O_SYNC
-	    openFlags |= O_SYNC;
+            openFlags |= O_SYNC;
 #else
-	    error = @symbol(badArgument2);
-	    goto err;
-#endif
-	}
+            error = @symbol(badArgument2);
+            goto err;
+#endif
+        }
     }
 
 #if defined(O_NONBLOCK)
@@ -3597,31 +3612,31 @@
 #endif
 
 again:
-    fd = open((char *) __stringVal(path), openFlags, mode);
+    fd = open((char *) __stringVal(encodedPathName), openFlags, mode);
     if (fd < 0) {
-	if (errno == EINTR) {
-	    __HANDLE_INTERRUPTS__;
-	    goto again;
-	} else {
-	    error = __mkSmallInteger(errno);
-	    goto err;
-	}
+        if (errno == EINTR) {
+            __HANDLE_INTERRUPTS__;
+            goto again;
+        } else {
+            error = __mkSmallInteger(errno);
+            goto err;
+        }
     }
     fileDescriptor = __mkSmallInteger(fd);
 err:;
 %}.
     ^ fileDescriptor notNil ifTrue:[
-	FileDescriptorHandle for:fileDescriptor.
+        FileDescriptorHandle for:fileDescriptor.
     ] ifFalse:[
-	(self errorHolderForNumber:error) reportError
-    ].
-
-    "
-	self open:'/etc/hosts' attributes:#(O_RDONLY) mode:nil
-	self open:'/tmp/xxzz' attributes:#(O_RDWR O_CREAT) mode:8r611
-	self open:'/etc/passwd' attributes:#(O_RDWR) mode:nil
-	self open:'/no one knows this file' attributes:#(O_RDONLY) mode:nil
-	self open:'foo/bar/baz' attributes:#(O_RDWR O_CREAT) mode:nil
+        (self errorHolderForNumber:error) reportError
+    ].
+
+    "
+        self open:'/etc/hosts' attributes:#(O_RDONLY) mode:nil
+        self open:'/tmp/xxzz' attributes:#(O_RDWR O_CREAT) mode:8r611
+        self open:'/etc/passwd' attributes:#(O_RDWR) mode:nil
+        self open:'/no one knows this file' attributes:#(O_RDONLY) mode:nil
+        self open:'foo/bar/baz' attributes:#(O_RDWR O_CREAT) mode:nil
     "
 !
 
@@ -3679,20 +3694,23 @@
      Return true if successful, false if directory is not empty or no permission.
      This is a lowLevel entry - use Filename protocol for compatibility."
 
+    |encodedPathName|
+
+    encodedPathName := self encodePath:fullPathName.
 %{
     int ret;
 
-    if (__isStringLike(fullPathName)) {
-	__BEGIN_INTERRUPTABLE__
-	do {
-	    ret = rmdir((char *) __stringVal(fullPathName));
-	} while (ret < 0 && errno == EINTR);
-	__END_INTERRUPTABLE__
-	if (ret < 0) {
-	    @global(LastErrorNumber) = __mkSmallInteger(errno);
-	    RETURN ( false );
-	}
-	RETURN (true);
+    if (__isStringLike(encodedPathName)) {
+        __BEGIN_INTERRUPTABLE__
+        do {
+            ret = rmdir((char *) __stringVal(encodedPathName));
+        } while (ret < 0 && errno == EINTR);
+        __END_INTERRUPTABLE__
+        if (ret < 0) {
+            @global(LastErrorNumber) = __mkSmallInteger(errno);
+            RETURN ( false );
+        }
+        RETURN (true);
     }
 %}.
     "/
@@ -3711,20 +3729,23 @@
     "remove the file named 'fullPathName'; return true if successful.
      This is a lowLevel entry - use Filename protocol for compatibility."
 
+    |encodedPathName|
+
+    encodedPathName := self encodePath:fullPathName.
 %{
     int ret;
 
-    if (__isStringLike(fullPathName)) {
-	__BEGIN_INTERRUPTABLE__
-	do {
-	    ret = unlink((char *) __stringVal(fullPathName));
-	} while (ret < 0 && errno == EINTR);
-	__END_INTERRUPTABLE__
-	if (ret < 0) {
-	    @global(LastErrorNumber) = __mkSmallInteger(errno);
-	    RETURN ( false );
-	}
-	RETURN (true);
+    if (__isStringLike(encodedPathName)) {
+        __BEGIN_INTERRUPTABLE__
+        do {
+            ret = unlink((char *) __stringVal(encodedPathName));
+        } while (ret < 0 && errno == EINTR);
+        __END_INTERRUPTABLE__
+        if (ret < 0) {
+            @global(LastErrorNumber) = __mkSmallInteger(errno);
+            RETURN ( false );
+        }
+        RETURN (true);
     }
 %}.
     ^ self primitiveFailed
@@ -3738,32 +3759,36 @@
      any invalid names.
      Returns true if successful, false if not"
 
+    |encodedOldPathName encodedNewPathName|
+
+    encodedOldPathName := self encodePath:oldPath.
+    encodedNewPathName := self encodePath:newPath.
 %{
     int ret, eno;
 
-    if (__isStringLike(oldPath) && __isStringLike(newPath)) {
+    if (__isStringLike(encodedOldPathName) && __isStringLike(encodedNewPathName)) {
 #if defined(HAS_RENAME)
-	__BEGIN_INTERRUPTABLE__
-	do {
-	    ret = rename((char *) __stringVal(oldPath), (char *) __stringVal(newPath));
-	} while (ret < 0 && errno == EINTR);
-	__END_INTERRUPTABLE__
+        __BEGIN_INTERRUPTABLE__
+        do {
+            ret = rename((char *) __stringVal(encodedOldPathName), (char *) __stringVal(encodedNewPathName));
+        } while (ret < 0 && errno == EINTR);
+        __END_INTERRUPTABLE__
 #else
-	ret = link((char *) __stringVal(oldPath), (char *) __stringVal(newPath));
-	if (ret >= 0) {
-	    ret = unlink((char *) __stringVal(oldPath));
-	    if (ret < 0) {
-		eno = errno;
-		unlink((char *) __stringVal(newPath));
-		errno = eno;
-	    }
-	}
-#endif
-	if (ret < 0) {
-	    @global(LastErrorNumber) = __mkSmallInteger(errno);
-	    RETURN ( false );
-	}
-	RETURN (true);
+        ret = link((char *) __stringVal(encodedOldPathName), (char *) __stringVal(encodedNewPathName));
+        if (ret >= 0) {
+            ret = unlink((char *) __stringVal(encodedOldPathName));
+            if (ret < 0) {
+                eno = errno;
+                unlink((char *) __stringVal(encodedNewPathName));
+                errno = eno;
+            }
+        }
+#endif
+        if (ret < 0) {
+            @global(LastErrorNumber) = __mkSmallInteger(errno);
+            RETURN ( false );
+        }
+        RETURN (true);
     }
 %}.
     ^ self primitiveFailed
@@ -3779,62 +3804,66 @@
 
      This is a low-level entry - use Filename protocol."
 
+    |encodedPathName|
+
+    encodedPathName := self encodePath:aPathName.
+
 %{
 #if defined(HAS_TRUNCATE) || defined(HAS_FTRUNCATE)
     int ret;
     off_t truncateSize;
 
-    if (!__isStringLike(aPathName))
-	goto getOutOfHere;
+    if (!__isStringLike(encodedPathName))
+        goto getOutOfHere;
 
     if (__isSmallInteger(newSize)) {
-	truncateSize = __intVal(newSize);
-	if (truncateSize < 0) {
-	    goto getOutOfHere;
-	}
+        truncateSize = __intVal(newSize);
+        if (truncateSize < 0) {
+            goto getOutOfHere;
+        }
     } else {
-	truncateSize = __signedLongIntVal(newSize);
-	if (truncateSize < 0) {
-	    goto getOutOfHere;
-	}
-	if (truncateSize == 0) {
-	    if (sizeof(truncateSize) == 8) {
-		if (__signedLong64IntVal(newSize, &truncateSize) == 0 || truncateSize < 0) {
-		    goto getOutOfHere;
-		}
-	    } else {
-		goto getOutOfHere;
-	    }
-	}
+        truncateSize = __signedLongIntVal(newSize);
+        if (truncateSize < 0) {
+            goto getOutOfHere;
+        }
+        if (truncateSize == 0) {
+            if (sizeof(truncateSize) == 8) {
+                if (__signedLong64IntVal(newSize, &truncateSize) == 0 || truncateSize < 0) {
+                    goto getOutOfHere;
+                }
+            } else {
+                goto getOutOfHere;
+            }
+        }
     }
 
 #if defined(HAS_TRUNCATE)
-	__BEGIN_INTERRUPTABLE__
-	do {
-	    ret = truncate((char *) __stringVal(aPathName), truncateSize);
-	} while (ret < 0 && errno == EINTR);
-	__END_INTERRUPTABLE__
+        __BEGIN_INTERRUPTABLE__
+        do {
+            ret = truncate((char *) __stringVal(encodedPathName), truncateSize);
+        } while (ret < 0 && errno == EINTR);
+        __END_INTERRUPTABLE__
 #else
 # ifdef HAS_FTRUNCATE
     {
-	int fd;
-
-	do {
-	    fd = open((char *) __stringVal(aPathName), 2);
-	} while (fd < 0 && errno == EINTR);
-	if (fd < 0) {
-	    @global(LastErrorNumber) = __mkSmallInteger(errno);
-	    RETURN ( false );
-	}
-
-	ret = ftruncate(fd, truncateSize);
-	close(fd);
+        int fd;
+
+        do {
+            fd = open((char *) __stringVal(encodedPathName), 2);
+        } while (fd < 0 && errno == EINTR);
+        if (fd < 0) {
+            @global(LastErrorNumber) = __mkSmallInteger(errno);
+            RETURN ( false );
+        }
+
+        ret = ftruncate(fd, truncateSize);
+        close(fd);
     }
 # endif /* HAS_FTRUNCATE */
 #endif
     if (ret < 0) {
-	@global(LastErrorNumber) = __mkSmallInteger(errno);
-	RETURN ( false );
+        @global(LastErrorNumber) = __mkSmallInteger(errno);
+        RETURN ( false );
     }
     RETURN (true);
 getOutOfHere:;
@@ -3922,29 +3951,32 @@
 
     "
      this could have been implemented as:
-	(self infoOf:aPathName) at:#mode
+        (self infoOf:aPathName) at:#mode
      but for huge directory searches the code below is faster
     "
 
+    |encodedPathName|
+
+    encodedPathName := self encodePath:aPathName.
 %{
     struct stat buf;
     int ret;
 
-    if (__isStringLike(aPathName)) {
+    if (__isStringLike(encodedPathName)) {
 # ifdef TRACE_STAT_CALLS
-	printf("stat on '%s' for accessMode\n", __stringVal(aPathName));
-# endif
-	__BEGIN_INTERRUPTABLE__
-	do {
-	    ret = stat((char *) __stringVal(aPathName), &buf);
-	} while ((ret < 0) && (errno == EINTR));
-	__END_INTERRUPTABLE__
-
-	if (ret < 0) {
-	    @global(LastErrorNumber) = __mkSmallInteger(errno);
-	    RETURN ( nil );
-	}
-	RETURN ( __mkSmallInteger(buf.st_mode & 0777) );
+        printf("stat on '%s' for accessMode\n", __stringVal(encodedPathName));
+# endif
+        __BEGIN_INTERRUPTABLE__
+        do {
+            ret = stat((char *) __stringVal(encodedPathName), &buf);
+        } while ((ret < 0) && (errno == EINTR));
+        __END_INTERRUPTABLE__
+
+        if (ret < 0) {
+            @global(LastErrorNumber) = __mkSmallInteger(errno);
+            RETURN ( nil );
+        }
+        RETURN ( __mkSmallInteger(buf.st_mode & 0777) );
     }
 %}.
    ^ self primitiveFailed
@@ -3960,20 +3992,23 @@
      independent. Return true if changed,
      false if such a file does not exist or change was not allowd."
 
+    |encodedPathName|
+
+    encodedPathName := self encodePath:aPathName.
 %{
     int ret;
 
-    if (__isStringLike(aPathName) && __isSmallInteger(modeBits)) {
-	__BEGIN_INTERRUPTABLE__
-	do {
-	    ret = chmod((char *)__stringVal(aPathName), __intVal(modeBits));
-	} while (ret < 0 && errno == EINTR);
-	__END_INTERRUPTABLE__
-	if (ret < 0) {
-	    @global(LastErrorNumber) = __mkSmallInteger(errno);
-	    RETURN ( false );
-	}
-	RETURN ( true );
+    if (__isStringLike(encodedPathName) && __isSmallInteger(modeBits)) {
+        __BEGIN_INTERRUPTABLE__
+        do {
+            ret = chmod((char *)__stringVal(encodedPathName), __intVal(modeBits));
+        } while (ret < 0 && errno == EINTR);
+        __END_INTERRUPTABLE__
+        if (ret < 0) {
+            @global(LastErrorNumber) = __mkSmallInteger(errno);
+            RETURN ( false );
+        }
+        RETURN ( true );
     }
 %}.
     ^ self primitiveFailed
@@ -4293,20 +4328,22 @@
     |path|
 
 %{  /* UNLIMITEDSTACK */
-	char nameBuffer[MAXPATHLEN + 1];
-
-	if (getcwd(nameBuffer, MAXPATHLEN)) {
-	    OBJ d;
-
-	    @global(CurrentDirectory) = d = __MKSTRING(nameBuffer);
-	    __GSTORE(d);
-	    RETURN (d);
-	}
-%}.
-    ^ self primitiveFailed
-
-    "
-	self getCurrentDirectory
+        char nameBuffer[MAXPATHLEN + 1];
+
+        if (getcwd(nameBuffer, MAXPATHLEN)) {
+            path = __MKSTRING(nameBuffer);
+        }
+%}.
+    path isNil ifTrue:[
+        ^ self primitiveFailed.
+    ].
+    path := self decodePath:path.
+    CurrentDirectory := path.
+
+    ^ path.
+
+    "
+        self getCurrentDirectory
     "
 !
 
@@ -4466,21 +4503,21 @@
     "return some object filled with info for the file 'aPathName';
      the info (for which corresponding access methods are understood by
      the returned object) is:
-	 type            - a symbol giving the files type
-	 mode            - numeric access mode
-	 uid             - owners user id
-	 gid             - owners group id
-	 size            - files size
-	 id              - files number (i.e. inode number)
-	 accessed        - last access time (as Timestamp)
-	 modified        - last modification time (as Timestamp)
-	 statusChanged   - last status change time (as Timestamp)
-	 alternativeName     - (windows only:) the MSDOS name of the file
-	 recordFormatNumeric - (VMS only:) numeric value of the recordFormat
-	 recordFormat        - (VMS only:) symbolic value of the recordFormat
-	 recordAttributes    - (VMS only:) recordAttributes
-	 fixedHeaderSize     - (VMS only:) fixed header size in a variable record format
-	 recordSize          - (VMS only:) record size.
+         type            - a symbol giving the files type
+         mode            - numeric access mode
+         uid             - owners user id
+         gid             - owners group id
+         size            - files size
+         id              - files number (i.e. inode number)
+         accessed        - last access time (as Timestamp)
+         modified        - last modification time (as Timestamp)
+         statusChanged   - last status change time (as Timestamp)
+         alternativeName     - (windows only:) the MSDOS name of the file
+         recordFormatNumeric - (VMS only:) numeric value of the recordFormat
+         recordFormat        - (VMS only:) symbolic value of the recordFormat
+         recordAttributes    - (VMS only:) recordAttributes
+         fixedHeaderSize     - (VMS only:) fixed header size in a variable record format
+         recordSize          - (VMS only:) record size.
 
      Some of the fields may be returned as nil on systems which do not provide
      all of the information.
@@ -4490,14 +4527,16 @@
      use #linkInfoOf: to get info about the link itself.
     "
 
-    |type mode uid gid size id nLink aOStime mOStime cOStime error|
+    |type mode uid gid size id nLink aOStime mOStime cOStime error encodedPathName|
+
+    encodedPathName := self encodePath:aPathName.
 %{
     struct stat buf;
     int ret;
 
-    if (!__isStringLike(aPathName)) {
-	error = @symbol(badArgument);
-	goto out;
+    if (!__isStringLike(encodedPathName)) {
+        error = @symbol(badArgument);
+        goto out;
     }
 
 # ifdef TRACE_STAT_CALLS
@@ -4505,76 +4544,76 @@
 # endif
     __BEGIN_INTERRUPTABLE__
     do {
-	ret = stat((char *) __stringVal(aPathName), &buf);
+        ret = stat((char *) __stringVal(encodedPathName), &buf);
     } while ((ret < 0) && (errno == EINTR));
     __END_INTERRUPTABLE__
 
     if (ret < 0) {
-	error = __mkSmallInteger(errno);
-	@global(LastErrorNumber) = error;
-	goto out;
+        error = __mkSmallInteger(errno);
+        @global(LastErrorNumber) = error;
+        goto out;
     }
     switch (buf.st_mode & S_IFMT) {
-	case S_IFDIR:
-	    type = @symbol(directory);
-	    break;
-
-	case S_IFREG:
-	    type = @symbol(regular);
-	    break;
+        case S_IFDIR:
+            type = @symbol(directory);
+            break;
+
+        case S_IFREG:
+            type = @symbol(regular);
+            break;
 # ifdef S_IFCHR
-	case S_IFCHR:
-	    type = @symbol(characterSpecial);
-	    break;
+        case S_IFCHR:
+            type = @symbol(characterSpecial);
+            break;
 # endif
 # ifdef S_IFBLK
-	case S_IFBLK:
-	    type = @symbol(blockSpecial);
-	    break;
+        case S_IFBLK:
+            type = @symbol(blockSpecial);
+            break;
 # endif
 # ifdef S_IFMPC
-	case S_IFMPC:
-	    type = @symbol(multiplexedCharacterSpecial);
-	    break;
+        case S_IFMPC:
+            type = @symbol(multiplexedCharacterSpecial);
+            break;
 # endif
 # ifdef S_IFMPB
-	case S_IFMPB:
-	    type = @symbol(multiplexedBlockSpecial);
-	    break;
+        case S_IFMPB:
+            type = @symbol(multiplexedBlockSpecial);
+            break;
 # endif
 # ifdef S_IFLNK
-	case S_IFLNK:
-	    type = @symbol(symbolicLink);
-	    break;
+        case S_IFLNK:
+            type = @symbol(symbolicLink);
+            break;
 # endif
 # ifdef S_IFSOCK
-	case S_IFSOCK:
-	    type = @symbol(socket);
-	    break;
+        case S_IFSOCK:
+            type = @symbol(socket);
+            break;
 # endif
 # ifdef S_IFIFO
-	case S_IFIFO:
-	    type = @symbol(fifo);
-	    break;
-# endif
-	default:
-	    type = @symbol(unknown);
-	    break;
+        case S_IFIFO:
+            type = @symbol(fifo);
+            break;
+# endif
+        default:
+            type = @symbol(unknown);
+            break;
     }
 
     if (sizeof(buf.st_ino) == 8) {
-	id = __MKUINT64(&buf.st_ino);
+        id = __MKUINT64(&buf.st_ino);
     } else {
-	id = __MKUINT(buf.st_ino);
+        id = __MKUINT(buf.st_ino);
     }
     mode = __mkSmallInteger(buf.st_mode & 0777);
     uid = __mkSmallInteger(buf.st_uid);
     gid = __mkSmallInteger(buf.st_gid);
     nLink = __mkSmallInteger(buf.st_nlink);
     if (sizeof(buf.st_size) == 8) {
-	size = __MKINT64(&buf.st_size);
+        size = __MKINT64(&buf.st_size);
     } else {
-	size = __MKINT(buf.st_size);
+        size = __MKINT(buf.st_size);
     }
     aOStime = __MKUINT(buf.st_atime);
     mOStime = __MKUINT(buf.st_mtime);
@@ -4583,26 +4622,26 @@
     out:;
 %}.
      mode notNil ifTrue:[
-	"/ now done lazy in FileStatusInfo
-	"/ atime := Timestamp fromOSTime:(aOStime * 1000).
-	"/ mtime := Timestamp fromOSTime:(mOStime * 1000).
-	"/ ctime := Timestamp fromOSTime:(cOStime * 1000).
-
-	^ FileStatusInfo
-		    type:type
-		    mode:mode
-		    uid:uid
-		    gid:gid
-		    size:size
-		    id:id
-		    accessed:aOStime
-		    modified:mOStime
-		    statusChanged:cOStime
-		    path:nil
-		    numLinks:nLink.
+        "/ now done lazy in FileStatusInfo
+        "/ atime := Timestamp fromOSTime:(aOStime * 1000).
+        "/ mtime := Timestamp fromOSTime:(mOStime * 1000).
+        "/ ctime := Timestamp fromOSTime:(cOStime * 1000).
+
+        ^ FileStatusInfo
+                    type:type
+                    mode:mode
+                    uid:uid
+                    gid:gid
+                    size:size
+                    id:id
+                    accessed:aOStime
+                    modified:mOStime
+                    statusChanged:cOStime
+                    path:nil
+                    numLinks:nLink.
     ].
     error notNil ifTrue:[
-	^ nil.
+        ^ nil.
     ].
 
     ^ self primitiveFailed
@@ -4620,31 +4659,35 @@
      This also returns true for symbolic links pointing to a directory;
      if you need to check for this, use #linkInfo:."
 
+    |encodedPathName|
+
+    encodedPathName := self encodePath:aPathName.
+
 %{
     int ret;
 
-    if (__isStringLike(aPathName)) {
-	struct stat buf;
+    if (__isStringLike(encodedPathName)) {
+        struct stat buf;
 
 # ifdef TRACE_STAT_CALLS
-	printf("stat on '%s' for isDirectory\n", __stringVal(aPathName));
-# endif
-	__BEGIN_INTERRUPTABLE__
-	do {
-	    ret = stat((char *) __stringVal(aPathName), &buf);
-	} while ((ret < 0) && (errno == EINTR));
-	__END_INTERRUPTABLE__
-	if (ret < 0) {
-	    @global(LastErrorNumber) = __mkSmallInteger(errno);
-	    RETURN ( false );
-	}
-	RETURN ( ((buf.st_mode & S_IFMT) == S_IFDIR) ? true : false);
+        printf("stat on '%s' for isDirectory\n", __stringVal(encodedPathName));
+# endif
+        __BEGIN_INTERRUPTABLE__
+        do {
+            ret = stat((char *) __stringVal(encodedPathName), &buf);
+        } while ((ret < 0) && (errno == EINTR));
+        __END_INTERRUPTABLE__
+        if (ret < 0) {
+            @global(LastErrorNumber) = __mkSmallInteger(errno);
+            RETURN ( false );
+        }
+        RETURN ( ((buf.st_mode & S_IFMT) == S_IFDIR) ? true : false);
     }
 %}.
     ^ self primitiveFailed
 
     "an alternative implementation would be:
-	^ (self infoOf:aPathName) type == #directory
+        ^ (self infoOf:aPathName) type == #directory
     "
 !
 
@@ -4652,22 +4695,26 @@
     "return true, if the given file is executable.
      For symbolic links, the pointed-to-file is checked."
 
+    |encodedPathName|
+
+    encodedPathName := self encodePath:aPathName.
+
 %{
     int ret;
 
-    if (__isStringLike(aPathName)) {
+    if (__isStringLike(encodedPathName)) {
 # ifdef TRACE_ACCESS_CALLS
-	printf("access on '%s' for executable\n", __stringVal(aPathName));
-# endif
-	__BEGIN_INTERRUPTABLE__
-	do {
-	    ret = access(__stringVal(aPathName), X_OK);
-	} while ((ret < 0) && (errno == EINTR));
-	__END_INTERRUPTABLE__
-	if (ret < 0) {
-	    @global(LastErrorNumber) = __mkSmallInteger(errno);
-	}
-	RETURN ( ((ret == 0) ? true : false) );
+        printf("access on '%s' for executable\n", __stringVal(encodedPathName));
+# endif
+        __BEGIN_INTERRUPTABLE__
+        do {
+            ret = access(__stringVal(encodedPathName), X_OK);
+        } while ((ret < 0) && (errno == EINTR));
+        __END_INTERRUPTABLE__
+        if (ret < 0) {
+            @global(LastErrorNumber) = __mkSmallInteger(errno);
+        }
+        RETURN ( ((ret == 0) ? true : false) );
     }
 %}.
     ^ self primitiveFailed
@@ -4677,22 +4724,25 @@
     "return true, if the file/dir 'aPathName' is readable.
      For symbolic links, the pointed-to-file is checked."
 
+    |encodedPathName|
+
+    encodedPathName := self encodePath:aPathName.
 %{
     int ret;
 
-    if (__isStringLike(aPathName)) {
+    if (__isStringLike(encodedPathName)) {
 # ifdef TRACE_ACCESS_CALLS
-	printf("access on '%s' for readable\n", __stringVal(aPathName));
-# endif
-	__BEGIN_INTERRUPTABLE__
-	do {
-	    ret = access(__stringVal(aPathName), R_OK);
-	} while ((ret < 0) && (errno == EINTR));
-	__END_INTERRUPTABLE__
-	if (ret < 0) {
-	    @global(LastErrorNumber) = __mkSmallInteger(errno);
-	}
-	RETURN ( ((ret == 0) ? true : false) );
+        printf("access on '%s' for readable\n", __stringVal(encodedPathName));
+# endif
+        __BEGIN_INTERRUPTABLE__
+        do {
+            ret = access(__stringVal(encodedPathName), R_OK);
+        } while ((ret < 0) && (errno == EINTR));
+        __END_INTERRUPTABLE__
+        if (ret < 0) {
+            @global(LastErrorNumber) = __mkSmallInteger(errno);
+        }
+        RETURN ( ((ret == 0) ? true : false) );
     }
 %}.
     ^ self primitiveFailed
@@ -4702,24 +4752,27 @@
     "return true, if 'aPathName' is a valid path name
      (i.e. the file or directory exists)"
 
+    |encodedPathName|
+
+    encodedPathName := self encodePath:aPathName.
 %{
     struct stat buf;
     int ret;
 
-    if (__isStringLike(aPathName)) {
+    if (__isStringLike(encodedPathName)) {
 # ifdef TRACE_STAT_CALLS
-	printf("stat on '%s' for isValidPath\n", __stringVal(aPathName));
-# endif
-	__BEGIN_INTERRUPTABLE__
-	do {
-	    ret = stat((char *) __stringVal(aPathName), &buf);
-	} while ((ret < 0) && (errno == EINTR));
-	__END_INTERRUPTABLE__
-	if (ret < 0) {
-	    @global(LastErrorNumber) = __mkSmallInteger(errno);
-	    RETURN (false);
-	}
-	RETURN ( ret ? false : true );
+        printf("stat on '%s' for isValidPath\n", __stringVal(encodedPathName));
+# endif
+        __BEGIN_INTERRUPTABLE__
+        do {
+            ret = stat((char *) __stringVal(encodedPathName), &buf);
+        } while ((ret < 0) && (errno == EINTR));
+        __END_INTERRUPTABLE__
+        if (ret < 0) {
+            @global(LastErrorNumber) = __mkSmallInteger(errno);
+            RETURN (false);
+        }
+        RETURN ( ret ? false : true );
     }
 %}.
     ^ self primitiveFailed
@@ -4732,22 +4785,25 @@
     "return true, if the given file is writable.
      For symbolic links, the pointed-to-file is checked."
 
+    |encodedPathName|
+
+    encodedPathName := self encodePath:aPathName.
 %{
     int ret;
 
-    if (__isStringLike(aPathName)) {
+    if (__isStringLike(encodedPathName)) {
 # ifdef TRACE_ACCESS_CALLS
-	printf("access on '%s' for writable\n", __stringVal(aPathName));
-# endif
-	__BEGIN_INTERRUPTABLE__
-	do {
-	    ret = access(__stringVal(aPathName), W_OK);
-	} while ((ret < 0) && (errno == EINTR));
-	__END_INTERRUPTABLE__
-	if (ret < 0) {
-	    @global(LastErrorNumber) = __mkSmallInteger(errno);
-	}
-	RETURN ( ((ret == 0) ? true : false) );
+        printf("access on '%s' for writable\n", __stringVal(encodedPathName));
+# endif
+        __BEGIN_INTERRUPTABLE__
+        do {
+            ret = access(__stringVal(encodedPathName), W_OK);
+        } while ((ret < 0) && (errno == EINTR));
+        __END_INTERRUPTABLE__
+        if (ret < 0) {
+            @global(LastErrorNumber) = __mkSmallInteger(errno);
+        }
+        RETURN ( ((ret == 0) ? true : false) );
     }
 %}.
     ^ self primitiveFailed
@@ -4784,7 +4840,9 @@
      on contrast to #infoOf:, which returns the info of the pointed to file
      in case of a symbolic link."
 
-    |type mode uid gid size id nLink aOStime mOStime cOStime path|
+    |type mode uid gid size id nLink aOStime mOStime cOStime path encodedPathName|
+
+    encodedPathName := self encodePath:aPathName.
 
 %{  /* STACK: 1200 */
 #if defined(S_IFLNK)
@@ -4792,10 +4850,10 @@
     int ret;
     char pathBuffer[1024];
 
-    if (__isStringLike(aPathName)) {
+    if (__isStringLike(encodedPathName)) {
         __BEGIN_INTERRUPTABLE__
         do {
-            ret = lstat((char *) __stringVal(aPathName), &buf);
+            ret = lstat((char *) __stringVal(encodedPathName), &buf);
         } while ((ret < 0) && (errno == EINTR));
         __END_INTERRUPTABLE__
 
@@ -4807,7 +4865,7 @@
     # ifdef S_IFLNK
             case S_IFLNK:
                 type = @symbol(symbolicLink);
-                if ((ret = readlink((char *) __stringVal(aPathName), pathBuffer, sizeof(pathBuffer))) < 0) {
+                if ((ret = readlink((char *) __stringVal(encodedPathName), pathBuffer, sizeof(pathBuffer))) < 0) {
                     @global(LastErrorNumber) = __mkSmallInteger(errno);
                     RETURN ( nil );
                 }
@@ -4880,15 +4938,6 @@
 #endif
 %}.
 
-    path notNil ifTrue:[
-        [
-            path := path utf8Decoded.
-        ] on:InvalidEncodingError do:[:ex|
-            "maybe there are old filenames in ISO8859-x,
-             just keep them untranslated"
-        ].
-    ].
-    
     mode notNil ifTrue:[
         ^ FileStatusInfo
             type:type
@@ -4900,7 +4949,7 @@
             accessed:aOStime
             modified:mOStime
             statusChanged:cOStime
-            path:path
+            path:(self decodePath:path)
             numLinks:nLink.
    ].
    ^ self primitiveFailed
@@ -4957,47 +5006,51 @@
 
     |p path command|
 
+    path = '.' ifTrue:[
+        ^ self getCurrentDirectory.
+    ].
+
     "some systems have a convenient function for this ..."
-    path := self primPathNameOf:pathName.
+    path := self primPathNameOf:(self encodePath:pathName).
 
     path isNil ifTrue:[
-	(self isValidPath:pathName) ifFalse:[
-	    p := pathName.
-	    [(p size > 1)
-	     and:[p endsWith:(self fileSeparator)]
-	    ] whileTrue:[
-		p := p copyWithoutLast:1.
-	    ].
-	    ^ p
-	].
-
-	(SlowFork==true or:[PipeFailed==true]) ifFalse:[
-	    PipeStream openErrorSignal handle:[:ex |
-		PipeFailed := true.
-		'UnixOperatingSystem [warning]: cannot fork/popen' errorPrintCR.
-		ex return.
-	    ] do:[
-		"have to fall back ..."
-		command := 'cd "' , pathName , '"; pwd'.
-		p := PipeStream readingFrom:command.
-	    ].
-
-	    (p isNil or:[p atEnd]) ifTrue:[
-		('UnixOperatingSystem [warning]: PipeStream for <' , command , '> failed') errorPrintCR.
-	    ] ifFalse:[
-		path := p nextLine.
-		p close.
-	    ]
-	].
-	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 isValidPath:pathName) ifFalse:[
+            p := pathName.
+            [(p size > 1)
+             and:[p endsWith:(self fileSeparator)]
+            ] whileTrue:[
+                p := p copyWithoutLast:1.
+            ].
+            ^ p
+        ].
+
+        (SlowFork==true or:[PipeFailed==true]) ifFalse:[
+            PipeStream openErrorSignal handle:[:ex |
+                PipeFailed := true.
+                'UnixOperatingSystem [warning]: cannot fork/popen' errorPrintCR.
+                ex return.
+            ] do:[
+                "have to fall back ..."
+                command := 'cd "' , pathName , '"; pwd'.
+                p := PipeStream readingFrom:command.
+            ].
+
+            (p isNil or:[p atEnd]) ifTrue:[
+                ('UnixOperatingSystem [warning]: PipeStream for <' , command , '> failed') errorPrintCR.
+            ] ifFalse:[
+                path := p nextLine.
+                p close.
+            ]
+        ].
+        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.
 
@@ -5019,28 +5072,31 @@
 primIdOf:aPathName
     "the actual code to return the fileNumber (i.e. inode number) of a file."
 
+    |encodedPathName|
+
+    encodedPathName := self encodePath:aPathName.
 %{
     struct stat buf;
     int ret;
     unsigned INT ino;
     OBJ retVal;
 
-    if (__isStringLike(aPathName)) {
+    if (__isStringLike(encodedPathName)) {
 # ifdef TRACE_STAT_CALLS
-	printf("stat on '%s' for id\n", __stringVal(aPathName));
-# endif
-	__BEGIN_INTERRUPTABLE__
-	do {
-	    ret = stat((char *) __stringVal(aPathName), &buf);
-	} while (ret < 0 && errno == EINTR);
-	__END_INTERRUPTABLE__
-	if (ret >= 0) {
-	    ino = buf.st_ino;
-	    retVal = __MKUINT(ino);
-	    RETURN (retVal);
-	}
-	@global(LastErrorNumber) = __mkSmallInteger(errno);
-	RETURN (nil);
+        printf("stat on '%s' for id\n", __stringVal(encodedPathName));
+# endif
+        __BEGIN_INTERRUPTABLE__
+        do {
+            ret = stat((char *) __stringVal(encodedPathName), &buf);
+        } while (ret < 0 && errno == EINTR);
+        __END_INTERRUPTABLE__
+        if (ret >= 0) {
+            ino = buf.st_ino;
+            retVal = __MKUINT(ino);
+            RETURN (retVal);
+        }
+        @global(LastErrorNumber) = __mkSmallInteger(errno);
+        RETURN (nil);
     }
     RETURN (nil);
 %}.
@@ -5062,25 +5118,9 @@
      Notice: if symbolic links are involved, the result may look different
      from what you expect."
 
-    |path|
-
 %{  /* UNLIMITEDSTACK */
 
     if (__isStringLike(pathName)) {
-        if (strcmp(__stringVal(pathName), ".") == 0) {
-            char nameBuffer[MAXPATHLEN + 1];
-
-            if (@global(CurrentDirectory) == nil) {
-                if (getcwd(nameBuffer, MAXPATHLEN)) {
-                    OBJ d;
-
-                    @global(CurrentDirectory) = d = __MKSTRING(nameBuffer);
-                    __GSTORE(d);
-                }
-            }
-            RETURN (@global(CurrentDirectory));
-        }
-
 #ifdef HAS_REALPATH
         {
             char nameBuffer[MAXPATHLEN+1];
@@ -5088,7 +5128,6 @@
             if (realpath(__stringVal(pathName), nameBuffer)) {
                 RETURN ( __MKSTRING(nameBuffer) );
             }
-            RETURN ( nil );
         }
 #endif /* ! HAS_REALPATH */
     }
@@ -5101,28 +5140,31 @@
      For nonexistent files, nil is returned."
 
     "could be implemented as:
-	(self infoOf:aPathName) accessed
-    "
-    |osSeconds i|
+        (self infoOf:aPathName) accessed
+    "
+    |osSeconds i encodedPathName|
+
+    encodedPathName := self encodePath:aPathName.
+
 %{
     struct stat buf;
     time_t mtime;
     int ret;
 
-    if (__isStringLike(aPathName)) {
+    if (__isStringLike(encodedPathName)) {
 # ifdef TRACE_STAT_CALLS
-	printf("stat on '%s' for timeOfLastAccess\n", __stringVal(aPathName));
-# endif
-	__BEGIN_INTERRUPTABLE__
-	do {
-	    ret = stat((char *) __stringVal(aPathName), &buf);
-	} while (ret < 0 && errno == EINTR);
-	__END_INTERRUPTABLE__
-	if (ret < 0) {
-	    @global(LastErrorNumber) = __mkSmallInteger(errno);
-	    RETURN (nil);
-	}
-	osSeconds = __MKUINT(buf.st_atime);
+        printf("stat on '%s' for timeOfLastAccess\n", __stringVal(encodedPathName));
+# endif
+        __BEGIN_INTERRUPTABLE__
+        do {
+            ret = stat((char *) __stringVal(encodedPathName), &buf);
+        } while (ret < 0 && errno == EINTR);
+        __END_INTERRUPTABLE__
+        if (ret < 0) {
+            @global(LastErrorNumber) = __mkSmallInteger(errno);
+            RETURN (nil);
+        }
+        osSeconds = __MKUINT(buf.st_atime);
     }
 %}.
     osSeconds notNil ifTrue:[^ Timestamp fromOSTime:(osSeconds * 1000)].
@@ -5141,29 +5183,31 @@
      For nonexistent files, nil is returned."
 
     "could be implemented as:
-	(self infoOf:aPathName) modified
-    "
-
-    |osSeconds i|
+        (self infoOf:aPathName) modified
+    "
+
+    |osSeconds i encodedPathName|
+
+    encodedPathName := self encodePath:aPathName.
 %{
     struct stat buf;
     int ret;
     time_t mtime;
 
-    if (__isStringLike(aPathName)) {
+    if (__isStringLike(encodedPathName)) {
 # ifdef TRACE_STAT_CALLS
-	printf("stat on '%s' for timeOfLastChange\n", __stringVal(aPathName));
-# endif
-	__BEGIN_INTERRUPTABLE__
-	do {
-	    ret = stat((char *) __stringVal(aPathName), &buf);
-	} while (ret < 0 && errno == EINTR);
-	__END_INTERRUPTABLE__
-	if (ret < 0) {
-	    @global(LastErrorNumber) = __mkSmallInteger(errno);
-	    RETURN ( nil );
-	}
-	osSeconds = __MKUINT(buf.st_mtime);
+        printf("stat on '%s' for timeOfLastChange\n", __stringVal(encodedPathName));
+# endif
+        __BEGIN_INTERRUPTABLE__
+        do {
+            ret = stat((char *) __stringVal(encodedPathName), &buf);
+        } while (ret < 0 && errno == EINTR);
+        __END_INTERRUPTABLE__
+        if (ret < 0) {
+            @global(LastErrorNumber) = __mkSmallInteger(errno);
+            RETURN ( nil );
+        }
+        osSeconds = __MKUINT(buf.st_mtime);
     }
 %}.
     osSeconds notNil ifTrue:[^ Timestamp fromOSTime:(osSeconds * 1000)].
@@ -5182,11 +5226,13 @@
      nil is returned.
      Notice: for symbolic links, the type of the pointed-to file is returned."
 
-    |i|
+    |i osSeconds encodedPathName|
+
+    encodedPathName := self encodePath:aPathName.
 
     "
      this could have been implemented as:
-	(self infoOf:aPathName) type
+        (self infoOf:aPathName) type
      but for huge directory searches the code below is faster
     "
 
@@ -5194,47 +5240,47 @@
     struct stat buf;
     int ret;
 
-    if (__isStringLike(aPathName)) {
+    if (__isStringLike(encodedPathName)) {
 # ifdef TRACE_STAT_CALLS
-	printf("stat on '%s' for type\n", __stringVal(aPathName));
-# endif
-	__BEGIN_INTERRUPTABLE__
-	do {
-	    ret = stat((char *) __stringVal(aPathName), &buf);
-	} while (ret < 0 && errno == EINTR);
-	__END_INTERRUPTABLE__
-	if (ret < 0) {
-	    @global(LastErrorNumber) = __mkSmallInteger(errno);
-	    RETURN ( nil );
-	}
-	switch (buf.st_mode & S_IFMT) {
-	    case S_IFDIR:
-		RETURN ( @symbol(directory) );
-	    case S_IFREG:
-		RETURN ( @symbol(regular) );
+        printf("stat on '%s' for type\n", __stringVal(encodedPathName));
+# endif
+        __BEGIN_INTERRUPTABLE__
+        do {
+            ret = stat((char *) __stringVal(encodedPathName), &buf);
+        } while (ret < 0 && errno == EINTR);
+        __END_INTERRUPTABLE__
+        if (ret < 0) {
+            @global(LastErrorNumber) = __mkSmallInteger(errno);
+            RETURN ( nil );
+        }
+        switch (buf.st_mode & S_IFMT) {
+            case S_IFDIR:
+                RETURN ( @symbol(directory) );
+            case S_IFREG:
+                RETURN ( @symbol(regular) );
 # ifdef S_IFCHR
-	    case S_IFCHR:
-		RETURN ( @symbol(characterSpecial) );
+            case S_IFCHR:
+                RETURN ( @symbol(characterSpecial) );
 # endif
 # ifdef S_IFBLK
-	    case S_IFBLK:
-		RETURN ( @symbol(blockSpecial) );
+            case S_IFBLK:
+                RETURN ( @symbol(blockSpecial) );
 # endif
 # ifdef S_IFLNK
-	    case S_IFLNK:
-		RETURN ( @symbol(symbolicLink) );
+            case S_IFLNK:
+                RETURN ( @symbol(symbolicLink) );
 # endif
 # ifdef S_IFSOCK
-	    case S_IFSOCK:
-		RETURN ( @symbol(socket) );
+            case S_IFSOCK:
+                RETURN ( @symbol(socket) );
 # endif
 # ifdef S_IFIFO
-	    case S_IFIFO:
-		RETURN ( @symbol(fifo) );
-# endif
-	    default:
-		RETURN ( @symbol(unknown) );
-	}
+            case S_IFIFO:
+                RETURN ( @symbol(fifo) );
+# endif
+            default:
+                RETURN ( @symbol(unknown) );
+        }
     }
 %}.
     i := self infoOf:aPathName.
@@ -8379,6 +8425,23 @@
 
 !UnixOperatingSystem class methodsFor:'path queries'!
 
+decodePath:encodedPathName 
+    "decode the pathName as returned by system calls.
+     E.g. linux system calls return sigle byte strings only,
+     so the pathName has been UTF-8 decoded."
+    
+    "linux strings are in UTF8 (in contemporary linux versions)"
+    encodedPathName notNil ifTrue:[
+        [
+            ^ encodedPathName utf8Decoded.
+        ] on:InvalidEncodingError do:[:ex|
+            "maybe there are old filenames in ISO8859-x,
+             just keep them untranslated"
+        ].
+    ].
+    ^ encodedPathName
+!
+
 defaultSystemPath
     "add additional directories to the systemPath
      (but only, if the major version is the same)"
@@ -8427,6 +8490,14 @@
     "
      OperatingSystem defaultSystemPath
     "
+!
+
+encodePath:pathName 
+    "encode the pathName for use with system calls.
+     E.g. linux system calls accept sigle byte strings only,
+     so the pathName has been UTF-8 encoded, before using it in a system call."
+    
+    ^ pathName utf8Encoded
 ! !
 
 !UnixOperatingSystem class methodsFor:'private'!
@@ -13292,11 +13363,11 @@
 !UnixOperatingSystem class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/UnixOperatingSystem.st,v 1.289 2012-12-13 11:13:51 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/UnixOperatingSystem.st,v 1.290 2012-12-13 13:20:12 stefan Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libbasic/UnixOperatingSystem.st,v 1.289 2012-12-13 11:13:51 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/UnixOperatingSystem.st,v 1.290 2012-12-13 13:20:12 stefan Exp $'
 ! !
 
 UnixOperatingSystem initialize!