ETOOBUSY 🚀 minimal blogging for the impatient
Open, sysopen, read, sysread... oh my!
TL;DR
In recent post Random bytes and co. I wrote a function to read
exactly 16 bytes from /dev/urandom
:
sub salt_please {
open my $fh, '< :raw :bytes', '/dev/urandom'
or die "open('/dev/urandom'): $!\n";
my $retval = '';
while ((my $len = length $retval) < 16) {
read($fh, $retval, 16 - $len, $len) // die "read(): $!\n"
}
close $fh;
return $retval;
}
My first thought was to use sysopen
and sysread
, but then I took a
look at perlopentut and figured that it was not needed.
Then of course I wondered… when should I use one or the other?!?
Here’s something I collected.
They don’t pair
The first thing is that there is no pairing, i.e. you can use read
with filehandles opened with sysopen
, and use sysread
with
filehandles opened with open
.
open
is almost certainly good
What’s the difference between open and sysopen in Perl?
The bottom line is that everyday usage for a multitude of files is fine with open. As put in this answer:
Unless you are working with a specific device that requires some special flags to be passed at
open(2)
time, for ordinary files on disk you should be fine with open.
One comment in the answer provides an excellent example of using sysopen over open:
[…] consider
O_WRONLY|O_EXCL|O_CREAT
combo, i.e. “create and write if not exists”. Using-f ... or open ...
instead is just asking for race condition.
So there I have it, to read (binary) data from /dev/urandom
I will
just open passing :raw :binary
as suggested in perlopentut.
read
is almost certainly good
What is the difference between read
and sysread
?
I’ll just copy-paste the author’s conclusions:
- read works with any Perl file handle, while sysread is limited to Perl file handles mapped to a system file handle/descriptor.
- read isn’t compatible with select (I’m referring to the 4-argument one called by IO::Select), while sysread is compatible with select.
- read can perform decoding for you, while sysread requires that you do your own decoding.
- read should be faster for very small reads, while sysread should be faster for very large reads.
Maybe I’m oversimplifying, but I think I’ll leave sysread for sockets etc. and stick to read if I’m reading local stuff.