Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

open() call with a directory path #12713

Open
p5pRT opened this issue Jan 19, 2013 · 7 comments
Open

open() call with a directory path #12713

p5pRT opened this issue Jan 19, 2013 · 7 comments

Comments

@p5pRT
Copy link

p5pRT commented Jan 19, 2013

Migrated from rt.perl.org#116453 (status was 'open')

Searchable as RT116453$

@p5pRT
Copy link
Author

p5pRT commented Jan 19, 2013

From victor@vsespb.ru

Created by victor@vsespb.ru

perl -e 'open(F, "</tmp") && -d "/tmp" && print "OK"'

seems open can take directory name as argument and not throw any error.
looks like C version act same way.

But I would suggest to document this behaviour, cause perl "open" POD
page full of examples like

open(my $fh, "<", "input.txt")
  or die "cannot open < input.txt​: $!";

which in fact won't catch error in case 'input.txt' is directory.

Perl Info

Flags:
    category=docs
    severity=low

Site configuration information for perl 5.10.1:

Configured by Debian Project at Tue Nov 27 00:14:30 UTC 2012.

Summary of my perl5 (revision 5 version 10 subversion 1) configuration:

  Platform:
    osname=linux, osvers=2.6.42-23-generic,
archname=x86_64-linux-gnu-thread-multi
    uname='linux komainu 2.6.42-23-generic #36-ubuntu smp tue apr 10
20:39:51 utc 2012 x86_64 gnulinux '
    config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN
-Dcccdlflags=-fPIC -Darchname=x86_64-linux-gnu -Dprefix=/usr
-Dprivlib=/usr/share/perl/5.10 -Darchlib=/usr/lib/perl/5.10
-Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5
-Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local
-Dsitelib=/usr/local/share/perl/5.10.1
-Dsitearch=/usr/local/lib/perl/5.10.1 -Dman1dir=/usr/share/man/man1
-Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1
-Dsiteman3dir=/usr/local/man/man3 -Dman1ext=1 -Dman3ext=3perl
-Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Ud_ualarm -Uusesfio
-Uusenm -DDEBUGGING=-g -Doptimize=-O2 -Duseshrplib
-Dlibperl=libperl.so.5.10.1 -Dd_dosuid -des'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN
-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2 -g',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing
-pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.4.3', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t',
lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib /lib64 /usr/lib64
    libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt
    perllibs=-ldl -lm -lpthread -lc -lcrypt
    libc=/lib/libc-2.11.1.so, so=so, useshrplib=true, libperl=libperl.so.5.10.1
    gnulibc_version='2.11.1'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -g -L/usr/local/lib
-fstack-protector'

Locally applied patches:



@INC for perl 5.10.1:
    /etc/perl
    /usr/local/lib/perl/5.10.1
    /usr/local/share/perl/5.10.1
    /usr/lib/perl5
    /usr/share/perl5
    /usr/lib/perl/5.10
    /usr/share/perl/5.10
    /usr/local/lib/site_perl
    .


Environment for perl 5.10.1:
    HOME=/root
    LANG=ru_RU.utf8
    LANGUAGE=en_US:en
    LC_MESSAGES=en_US.UTF-8
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
    PERL_BADLANG (unset)
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Jan 20, 2013

From @jkeenan

On Sat Jan 19 01​:32​:09 2013, vsespb wrote​:

This is a bug report for perl from victor@​vsespb.ru,
generated with the help of perlbug 1.39 running under perl 5.10.1.

-----------------------------------------------------------------
[Please describe your issue here]

perl -e 'open(F, "</tmp") && -d "/tmp" && print "OK"'

seems open can take directory name as argument and not throw any
error.
looks like C version act same way.

But I would suggest to document this behaviour, cause perl "open" POD
page full of examples like

open(my $fh, "<", "input.txt")
or die "cannot open < input.txt​: $!";

which in fact won't catch error in case 'input.txt' is directory.

Looks like the problem appears when you open for reading, but not for
writing​:

#####
[parrot] 514 $ perl -e 'open my $M, q{>}, q{/tmp} or die qq{Unable to
open};'
Unable to open at -e line 1.
[parrot] 515 $ perl -e 'open my $M, q{<}, q{/tmp} or die qq{Unable to
open};'
[parrot] 516 $ perl -e 'open my $M, qq{>/tmp} or die qq{Unable to open};'
Unable to open at -e line 1.
[parrot] 517 $ perl -e 'open my $M, qq{</tmp} or die qq{Unable to open};'
#####

@p5pRT
Copy link
Author

p5pRT commented Jan 20, 2013

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Jan 20, 2013

From victor@vsespb.ru

yes, only for reading.

another confusing thing that file size is > 0 and eof is true for just
opened file.

perl -e 'open(F, "</tmp") && -d "/tmp" && -s "/tmp" && eof F && print "OK"'

prints OK

I am sure this is intended behaviour.. but point is perl documentation
is a bit confusing, and can lead to writing buggy code..

On Sat Jan 19 16​:30​:41 2013, jkeenan wrote​:

On Sat Jan 19 01​:32​:09 2013, vsespb wrote​:

This is a bug report for perl from victor@​vsespb.ru,
generated with the help of perlbug 1.39 running under perl 5.10.1.

-----------------------------------------------------------------
[Please describe your issue here]

perl -e 'open(F, "</tmp") && -d "/tmp" && print "OK"'

seems open can take directory name as argument and not throw any
error.
looks like C version act same way.

But I would suggest to document this behaviour, cause perl "open" POD
page full of examples like

open(my $fh, "<", "input.txt")
or die "cannot open < input.txt​: $!";

which in fact won't catch error in case 'input.txt' is directory.

Looks like the problem appears when you open for reading, but not for
writing​:

#####
[parrot] 514 $ perl -e 'open my $M, q{>}, q{/tmp} or die qq{Unable to
open};'
Unable to open at -e line 1.
[parrot] 515 $ perl -e 'open my $M, q{<}, q{/tmp} or die qq{Unable to
open};'
[parrot] 516 $ perl -e 'open my $M, qq{>/tmp} or die qq{Unable to open};'
Unable to open at -e line 1.
[parrot] 517 $ perl -e 'open my $M, qq{</tmp} or die qq{Unable to open};'
#####

@p5pRT
Copy link
Author

p5pRT commented Jan 21, 2013

From @arc

Victor Efimov <perlbug-followup@​perl.org> wrote​:

perl -e 'open(F, "</tmp") && -d "/tmp" && print "OK"'

seems open can take directory name as argument and not throw any error.
looks like C version act same way.

But I would suggest to document this behaviour

This is long-standing behaviour (and, by my reading, mandated by the
applicable standards on Unixish systems)​: directories are people^W
files too. That is, they're considered files to the extent that
opening them read-only is permitted (and, on some systems, it is or
has been even useful to do so).

I do take your point that, to people who don't know that, this
behaviour may seem surprising. But `perldoc -f open` is already
several hundred lines of fairly dense prose, and it's not immediately
obvious to me that adding a note about opening directories would
improve it. Do you have a concrete suggestion for how Perl's
documentation on this topic could be improved?

--
Aaron Crane ** http​://aaroncrane.co.uk/

@p5pRT
Copy link
Author

p5pRT commented Jan 21, 2013

From @arc

Victor Efimov via RT <perlbug-followup@​perl.org> wrote​:

another confusing thing that file size is > 0 and eof is true for just
opened file.

perl -e 'open(F, "</tmp") && -d "/tmp" && -s "/tmp" && eof F && print "OK"'

prints OK

I am sure this is intended behaviour.. but point is perl documentation
is a bit confusing, and can lead to writing buggy code..

I think that's also the expected behaviour, when you're on a system
for which read(2) on a file descriptor opened on a directory returns
no data. Perl's eof builtin answers the question "is any data
available on this filehandle" (not "is this file non-empty"); if
necessary, it first tries to read data into the filehandle's buffer
before answering. In this case, reading the directory produces no
output, so eof immediately returns true.

Again, do you have a concrete suggestion for how to improve the
documentation here, given that (as far as I can tell) there's nothing
that Perl could reasonably do differently?

--
Aaron Crane ** http​://aaroncrane.co.uk/

@p5pRT
Copy link
Author

p5pRT commented Jan 21, 2013

From victor@vsespb.ru

Good news, there is http​://perldoc.perl.org/functions/open.html with
notice on top of page​:

(The following is a comprehensive reference to open()​: for a gentler
introduction you may consider perlopentut.)
And http​://perldoc.perl.org/perlopentut.html with a section "Opening
Non-File Files"
http​://perldoc.perl.org/perlopentut.html#Opening-Non-File-Files

When is a file not a file? Well, you could say when it exists but
isn't a plain file. We'll check whether it's a symbolic link first, just
in case.

if (-l $file || ! -f _) {
print "$file is not a plain file\n";
}

What other kinds of files are there than, well, files? Directories,
symbolic links, named pipes,
Unix-domain sockets, and block and character devices. Those are all
files, too--just not plain files.
This isn't the same issue as being a text file. Not all text files are
plain files.
Not all plain files are text files. That's why there are separate -f
and -T file tests.

However, on top of the page
http​://perldoc.perl.org/perlopentut.html#Simple-Opens there is a
paragraph which explains how to check errors (with "|| die"),
explanations include difference between "or" and "||",
2 arg open vs 3 arg open, leading space for 2arg open issues. well,
everything.

I propose to add

"Also, keep in mind that even if open returns success, that does not
mean that you opened plain file, see L<"Opening Non-File Files">"

after the following lines​:

Using || in the latter examples would effectively mean
which is definitely not what you want.

On Mon Jan 21 06​:10​:00 2013, perl@​aaroncrane.co.uk wrote​:

Victor Efimov via RT <perlbug-followup@​perl.org> wrote​:

another confusing thing that file size is > 0 and eof is true for
just
opened file.

perl -e 'open(F, "</tmp") && -d "/tmp" && -s "/tmp" && eof F &&
print "OK"'

prints OK

I am sure this is intended behaviour.. but point is perl
documentation
is a bit confusing, and can lead to writing buggy code..

I think that's also the expected behaviour, when you're on a system
for which read(2) on a file descriptor opened on a directory returns
no data. Perl's eof builtin answers the question "is any data
available on this filehandle" (not "is this file non-empty"); if
necessary, it first tries to read data into the filehandle's buffer
before answering. In this case, reading the directory produces no
output, so eof immediately returns true.

Again, do you have a concrete suggestion for how to improve the
documentation here, given that (as far as I can tell) there's nothing
that Perl could reasonably do differently?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants