2

I have the following perl code which tries to write a string to a newly created file:

open(OUT, ">$file") or die "file out error!\n";
print OUT $string;

Normally, this code works fine. If we do not have write permissions to the directory where $file exists, the program fails, which is expected. However, instead of printing "file out error!" as the error message, the program simply exits with exit code 13 (Permission denied).

  1. Why does the open method succeed when we are unable to write to the file?
  2. How do we get the appropriate error message in this instance?
jcee14
  • 908
  • 3
  • 15
  • 28
  • First, I don't think `open` can ever result in a SIGPIPE. One gets a SIGPIPE when writing to a closed pipe. That means `print` is the likely cause of the SIGPIPE. `$SIG{PIPE} = 'IGNORE';` would cause the system (and thus `print`) to return $!=EPIPE instead of throwing SIGPIPE. – ikegami Jun 27 '12 at 20:19
  • Yes, I agree with all the points, though it doesn't answer my question. – jcee14 Jun 27 '12 at 20:20
  • I didn't post an answer since the question makes no sense. As I explained, `open` did not result in an error, so expecting "file out error!" makes no sense. – ikegami Jun 27 '12 at 20:53
  • 1. So if the open does not fail if I will have write errors, when will it fail? What is the point of the 'open(filehdl, file) or die "msg"' convention commonly seen in scripts? 2. Printing EPIPE instead of exit code 13 is not really better. I would like to see the permission error which is the actual cause of failure. – jcee14 Jun 27 '12 at 21:00
  • See `man 2 open` for list of possible errors – ikegami Jun 27 '12 at 21:07
  • Under ERRORS section of man 2 open: EROFS pathname refers to a file on a read-only file system and write access was requested. – jcee14 Jun 27 '12 at 21:08
  • So why does open not result in an EROFS error in this instance? – jcee14 Jun 27 '12 at 21:12
  • No idea. That's got nothing to do with Perl, and you provided absolutely no information regarding this new question. – ikegami Jun 27 '12 at 21:20
  • So why did you even bring this up? I assume you mention unix open because it is the underlying call from Perl's open command. What more information do you need? – jcee14 Jun 27 '12 at 21:25
  • Why did I bring what up? // I did. // Me? none, cause I can't help answer your new question. But I don't see how "Why does open(2) not result in an EROFS error?" can possibly be answered without additional information. – ikegami Jun 27 '12 at 21:30
  • 1
    `EROFS` indicates that the entire filesystem you want to write to is read-only, not that you tried to write to a read-only file on a read-write filesystem. See `EACCES` for that error. – mob Jun 27 '12 at 21:33
  • @mob, that makes sense, but then my question just changes to: why doesn't Perl's open throw EACCES? (Assuming that open(2) is used in this implementation) – jcee14 Jun 27 '12 at 21:37
  • `open` doesn't throw anything. If there's a problem in `open`, Perl sets `$!`, the open call returns `undef`, and the program continues. – mob Jun 27 '12 at 21:40
  • @mob, sorry, I meant why doesn't the line (open() or die..) throw anything, especially since you said the open call should return undef. Shouldn't perl -e 'undef or die "asdf"' print "asdf"? – jcee14 Jun 27 '12 at 21:46
  • I dunno. Are you throwing out your standard error? What does `perl -e 'kill "PIPE",$$'; echo $?` print out? Is it the same or different from the output of `perl -e '$!=13;die';echo $?` ? – mob Jun 27 '12 at 22:22
  • $ perl -e 'kill "PIPE",$$'; echo $? 141 $ perl -e '$!=13;die';echo $? Died at -e line 1. 13 – jcee14 Jun 27 '12 at 22:24
  • 2
    And what's the exit code of your program? If it's 13, then that's a sign of an `EACCES` error in the `open` call. If it's 141, that's evidence of a `SIGPIPE`. – mob Jun 27 '12 at 22:52
  • 1
    Perl's open does return false with $!=EACCES when the system returns that error. (`chmod a-w . ; perl -e'open my $fh, ">", "file" or die $!'`) – ikegami Jun 28 '12 at 01:39
  • So it seems when my program exits with code 13, it is referring to Perl's code 13 (Permission denied). I'm just not sure why it doesn't print my die statement. – jcee14 Jun 28 '12 at 13:55

1 Answers1

3

I think you are confusing the programs exit code and its reporting of a standard system system error code. Error code (errno) 13 equates to "permission denied".

perl -lE '$!=13;say $!'
Permission denied

perl -lE '$!=32;say $!'
Broken pipe

Of course the actual message may vary slightly depending on your OS.

And for that matter, a better (IMO) way to construct an error message for the open is something like: `open OUT,">","$file" or die "Can't open $file: $!\n".

JRFerguson
  • 7,426
  • 2
  • 32
  • 36
  • A process exiting sets `$?` (a WEXITSTATUS), not `$!` (errno). `$? = 13` is SIGPIPE on many systems. – ikegami Jun 27 '12 at 21:16
  • 1
    The system error code and the program exit code can be the same when you use `die` to exit the program. Try `perl -e '$!=4;die';echo $?` and `perl -e '$!=14;die';echo $?`, for example. – mob Jun 27 '12 at 21:26
  • @mob, bash's `$?` is not the same as Perl's. It's just a part of the exit code. The exit code in that example is 4 << 256 and 14 << 256. The OP could have meant the exit code, but I was pointing out he could be right to say he got SIGPIPE. – ikegami Jun 27 '12 at 21:31
  • And for that matter, a better (IMO) way to construct an error message for the open is something like: `open OUT,">","$file" or die "Can't open $file: $!\n". – JRFerguson Jun 27 '12 at 21:34
  • @ikegami Ah, then your original comment makes more sense. Yes, of course: The "exit code" $?>>8 and the signal number the process received is $?&127 . – JRFerguson Jun 27 '12 at 21:38
  • @jcee14, So? What exactly is 13? – ikegami Jun 28 '12 at 01:43