Mailing List Archive

POSIX bug + perl sysopen() in lieu of open(2)
0. It's confusing that to get FileHandle::new_from_fd you have
to use POSIX instead of FileHandle! Any ideas for
fixing this?

1. POSIX's FileHandle::new_from_fd didn't work for update; I've fix
that myself, since I'm currently holding the patch pumpkin
for the {lib,ext,pod} dictories:

sub FileHandle::new_from_fd {
POSIX::usage "FileHandle->new_from_fd(fd,mode)" if @_ != 3;
my($class,$fd,$mode) = @_;
my($sym) = $class->POSIX::gensym;

$mode =~ s/a(\+?).*/$1>>/
|| $mode =~ s/w(\+?).*/$1>/
|| $mode =~ s/r(\+?).*/$1>/
|| ($mode = '<');

open($sym, "$mode&=$fd") and bless $sym => $class;
}

2. I believe that the way people truly want to get at this stuff is
using something that precisely mimics C's open(2) system call
(not perl's open2() call! :-), perhaps like this:

use FileHandle;
use POSIX qw(:fcntl_h);

$path = "/tmp/testfile";
$fh = sysopen($path, O_RDWR|O_CREAT|O_EXCL, 0700)
|| die "$path: $!";
print "fh is $fh\n";
$fh->autoflush(1);
$fh->print("stuff $$\n");
seek($fh, 0, SEEK_SET);
print "File contains: ", <$fh>;

I believe that this is a definition for sysopen() that works
per those expectations:

sub sysopen ($;$$) {
my $path = shift;
my $flag = shift || O_RDONLY;
my $mode = shift || 0644;

my $amode = do {
if ($flag & O_RDONLY) { "r" }
elsif ($flag & O_WRONLY) { ($flag & O_APPEND) ? "w" : "a" }
elsif ($flag & O_RDWR) {
if ($flag & O_CREAT) { "w+" }
else { ($flag & O_APPEND) ? "r+" : "a+" }
}
};
my $fd = POSIX::open($path, $flag, $mode);
return undef unless defined $fd;
my $fh = FileHandle->new_from_fd($fd, $amode);
return defined($fh) ? $fh : undef;
}

Does anyone have any comments about that? I think I have the modes
write, er, right :-). Yes, it seems like one more function call than
it deserves, but that's optimizable later.

Now, where does it go? It's not terrible useful without POSIX stuff,
although the truth is it will actually work with good old simple
Fcntl.pm constants.

I'd really rather not rehash the bazillion different FileHandle::new
discussions. I'm just trying to figure out how and where to provide
sysopen(), which is supposed to exactly mimic the C open(2).

--tmo