Re: Resolving relative path on AFS broken in newer version

Max Chernoff <[email protected]> Wed, 01 Jul 2026 01:36:46 -0600
Newsgroups gmane.comp.tex.live,gmane.comp.tex.tex-k
Message-ID <[email protected]>
Hi Michael,

On Wed, 2026-07-01 at 08:27 +0200, [email protected] wrote:
> Anyway here are the results of running with test.tex:

Thanks!

> [...]
> chdir("..")                             =3D 0
> openat(AT_FDCWD, ".", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) =3D 5
> fstat(5, {st_mode=3DS_IFDIR|0700, st_size=3D40960, ...}) =3D 0
> getdents64(5, 0x557db77a4360 /* 696 entries */, 32768) =3D 26424
> newfstatat(AT_FDCWD, ".", {st_mode=3DS_IFDIR|0700, st_size=3D40960, ...},=
 AT_SYMLINK_NOFOLLOW) =3D 0
> newfstatat(AT_FDCWD, "..", {st_mode=3DS_IFDIR|0755, st_size=3D22528, ...}=
, AT_SYMLINK_NOFOLLOW) =3D 0
> newfstatat(AT_FDCWD, "mpi", {st_mode=3DS_IFDIR|0755, st_size=3D10240, ...=
}, AT_SYMLINK_NOFOLLOW) =3D 0
> newfstatat(AT_FDCWD, ".", {st_mode=3DS_IFDIR|0700, st_size=3D40960, ...},=
 0) =3D 0
> close(5)                                =3D 0
> chdir("..")                             =3D 0
> openat(AT_FDCWD, ".", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) =3D 5
> fstat(5, {st_mode=3DS_IFDIR|0755, st_size=3D22528, ...}) =3D 0
> getdents64(5, 0x557db77a4360 /* 639 entries */, 32768) =3D 20288
> newfstatat(AT_FDCWD, ".", {st_mode=3DS_IFDIR|0755, st_size=3D22528, ...},=
 AT_SYMLINK_NOFOLLOW) =3D 0
> newfstatat(AT_FDCWD, "..", {st_mode=3DS_IFDIR|0777, st_size=3D2048, ...},=
 AT_SYMLINK_NOFOLLOW) =3D 0
> newfstatat(AT_FDCWD, "d3gast", {st_mode=3DS_IFDIR|0755, st_size=3D4096, .=
..}, AT_SYMLINK_NOFOLLOW) =3D 0
> [...]

The only code in TL that follows this pattern of

    chdir("..");
    opendir(".");
    for (...) {
        if (lstat(path) !=3D 0) {
            perror(path);
        }
    }

is in texk/kpathsea/xgetcwd.c:

    https://github.com/TeX-Live/texlive-source/blob/ac2a0257/texk/kpathsea/=
xgetcwd.c#L95-L102

However, this code shouldn't run on any remotely modern system. But this
is the only place where this sequence of syscalls appears, so I suspect
that there's a Configure bug here. You said that it worked before,
r77486 and r78928 are the only recent changes to this file, and r78928
was committed after the release of TL26, so I suspect that r77486 broke
something here and made your copy of pdfTeX use the
ancient-compatibility code path instead of the modern one. Karl?

Also, I believe that AFS is analogous to NFS, and r78928 added the comment

    Doesn't work under NFS.

to "xgetcwd.c", so I guess the fact that this specific function fails
isn't terribly surprising. Still, it seems not great that this
completely prevents TeX from running.

> newfstatat(AT_FDCWD, "dwmoreau", 0x7fff1c1bf880, AT_SYMLINK_NOFOLLOW) =3D=
 -1 ENODEV (No such device)
> pdftex: dwmoreau: No such device

As an aside, this is a rather unexpected error code. The man page for
newfstatat(2) doesn't list it as a valid error code:

    https://man7.org/linux/man-pages/man2/newfstatat.2.html#ERRORS

and the closely-related description in the openat(2) man page doesn't
seem to fit here either:

    ENODEV path refers to a device special file and no corresponding
           device exists.  (This is a Linux kernel bug; in this
           situation ENXIO must be returned.)

    https://man7.org/linux/man-pages/man2/openat.2.html#ERRORS:~:text=3DENO=
DEV

The description in fuse(4) is a little bit closer:

    ENODEV Returned from read(2) and write(2) if the FUSE filesystem
           was unmounted.

    https://man7.org/linux/man-pages/man4/fuse.4.html#ERRORS:~:text=3DENODE=
V

but stat(2) is quite different from read(2) and write(2), so this
doesn't really seem correct either.

OpenAFS's behaviour here does appear to be intentional:

    https://gerrit.openafs.org/#/c/11788/

but since this is completely undocumented, it's not terribly surprising
that this breaks some programs. If you have some time to spare, I'd
recommend reporting this to the stat(2) man page maintainers:

    https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/CONTRI=
BUTING.d/bugs

    https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/CONTRI=
BUTING.d/mail

(I'm not really sure about how OpenAFS and the Linux kernel are related,
so it may be better to report it to the OpenAFS maintainers instead, but
you probably have a better idea of this than I do.)

Thanks,
-- Max