Project

General

Profile

Bug #10067

File.file? misleading semantics & documentation for symbolic links

Added by robe (Michael Renner) almost 6 years ago. Updated almost 6 years ago.

Status:
Closed
Priority:
Normal
Target version:
ruby -v:
ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]
[ruby-core:63842]

Description

The documentation for File.file? states:

"Returns true if the named file exists and is a regular file."

When trying that out I get the following results:

% /usr/bin/stat link
  File: `link' -> `file'
  Size: 4           Blocks: 0          IO Block: 4096   symbolic link
Device: 16h/22d Inode: 2804357     Links: 1
Access: (0777/lrwxrwxrwx)  Uid: ( 1000/    robe)   Gid: ( 1000/    robe)
Access: 2014-07-19 01:01:51.514979670 +0200
Modify: 2014-07-19 01:01:50.799975936 +0200
Change: 2014-07-19 01:01:50.799975936 +0200
 Birth: -
% ruby -e "puts File.file?('link')"
false
% ruby -e "puts File.symlink?('link')"
true
% touch file
% ruby -e "puts File.file?('link')"
true
% ruby -e "puts File.symlink?('link')"
true
%

which is entirely not what one would expect.

You need to decide if the File ?-methods offer stat OR lstat semantic, change it and document it accordingly.

The current documentation and implementation behavior is especially confusing since the POSIX standard states that the type of a file can be either a regular file OR a symlink, not both at the same time.

Updated by nobu (Nobuyoshi Nakada) almost 6 years ago

  • Category changed from core to doc
  • Assignee set to zzak (Zachary Scott)
  • Target version set to 2.2.0

It's same as test(1) command.

Updated by jaredbeck (Jared Beck) almost 6 years ago

I can confirm that test -f and File.file? seem to have the same return values in this example:

ln -s link file
ruby -e 'puts File.file?("link")'
false
test -f link; echo $?
1
touch file
ruby -e 'puts File.file?("link")'
true
test -f link; echo $?
0

Though, I'm using ruby 2.1.2 on mac os 10.9.4, so your mileage may vary :)

ruby --version
ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin13.0]

Updated by nobu (Nobuyoshi Nakada) almost 6 years ago

Citing from POSIX manpage test(1)

With the exception of the -h pathname and -L pathname primaries,
if a pathname argument is a symbolic link, test shall evaluate the
expression by resolving the symbolic link and using the file
referenced by the link.

Updated by robe (Michael Renner) almost 6 years ago

Nobuyoshi Nakada wrote:

Citing from POSIX manpage test(1)

With the exception of the -h pathname and -L pathname primaries,
if a pathname argument is a symbolic link, test shall evaluate the
expression by resolving the symbolic link and using the file
referenced by the link.

Oh my, just double-checked, Python and Perl have implemented the same behaviour as test(1), along with Ruby.

The big difference being the wording of the documentation. The test man page explicitly states:

True if pathname resolves to an existing directory entry for a [..]

as well as the paragraph you quoted.

I guess clarifying that in the File documentation is warranted as well as pointing out that people are strongly advised to use lstat if they want consistent behaviour.

I personally would go as far and ditch the test(1) semantics and stick to querying lstat() by default, but that's just me and will probably break lots of things ;)

Updated by zzak (Zachary Scott) almost 6 years ago

  • Status changed from Open to Assigned

Thanks, I'll see if I can clean up any misunderstandings here

Updated by zzak (Zachary Scott) almost 6 years ago

  • Status changed from Assigned to Closed
  • % Done changed from 0 to 100

Applied in changeset r46978.


  • file.c: [DOC] Clarify how File.file? handles symbolic links. Also cleaned up the rdoc style for this method, more to follow. Originally reported by Michael Renner [Bug #10067]

Also available in: Atom PDF