VFS::Gnome - Gnome Virtual Filesystem for Perl


VFS-Gnome documentation Contained in the VFS-Gnome distribution.

Index


Code Index:

NAME

Top

VFS::Gnome - Gnome Virtual Filesystem for Perl

SYNOPSIS

Top

  use VFS::Gnome;

  vfsopen(*IN, "<http://www.piersharding.com") or die $!;
  # dont forget the * when using strict
  print while (<IN>);
  close IN;




DESCRIPTION

Top

VFS::Gnome is a TIEHANDLE module that uses the gnome-vfs library from the Gnome project (http://www.gnome.org). The gnome-vfs library (Virtual File System) allows uniform access to various uri types such as http://, https://, file://, ftp:// etc.

METHODS

Top

vfsopen()

vfsopen is pushed into the users calling namespace via the import statement, so there is no need to fully qualify it.

vfsopen(*FH, ">file:///tmp/some.file") or die $!;

Because use strict forbids the use of barewords, then you must remember to use the * (typeglob notation) on your filehandle - but only for the vfsopen there after it is not required.

VFS::Gnome supports:

* '>' output to a file
* '<' input from a file
* '>>' append to a file ( this is broken in RH8.0 as gnome_vfs_seek is broken )

other functions

once opened - a file handle behaves much like an ordinary one, in that you can "print" to it, and read from it with the "<>" (diamond) operator.

vfsstat()

vfsstat takes a single argument of a uri and returns a 13 element array of information as the core perl stat() function does.

0 dev device number of filesystem (currently undef)
1 inode inode number (currently undef)
2 mode file mode (type and permissions in character form)
4 uid numeric user ID of file's owner
5 gid numeric group ID of file's owner
6 rdev the device identifier (special files only)
7 size total size of file, in bytes
8 atime last access time in seconds since the epoch
9 mtime last modify time in seconds since the epoch
10 ctime inode change time (NOT creation time!) in seconds since the epoch
11 blksize preferred block size for file system I/O
12 blocks actual number of blocks allocated
13 type a new entry specifying the type This can be f - file, d - directory, p - pipe, s - socket, c - character device, b - block device, l - link
14 name a new entry specifying the file name ( minus the path )

vfsexists()

vfsexists takes a single argument of a uri and returns true if it exists.

vfsmove()

vfsmove takes two arguments - the from and to uri's, and returns true if the file was successfully transported.

vfsopendir()

vfsopendir opens a handle on a directory in the same style as a TIED files handle. This is used in preference to trying to imitate the opendir, readdir, closedir syntax of Perl, that can not be imitated thru the tie() operation.

vfsopendir(*DIR, "file:///tmp") or die $!;

Because use strict forbids the use of barewords, then you must remember to use the * (typeglob notation) on your filehandle - but only for the vfsopendir there after it is not required.

subsequently the handle can be addressed in two ways:

* in array context
* in scalar context

Array context emulates individual readdir commands of standard Perl, in that it returns a list of names read from the given directory.

  push(@a, (<DIR>));

Scalar context returns the results of individual stat commands as an array ref. This is what gnome-vfs does natively. The first element of the stat array has been highjacked to supply the files name.

 while($dirent = <DIR>)
   push(@a, $dirent->[0]);




VERSION

Top

very new

AUTHOR

Top

Piers Harding - piers@cpan.org

SEE ALSO

Top

  http://developer.gnome.org/doc/API/gnome-vfs/ and perldoc Tie::Handle

COPYRIGHT

Top


VFS-Gnome documentation Contained in the VFS-Gnome distribution.

package VFS::Gnome;
use strict;
require 5.006;
use Carp;
require DynaLoader;
require Exporter;
use vars qw(@ISA $VERSION @EXPORT_OK $RUN_ONCE);
$VERSION = '0.05';
@ISA = qw(DynaLoader Exporter);

use Data::Dumper;

sub dl_load_flags { 0x01 }
VFS::Gnome->bootstrap($VERSION);


# export the open command, and initialise gnome-vfs
my @export_ok = ("vfsopen", "vfsexists", "vfsstat", "vfsmove", "vfsunlink", "vfsopendir" );
sub import {

  my ( $caller ) = caller;

  no strict 'refs';
  foreach my $sub ( @export_ok ){
    *{"${caller}::${sub}"} = \&{$sub};
  }

  # initialise the vfs engine
  do_vfs_init();

}

# open a file handle with vfs
sub vfsopen {

  my ( $caller ) = caller;
  my $handle = shift;
  $handle =~ s/.*:://;
  no strict 'refs';
  return tie *{"${caller}::${handle}"}, __PACKAGE__, @_;

}

# open a directory handle with vfs
sub vfsopendir {

  my ( $caller ) = caller;
  my $handle = shift;
  $handle =~ s/.*:://;
  no strict 'refs';
  return tie *{"${caller}::${handle}"}, __PACKAGE__, @_;

}

# check that the uri exists
sub vfsexists {

  my $uri = shift;
  return do_vfs_exists($uri);

}

# get posix style stats on uri
sub vfsstat {

  my $uri = shift;
  my $stats = do_vfs_stat($uri);
  if (ref($stats)){
    return @{$stats};
  } else {
    return $stats;
  }

}

# move one uri to another
sub vfsmove {

  my ($furi, $turi) = @_;
  die "from uri($furi) does not exist\n"
     unless vfsexists($furi);
  die "to uri does not exist\n"
     unless $turi;
  return do_vfs_move($furi, $turi);

}

# unlink/delete a given uri
sub vfsunlink {

  my $uri = shift;
  die "uri($uri) to delete does not exist\n"
     unless vfsexists($uri);
  return do_vfs_unlink($uri);

}


# instantiate the tied object
sub TIEHANDLE {

  my $caller = (caller(1))[3];
  $caller =~ s/.*:://;
  my $class = shift;
  my $file = shift;

  # determine if this is a file or directory call
  if ($caller eq 'vfsopen'){
    my ($meth, $uri) = $file =~ /^([\<\>]+)(.*?)$/;

    die "No file open method specified - $file\n"
      unless $meth;
    die "no open method/file name specified - $file\n"
      unless $uri;
    die "open method unsupported - $file\n"
      unless $meth eq '<' or $meth eq '>' or $meth eq '>>';

    my $self = { 'uri' => $file, 
                 'type' => 'file',
                 'rows' => [],
                 'buffer' => "",
                 'eof' => undef,
                 'nline' => $/,
                 'handle' => 
		   do_vfs_open($uri, $meth =~ />/ ? 1 : 0, $meth eq '>>' ? 1 : 0)
	       };
    bless($self, $class);
    return $self;
  } elsif ($caller eq 'vfsopendir'){

    my $self = { 'uri' => $file, 
                 'type' => 'dir',
                 'rows' => [],
                 'buffer' => "",
                 'eof' => undef,
                 'handle' => do_vfs_dir_open($file)
	       };
    bless($self, $class);
    return $self;
  }

  # the TIE fails
  return undef;

}


# read next buffer of a vfs file handle
sub READLINE {

  my $self = shift;

  if ( $self->{'type'} eq 'file' ){
    if ($self->{'nline'} ne $/){
        $self->{'buffer'} = join("",@{$self->{'rows'}});
        $self->{'rows'} = [];
        $self->{'nline'} = $/;
    }

    # Find the next available record
    my $buf = "";
    # return the rest of the file
    if ( wantarray() ){
        $self->{'buffer'} .= $buf
	    while ($buf = do_vfs_read($self->{'handle'}));
        @{$self->{'rows'}} = split(/$self->{nline}/, $self->{'buffer'}, -1);
        for (my $i = 0; $i < @{$self->{'rows'}} - 1; $i++){
          $self->{'rows'}->[$i] .= $self->{'nline'};
  	}
        $self->{'buffer'} = undef;
	$self->{'eof'} = 1;
	my $last = $self->{'rows'}->[-1];
	pop@{$self->{'rows'}} unless defined($last);
	return @{$self->{'rows'}};
     
    # get the next record
    } else {
      while ( ! $self->{'eof'} && scalar @{$self->{'rows'}} < 1  ){
        $buf =  do_vfs_read($self->{'handle'});
        # drop out if we are at the end of the file
        if ( ! defined($buf) ){
          $self->{'eof'} = 1;
          @{$self->{'rows'}}  = ( $self->{'buffer'} );
	  last;
	}

	# ok - we got some
        $self->{'buffer'} .= $buf;
        if ( $self->{'buffer'} =~ /$self->{nline}/s ){
          @{$self->{'rows'}} = split(/$self->{nline}/, $self->{'buffer'}, -1);
	  $self->{'buffer'} = pop(@{$self->{'rows'}});
          foreach (@{$self->{'rows'}}){
            $_ .= $self->{'nline'};
  	  }
          last;
        }
      }
      return @{$self->{'rows'}} ? shift(@{$self->{'rows'}}) : undef;
    }

  } elsif ( $self->{'type'} eq 'dir' ){
      # return a list of directories if in array context
      if (wantarray()){
       my @dir = ();
       while (my $dir = do_vfs_dir_read_next($self->{'handle'}) ){
         push(@dir, $dir->[-1]);
       }
       $self->{'eof'} = 1;
       return @dir;
      } else {
        # in scalar - return the next directory entry in stat format
        my $dirent = do_vfs_dir_read_next($self->{'handle'});
	$self->{'eof'} = 1 unless defined($dirent);
	return $dirent;
      }
  }

}


sub EOF {
 
  my $self = shift;
  # you dont do this with a directory
  return undef if $self->{'type'} eq 'dir';
  return $self->{'eof'};

}


sub BINMODE {
 die "not finished!";

}


sub UNTIE {
 die "not finished!";

}


sub DESTROY {
 #die "not finished!";

}


# print to a vfs file handle
sub PRINT {

  my $self = shift;
  # you dont do this with a directory
  return undef if $self->{'type'} eq 'dir';
  my $buffer = join("",@_);
  return do_vfs_write($self->{'handle'}, $buffer);

}


# close a vfs file handle
sub CLOSE {

  my $self = shift;
  if ($self->{'type'} eq 'dir'){
    die "Directory Close failed \n" unless do_vfs_dir_close($self->{'handle'});
  } elsif ($self->{'type'} eq 'file'){
    die "Close failed \n" unless do_vfs_close($self->{'handle'});
  }

}


#==============================================================================



1;