2009-03-23 26 views
12

Se le da un objeto IO::File o un typeglob (\*STDOUT o Symbol::symbol_to_ref("main::FH")); ¿cómo harías para determinar si es un mango de lectura o escritura? La interfaz no se puede extender para pasar esta información (estoy anulando close para agregar llamadas a flush y sync antes del cierre real).¿Cómo puedo determinar si un manejador de archivo Perl es un manejador de lectura o escritura?

Actualmente estoy tratando de flush y sync el gestor de archivo e ignorando el error "Invalid argument" (que es lo que tengo cuando intente flush o sync un gestor de archivo de lectura):

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: $!"; 
     } 
}; 
+0

+1 fantástico pregunta! No tengo idea de cuándo alguna vez usaría esto, pero estoy fascinado de saber que alguien lo necesita. – scraimer

+0

Ext4 ha planteado problemas que Ext3 había mantenido ocultos por un tiempo. Ver http://thunk.org/tytso/blog/2009/03/15/dont-fear-the-fsync/ y el hilo p5p en curso (http://www.xray.mpe.mpg.de/mailing-lists /perl5-porters/2009-03/msg00322.html) para fondo. –

Respuesta

7

Tener un vistazo a la fcntl opciones. Tal vez F_GETFL con O_ACCMODE.

Editar: Hice un poco de google y jugando durante el almuerzo y he aquí algo de probablemente no portátil código pero funciona para mi máquina Linux, y probablemente cualquier sistema POSIX (tal vez incluso Cygwin, ¿quién sabe?) . salida

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); 

Ejemplo:

$ perl test.pl 
out 
File is: Write only 

in 
File is: Read only 

both 
File is: Read/Write 
+0

Parece que fcntl es específico del sistema operativo, pero si funciona para un sistema operativo determinado, podría crear un hash de envío basado en el sistema operativo y volver a mi código actual si el sistema operativo actual no está en el hash de despacho. –

+0

Me alegra que te guste. Puse un código de prueba. – JasonSmith

+0

En lugar de codificar "3", podría hacer 'O_RDONLY | O_RDWR | O_WRONLY' pero es poco probable que esas constantes cambien, ya que no han cambiado durante 20 años. Aún así, hace que el código sea más legible. – JasonSmith

Cuestiones relacionadas