+2025-06-13 Bruno Haible <bruno@clisp.org>
+
+ stat: Support the file name "/dev/null" on native Windows.
+ Reported by Collin Funk in
+ <https://lists.gnu.org/archive/html/bug-gnulib/2025-06/msg00119.html>.
+ * lib/stat.c (rpl_stat): On native Windows, map "/dev/null" to "NUL".
+ * tests/test-fstat.c (main): Test /dev/null also on native Windows.
+ * tests/test-stat.h (test_stat_func): Likewise.
+ * tests/test-lstat.h (test_lstat_func): Likewise.
+ * doc/posix-functions/stat.texi: Mention problem of null device name.
+ * doc/posix-functions/lstat.texi: Likewise.
+
2025-06-12 Bruno Haible <bruno@clisp.org>
lstat tests: Avoid test failure on Solaris.
offset from @code{tv_sec}. Solaris 11.4 is similar, except that
@code{tv_sec} might also be @minus{}1000000000.
@item
+On Windows platforms (excluding Cygwin), a different name has to be used
+for the null device, namely @code{"NUL"} instead of @code{"/dev/null"}.
+@item
On Windows platforms (excluding Cygwin), symlinks are not supported, so
@code{lstat} does not exist.
@end itemize
@minus{}999999999..@minus{}1, representing a negative nanoseconds
offset from @code{tv_sec}. Solaris 11.4 is similar, except that
@code{tv_sec} might also be @minus{}1000000000.
+@item
+On Windows platforms (excluding Cygwin), a different name has to be used
+for the null device, namely @code{"NUL"} instead of @code{"/dev/null"}.
@end itemize
Portability problems not fixed by Gnulib:
around length limitations
<https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file> ? */
+ /* To ease portability. Like in open.c. */
+ if (strcmp (name, "/dev/null") == 0)
+ name = "NUL";
+
/* POSIX <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13>
specifies: "More than two leading <slash> characters shall be treated as
a single <slash> character." */
int fd;
struct stat statbuf;
-#if defined _WIN32 && !defined __CYGWIN__
- fd = open ("NUL", O_RDWR);
-#else
fd = open ("/dev/null", O_RDWR);
-#endif
ASSERT (fstat (fd, &statbuf) == 0);
close (fd);
ASSERT (!S_ISREG (statbuf.st_mode));
/* /dev/null is a character device.
Except on Solaris, where it is a symlink. */
-#if defined _WIN32 && !defined __CYGWIN__
- ASSERT (func ("NUL", &st1) == 0);
-#else
ASSERT (func ("/dev/null", &st1) == 0);
-#endif
ASSERT (!S_ISREG (st1.st_mode));
#if !defined __sun
ASSERT (S_ISCHR (st1.st_mode));
ASSERT (errno == ENOTDIR);
/* /dev/null is a character device. */
-#if defined _WIN32 && !defined __CYGWIN__
- ASSERT (func ("NUL", &st1) == 0);
-#else
ASSERT (func ("/dev/null", &st1) == 0);
-#endif
ASSERT (!S_ISREG (st1.st_mode));
ASSERT (S_ISCHR (st1.st_mode));