Skip to content

long symlinks: libuv stat throws errors where /bin/stat doesn't #49828

@maleadt

Description

@maleadt

Courtesy of Mads.jl, we have this fun symlink:

❯ ls -lah Mads.jl/examples/model_analysis/models/internal-polynomial.jl
lrwxrwxrwx 1 tim tim 472 May 16 12:15 Mads.jl/examples/model_analysis/models/internal-polynomial.jl -> import Mads
import OrderedCollections

function makemadsmodelrun_internal_polynomial(madsdata::AbstractDict)
	times = Mads.getobstime(madsdata)
	names = Mads.getobskeys(madsdata)
	function madsmodelrun(parameters::AbstractDict) # model run
		f(t) = parameters["a"] * (t ^ parameters["n"]) + parameters["b"] * t + parameters["c"] # a * t^n + b * t + c
		predictions = OrderedCollections.OrderedDict{String, Float64}(zip(names, map(f, times)))
		return predictions
	end
end

Yes, this is a symlink pointing to Julia code instead of to a file containing Julia code. As you can see, ls doesn't care, and /bin/stat works fine as well:

❯ stat Mads.jl/examples/model_analysis/models/internal-polynomial.jl
  File: Mads.jl/examples/model_analysis/models/internal-polynomial.jl -> import Mads
import OrderedCollections

function makemadsmodelrun_internal_polynomial(madsdata::AbstractDict)
	times = Mads.getobstime(madsdata)
	names = Mads.getobskeys(madsdata)
	function madsmodelrun(parameters::AbstractDict) # model run
		f(t) = parameters["a"] * (t ^ parameters["n"]) + parameters["b"] * t + parameters["c"] # a * t^n + b * t + c
		predictions = OrderedCollections.OrderedDict{String, Float64}(zip(names, map(f, times)))
		return predictions
	end
end

  Size: 472       	Blocks: 8          IO Block: 4096   symbolic link
Device: 0,40	Inode: 48188       Links: 1
Access: (0777/lrwxrwxrwx)  Uid: ( 1000/     tim)   Gid: ( 1000/     tim)
Access: 2023-05-16 12:47:44.516243458 +0200
Modify: 2023-05-16 12:15:27.991656675 +0200
Change: 2023-05-16 12:15:27.991656675 +0200
 Birth: 2023-05-16 12:15:27.991656675 +0200
statx(AT_FDCWD, "Mads.jl/examples/model_analysis/models/internal-polynomial.jl", AT_STATX_SYNC_AS_STAT|AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT, STATX_ALL, {stx_mask=STATX_ALL|STATX_MNT_ID, stx_attributes=0, stx_mode=S_IFLNK|0777, stx_size=472, ...}) = 0

Julia/libuv however don't like this symlink:

❯ julia -e 'stat("Mads.jl/examples/model_analysis/models/internal-polynomial.jl")'
ERROR: IOError: stat("Mads.jl/examples/model_analysis/models/internal-polynomial.jl"): name too long (ENAMETOOLONG)
Stacktrace:
 [1] uv_error
   @ ./libuv.jl:97 [inlined]
 [2] stat(path::String)
   @ Base.Filesystem ./stat.jl:152
 [3] top-level scope
   @ none:1
[pid 17416] statx(AT_FDCWD, "Mads.jl/examples/model_analysis/models/internal-polynomial.jl", AT_STATX_SYNC_AS_STAT, STATX_ALL,  <unfinished ...>
[pid 17416] <... statx resumed>0x7ffc0bb7cc80) = -1 ENAMETOOLONG (File name too long)

Note that the Julia code here is around 500 chars, so nothing near PATH_MAX (4096 on my system). In fact, it looks like the limit is 256 characters:

julia> touch("a"^255)

julia> symlink(path, "foo")

julia> stat("foo")
ERROR: IOError: stat("foo"): name too long (ENAMETOOLONG)

shell> stat foo
  File: foo -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

I don't particularly care about this 'bug', but PkgEval encountered it in the wild (doing isdir for recursive chmod) and it seemed like a curious mismatch between coreutils and libuv.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugIndicates an unexpected problem or unintended behaviorfilesystemUnderlying file system and functions that use itupstreamThe issue is with an upstream dependency, e.g. LLVM

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions