A tale of two path separators(alexwlchan.net) |
A tale of two path separators(alexwlchan.net) |
Double colon (::) meant the same as .. on Unix/DOS, that is "go up one level". So you have to be careful when concatenating paths to not get double separators.
Paths starting with : were relative. If a path didn't start with the separator, the first component was the volume name (disk partition). Again, quite unlike Unix.
Also, remember it was common to have spaces in names on Mac, even the default harddrive on Macs was named "Macintosh HD". So an absolute path like "Macintosh HD:Programs:MacWrite" would have been common. (I grew up with Macs in Swedish, so I'm back translating the names here, could be that the names were slightly different in English.)
$ cat <<'EOF' >x.lisp
heredoc> (require :uiop)
heredoc> (let ((p (make-pathname :name "foo:bar")))
heredoc> (format t "~@{~A~%~}" (namestring p) (uiop:native-namestring p)))
heredoc> EOF
$ ccl -b -Q -l x.lisp </dev/null
foo\:bar
foo:bar
$ sbcl --script x.lisp
foo:bar
foo:bar $ touch "foo:bar"
In the Terminal, then Finder renders it as foo/bar.So who is lying, how is it stored in the directory entry in APFS itself?
(Other characters of course cause usability problems and are potentially even a security vulnerability depending on the terminal. But they're still "valid".)
Windows handles slash as well, also part of a unification with UNIX style paths intended for XEDOS.
I want to call such aliases "normal" files, as opposed to a link, but the path description is saved in the Resource Fork of the file, not the Data fork.
Resolving an alias can involve network path traversal. You can make an alias of a file on an AFP volume and save it locally, and the next time you use the alias the volume will be auto mounted if necessary. I think you can get similar behavior from other OS configurations.
I seem to recall that if you move or rename a file, the system will update the alias for you. It can't always figure this out. But it will try. That's something you might not see elsewhere...
I've forgotten why AppleScript returns alias objects instead of strings.
For NT-based Windows: only in cmd.exe, and other apps which choose to support the same convention. The NT/Win32 API only supports a single per-process directory
There is actually space in NT data structures to store per-drive current directory, but no released version has ever used it. I think they planned to implement the idea in NT itself (or NT’s implementation of Win32), but then settled on just having a single current directory per-process, and faking the old behaviour in cmd.exe using environment variables
By contrast, Windows 1.x/2.x/3.x/9x/Me retained the old DOS behaviour of per-drive current directories, so Win32 does actually have them if you mean the Win32s or 9x/Me implementations of Win32.
Separately, both Linux and macOS support per-thread current directories separate from the per-process current directory, although by default all threads use the process-wide current directory. Last I checked, the macOS implementation was a bit more sophisticated, in that on Linux once the link between process and thread current directory was severed, it was gone for the lifetime of the thread; by contrast, macOS has an API to re-establish it.
C:\WINDOWS\system32>cd D:\backups\some-huge-directory
C:\WINDOWS\system32>del /s *
Oops. I learned to look twice before running a big dangerous command. And to use /d.Though nowadays system files should be protected even from admin and even if you do manage to delete them, Windows can restore them.
RTL_USER_PROCESS_PARAMETERS has a field “RTL_DRIVE_LETTER_CURDIR CurrentDirectores[32]” (note the misspelling). And then RTL_DRIVE_LETTER_CURDIR is defined as:
typedef struct _RTL_DRIVE_LETTER_CURDIR
{
WORD Flags;
WORD Length;
ULONG TimeStamp;
STRING DosPath;
} RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR;
But, AFAIK, Microsoft has never shipped anything that uses it. My own impression is this was the original design for handling compatibility with the DOS current directory behaviour, but they ended up deciding on doing it in cmd.exe instead. And of course, NTVDM and 16-bit Windows app support, but I think that just used the 16-bit DOS code and its associated data structures.https://www.geoffchappell.com/studies/windows/km/ntoskrnl/in...
macOS supports case-insensitivity[0] and performs unicode normalization[1] on filenames, and decomposes name data to an extent that the question "what does the fs see" is a bit moot.
With that said, the internal storage of filenames in APFS are a nul-terminated UTF-8 string[2], with (i'm pretty sure) colons as colons, which the Finder displays as slashes.
[0] if you make a file named "Makefile" then touch a file named "makefile", it'll touch the first file, instead of making a second file.
[1] if you make a file named "schön" (s-c-h-combining¨-o-n) and then search for (s-c-h-ö-n), you can find it, or vice versa. The particular normalization/canonicalization used is NFD.
[2] j_drec_key_t description in https://developer.apple.com/support/downloads/Apple-File-Sys...
Well, strictly speaking Linux does too, since it supports mounting local or remote filesystems with this feature
For a long time, the real distinction was that “native” Linux filesystems didn’t support it, but “foreign” ones did. However, nowadays even some of the “native” filesystems have optional support for case-insensitivity (e.g. casefold feature on ext4)
The real difference now: on macOS, it is normal to have this feature turned on, exceptional to have it disabled; on Linux, it is the other way around
Combining marks come after the character they modify, btw. (Presumably thanks to support from things like harfbuzz, modern systems will happily put two dots above an h.)
Path separators, whether to accept directory entries with path separator in them, etc. are usually handled layer above