FloydATC has asked for the wisdom of the Perl Monks concerning the following question:

If I try to open a block device using open(my $fh, "+<", "/dev/foo") the device node is truncated and replaced with a regular file. I'm guessing the solution involves sysopen() and O_DIRECT but I'd rather not experiment too much with these things and I can't seem to find any good docs on it. Can someone point me to example code showing how to "safely" do random read/write ops on a raw block device?

Also, I know syswrite() and seek() are mutually incompatible. Does the 4th parameter to syswrite() do the same as seek() on the file handle?

Edit:

"When it comes to opening devices, it can be easy and it can be tricky. We’ll assume that if you’re opening up a block device, you know what you’re doing. The character devices are more interesting."
In all of Perl's documentation, this must be the single least useful bit of info :-|
-- Time flies when you don't know what you're doing

Replies are listed 'Best First'.
Re: Random read/write on a block device
by ikegami (Patriarch) on Jun 25, 2009 at 11:59 UTC
    I don't know the answer to your main question. Although if you provide code written in a different language, we could help you translate it.

    I know syswrite() and seek() are mutually incompatible.

    But sysseek isn't.

    Does the 4th parameter to syswrite() do the same as seek() on the file handle?

    No. As documented, "An OFFSET may be specified to write the data from some part of the string other than the beginning."

    That means syswrite($fh, "abcdef", 2, 3) will write three bytes starting at index 2: de.

    FYI, [doc://funcname] links to better (up to date) documentation. [funcname] finds rather old documentation which isn't rendered particularly well.

      See, I missed sysseek() completely... very impressive.

      About the docs you refer to, that's what I thought it meant but I was unsure since it overlaps with what substr() does, and passing unused data to syswrite() seems like an odd thing to do. Thanks for clearing it up :-)

      -- Time flies when you don't know what you're doing

        passing unused data to syswrite() seems like an odd thing to do.

        Since you can't control how many bytes actually get written, it makes it very easy to use syswrite:

        my $to_write = length($msg); while ($to_write) { my $written = syswrite($fh, $msg, $to_write, -$to_write) or die "syswrite: $!\n"; $to_write -= $written; }