#!/usr/bin/perl use strict; use File::Basename; use Data::Dumper; use Fuse; use POSIX qw(ENOENT EISDIR EINVAL EEXIST); my $extra_goodies = 1; $| = 1; # This is where we'll store our # data. my (%files) = ( '/.' => { type => 0040, mode => 0755, uid => 0, gid => 0, ctime => time()-1000, atime => time()-1000, mtime => time()-1000, content => "", }, '/' => { type => 0040, mode => 0755, uid => 0, gid => 0, ctime => time()-1000, atime => time()-1000, mtime => time()-1000, content => "", }, ); sub debug { print "hash_fs: @_\n"; return; } # Functions to parse paths sub path { my $f = shift; return undef unless $f; my($file, $dir, undef) = fileparse($f, ("")); return ($file, $dir); } sub d { my(undef, $dir) = path(shift); return $dir; } sub f { my ($file, undef) = path(shift); return $file; } sub hash_getdir { my $path = shift; my @list = (".",".."); return -ENOENT() unless exists $files{$path}; my $type = $files{$path}{'type'}; if($type != 0040) { $path = d($path); } foreach my $f (keys %files) { # we only want to send the files that belong here! if(d($f) ne $path) { if(d($f) ne "$path/") { next; } } next if f($f) =~ m/^\.$/; next if $f eq $path; push @list, f($f); } return @list,0; } sub hash_open { my ($file, $dir) = path(shift); my $path = $dir.$file; return -EISDIR() if $file eq '.' or $file eq '..'; return -ENOENT() unless $files{$path}; return 0; } sub hash_getattr { my ($file, $dir) = path(shift); $file =~ s,^/,,; $file = '.' unless length($file); my $path = $dir.$file; return -ENOENT() unless exists $files{$path}; my $mode = $files{$path}{'mode'}; my $type = $files{$path}{'type'}; my $uid = $files{$path}{'uid'}; my $gid = $files{$path}{'gid'}; my $size = length($files{$path}{'content'}); my $atime = $files{$path}{'atime'} ; my $ctime = $files{$path}{'ctime'} ; my $mtime = $files{$path}{'mtime'} ; my $modes = ($type<<9) + $mode; my ($dev, $ino, $rdev, $blocks, $nlink, $blksize) = (0,0,0,1,1,1024); # We do not really have a block size since everything is in memroy. # We will make one up as 1K. $blocks = int($size/1024); $blocks = 1 if $blocks <= 0; return ($dev,$ino,$modes,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks); } sub hash_truncate { my $path = shift; return -ENOENT() unless exists $files{$path}; $files{$path}{'content'} = ""; return 0; } sub hash_read { my ($file, $dir) = path(shift); my $path = $dir.$file; my ($buf,$off) = @_; return -ENOENT() unless exists $files{$path}; my $content = $files{$path}{'content'}; return -EINVAL() if $off > length($content); return 0 if $off == length($content); return substr($content,$off,$buf); } sub hash_write { my ($path, $buf,$off) = @_; return -ENOENT() unless exists $files{$path}; return 0 unless length($buf); $files{$path}{'content'} .= $buf; return length($buf); } sub hash_unlink { my $path = shift; return -ENOENT() unless exists $files{$path}; delete $files{$path}; return 0; } sub hash_statfs { my $tot = 0; my $fnum = 0; foreach my $f (keys %files) { $tot += length($files{$f}{'content'}); $fnum++; } return(255, $fnum, 1, ($tot > 1024) ? int($tot/1024):1, ($tot > 1024) ? int($tot/1024)+1:1, 1024); } sub hash_readlink { return -ENOENT(); } sub hash_rmdir { return -ENOENT(); } sub hash_symlink { return -ENOENT(); } sub hash_rename { return -ENOENT(); } sub hash_link { return -ENOENT(); } sub hash_chmod { return 0; } sub hash_chown { return 0; } sub hash_utime { return 0; } sub hash_flush { return 0; } sub hash_release { return 0; } sub hash_fsync { return 0; } sub hash_setxattr { return 0; } sub hash_getxattr { return 0; } sub hash_listxattr { return 0; } sub hash_removexattr { return 0; } sub hash_mknod { my ($path, $modes, $dev) = @_; return 0 if exists $files{$path}; $files{$path}{'mode'} = 0644; $files{$path}{'type'} = 0100; $files{$path}{'uid'} = $files{$path}{'$gid'} = 0; $files{$path}{'atime'} = $files{$path}{'mtime'} = $files{$path}{'ctime'} = time(); $files{$path}{'content'} = ""; return 0; } sub hash_mkdir { my $path = shift; return -ENONENT() unless $extra_goodies; return -EEXIST() if exists $files{$path}; $files{$path}{'type'} = 0040; $files{$path}{'mode'} = 0755; $files{$path}{'uid'} = 0; $files{$path}{'gid'} = 0; $files{$path}{'atime'} = $files{$path}{'mtime'} = $files{$path}{'ctime'} = time(); $files{$path}{'content'} = ""; return 0; } my ($mountpoint) = ""; $mountpoint = shift(@ARGV) if @ARGV; Fuse::main( 'mountpoint'=> $mountpoint, 'chmod' => "main::hash_chmod", 'open' => "main::hash_open", 'read' => "main::hash_read", write => "main::hash_write", 'getdir' => "main::hash_getdir", 'getattr' => "main::hash_getattr", 'truncate' => "main::hash_truncate", 'readlink' => "main::hash_readlink", 'unlink' => "main::hash_unlink", 'rmdir' => "main::hash_rmdir", 'symlink' => "main::hash_symlink", 'rename' => "main::hash_rename", 'link' => "main::hash_link", 'chown' => "main::hash_chown", 'utime' => "main::hash_utime", 'statfs' => "main::hash_statfs", 'flush' => "main::hash_flush", 'release' => "main::hash_release", 'fsync' => "main::hash_fsync", 'setxattr' => "main::hash_setxattr", 'getxattr' => "main::hash_getxattr", 'listxattr' => "main::hash_listxattr", 'removexattr' => "main::hash_removexattr", 'mknod' => "main::hash_mknod", mkdir =>"main::hash_mkdir", 'threaded' => 0, 'debug' => 1 ); # vi: set ts=2 sw=2: #