Crystal: File.info fails on a broken symlink

Created on 20 Apr 2020  路  14Comments  路  Source: crystal-lang/crystal

Steps to reproduce:

  1. Create a broken symlink: ln -s foo bar
  2. Do crystal eval 'File.info("./bar").type'

Error:

Unhandled exception: Unable to get file info: './bar': No such file or directory (File::NotFoundError)
  from /usr/share/crystal/src/file.cr:150:37 in 'info'
  from /usr/share/crystal/src/file.cr:149:3 in 'info'
  from /eval:1:1 in '__crystal_main'
  from /usr/share/crystal/src/crystal/main.cr:105:5 in 'main_user_code'
  from /usr/share/crystal/src/crystal/main.cr:91:7 in 'main'
  from /usr/share/crystal/src/crystal/main.cr:114:3 in 'main'
  from __libc_start_main
  from _start
  from ???

Crystal 0.34.0 [4401e90f0] (2020-04-06)

LLVM: 8.0.0
Default target: x86_64-unknown-linux-gnu

Most helpful comment

In Ruby it causes no surprise:

File.symlink?("./bar") # => true
File.ftype("./bar") # => link.

It feels like follow_symlinks should be false by default (less surprise).

All 14 comments

I would argue not a bug. That's what the follow_symlinks named parameter is for.

https://crystal-lang.org/api/0.34.0/File.html#info(path:Path|String,follow_symlinks=true):Info-class-method

follow_symlinks: true leads to exactly the same exception.

The problem is, File.info().symlink? is a shortcut for File.info().type.symlink? (as it stated in the doc).
Now, it is very confusing to run File.info("./bar").symlink? and get the exception.

follow_symlinks: true leads to exactly the same exception.

Yes of course, since that's the default value. The broken symlink is followed and thus the error is raised.

To check whether something is a symlink one always has to File.info(path, follow_symlinks: false).symlink?, File.info(path).symlink? will always be false or raise.

We could talk about a more convenient API (File.symlink?(path)?), but there's no bug.

In Ruby it causes no surprise:

File.symlink?("./bar") # => true
File.ftype("./bar") # => link.

It feels like follow_symlinks should be false by default (less surprise).

The fairer comparison to our current API would be File.stat("bar") which gives

Traceback (most recent call last):
    1: from -e:1:in `<main>'
-e:1:in `stat': No such file or directory @ rb_file_s_stat - bar (Errno::ENOENT) 

@jhass Hmm, I see.

If the team is going to keep the follow_symlinks as is, I will close the issue and open another one, dedicated to File.info().symlink? specifically.

Yes, follow_symlinks should be false, to be consistent with File.chown and File.same?.

File.info(path).symlink? will always be false or raise.

It looks weird, but since it is expected, closing.

The issue may be solved, but do we still want to have follow_symlinks: true by default?
Or otherwise, why having it to false by default on File.chown and File.same? then?

I think the status quo makes sense and will lead to expected behavior more often than to unexpected behavior. I would be open to add a File.symlink? and perhaps even dropping the symlink? helper on File::Info to reduce confusion.

The current behaviour is correct and the same as ruby.

That's wrong @RX14 for File.chown.
In Ruby, it follows symlinks by default - here not.

There are the lchown and lstat methods which don't follow symlinks.

See https://ruby-doc.org/core-2.7.1/File.html

I'm happy to change that default.

Was this page helpful?
0 / 5 - 0 ratings