On Jan 20, 2007, at 1:44 PM, Alastair Bridgewater wrote:
> Hello all,
> SBCL/Win32 signals an error "No such file or directory" when
> attempting to
> open the "NUL" device for reading. This is an old-style DOS device
> and as such can always be opened in any directory. We actually
> rely on
> being able to open NUL in two places so far: the build process uses
> "--userinit NUL --sysinit NUL" and the sb-md5 contrib attempts to
> take the
> md5sum of NUL (/dev/null on non-windows systems) during its test
> phase. We
> -should- be trying to do the same in the test suite as well, but
> at least
> that doesn't impact the build process.
> So, why are we signalling a file not found? Because we are using
> stat(2) to
> see if the file exists (or to find out some information about the
> old file),
> which in turn uses FindFirstFile(), which looks for files in a
> not device files.
> I'm not sure what to do here, particularly given that this is a
> compatability mess on both the SBCL side and the Win32 side (stat
> (2) isn't
> in the platform API, it's part of msvcrt specifically for
> compatability with
> unix programs, and we all know how well that worked for signal(2),
> we?), so I'm planning to leave it alone for a while.
Actually, even the windows native APIs can't stat NUL.
GetFileAttributesExW returns Error 22. So the only way to fix this is
to not try to stat the device, but just go straight for open.
But, anyhow, if anything is to be done about this situation in
general, I'd suggest that SBCL explicitly *not* support the dos-
device "file in every dir" behavior. It should do all file access
with the windows unicode APIs, and always provide "\\?\"-prefixed
pathnames. This allows access to all files that can actually exist,
including ones with special device names like NUL, characters not
encodable in the system charset (utf8 is not an allowable system
encoding in windows), and paths that are longer than 260 characters.
Please do note that a file called "NUL" can actually exist in a
directory on windows!
"\\?\" is the root of the "dos device" namespace, containing entries
like C:, NUL, PRN, UNC, COM1, etc. (and of course you can't list that
dir, but if you really want to know what's available there, you can
use the QueryDosDevices() call.). The only real restriction is that
you must always provide absolute paths, so the current directory has
to be maintained manually.
Given that CL already has a pathname abstraction, it shouldn't be a
big deal for the pathname abstraction to translate into the platform
path syntax which actually works rather than the one which is
C:\foo\bar.txt -> \\?\C:\foo\bar.txt
\\servername\share\foo.txt -> \\?\UNC\servername\share\foo.txt
Note that mscrt's stat also has another interesting "feature" where
by all files on NTFS partitions have their timestamps change by an
hour every daylight savings time transition. That's not a problem
with the underlying windows APIs, only with stat. Wonderfully
But, I'm not actually volunteering to do any of this work, just
imparting some hopfully useful information. :)