Подтвердить что ты не робот

Как определить, является ли дескриптор файла Perl дескриптором чтения или записи?

Вам предоставляется объект IO::File или типglob (\*STDOUT или Symbol::symbol_to_ref("main::FH")); как бы вы определили, является ли это ручкой чтения или записи? Интерфейс не может быть расширен для передачи этой информации (я переопределяю close, чтобы добавить вызовы к flush и sync до фактического закрытия).

В настоящее время я пытаюсь выполнить flush и sync дескриптор файла и игнорировать ошибку "Invalid argument" (это то, что я получаю при попытке flush или sync читать дескриптор файла):

eval { $fh->flush; 1 } or do {
        #this seems to exclude flushes on read handles
        unless ($! =~ /Invalid argument/) {
                croak "could not flush $fh: $!";
        }
};

eval { $fh->sync; 1 } or do {
        #this seems to exclude syncs on read handles
        unless ($! =~ /Invalid argument/) {
                croak "could not sync $fh: $!";
        }
};
4b9b3361

Ответ 1

Посмотрите параметры fcntl. Может быть F_GETFL с O_ACCMODE.

Изменить: Я немного поработал над игрой и поиграл за обедом, и вот какой-то, возможно, не переносимый код, но он работает для моего Linux-бокса и, возможно, любой системы Posix (возможно, даже Cygwin, кто знает?).

use strict;
use Fcntl;
use IO::File;

my $file;
my %modes = ( 0 => 'Read only', 1 => 'Write only', 2 => 'Read / Write' );

sub open_type {
    my $fh = shift;
    my $mode = fcntl($fh, F_GETFL, 0);
    print "File is: " . $modes{$mode & 3} . "\n";
}

print "out\n";
$file = new IO::File();
$file->open('> /tmp/out');
open_type($file);

print "\n";

print "in\n";
$file = new IO::File();
$file->open('< /etc/passwd');
open_type($file);

print "\n";

print "both\n";
$file = new IO::File();
$file->open('+< /tmp/out');
open_type($file);

Пример вывода:

$ perl test.pl 
out
File is: Write only

in
File is: Read only

both
File is: Read / Write