• R/O
  • SSH
  • HTTPS

perl-fuse-fv: Commit


Commit MetaInfo

Revision76 (tree)
Zeit2011-12-17 15:05:27
Autortofjw

Log Message

Fuse-Class 0.02

Ändern Zusammenfassung

Diff

--- Fuse-Class/tags/Fuse-Class-0.02/test/fuse28.pm (nonexistent)
+++ Fuse-Class/tags/Fuse-Class-0.02/test/fuse28.pm (revision 76)
@@ -0,0 +1,624 @@
1+#
2+# test filesystem for Fuse 2.8
3+# (file operations are done via file/directory handle.)
4+#
5+
6+use strict;
7+use warnings;
8+
9+use Fcntl;
10+
11+package test::fuse28;
12+
13+use base qw(Fuse::Class);
14+
15+sub new {
16+ my $class = shift;
17+
18+ my $self = {
19+ root => test::fuse28::Directory->new,
20+
21+ handle => {
22+ }
23+ };
24+
25+ return bless $self, $class;
26+}
27+
28+sub issue_handle {
29+ my $self = shift;
30+ my $obj = shift;
31+
32+ my $i = 0;
33+ while ($self->{handle}->{$i}) {
34+ $i++;
35+ }
36+
37+ $self->{handle}->{$i} = $obj;
38+
39+ return $i;
40+}
41+
42+sub release_handle {
43+ my $self = shift;
44+ my ($fh) = @_;
45+
46+ delete $self->{handle}->{$fh};
47+}
48+
49+sub pickup {
50+ my $self = shift;
51+ my $path = shift;
52+
53+ my $ret = $self->{root};
54+
55+ for my $e (split('/', $path)) {
56+ next if ($e eq '');
57+
58+ if ($ret->isa('test::fuse28::Directory')) {
59+ if ($e eq '..') {
60+ $ret = $ret->parent;
61+ }
62+ elsif ($e eq '.') {
63+ ; # nothing
64+ }
65+ else {
66+ $ret = $ret->entity($e);
67+ }
68+ }
69+ else {
70+ return undef;
71+ }
72+ }
73+
74+ return $ret;
75+}
76+
77+sub getattr {
78+ my $self = shift;
79+ my ($path) = @_;
80+
81+ my $entity = $self->pickup($path);
82+ return -2 unless ($entity);
83+
84+ return $entity->attr;
85+}
86+
87+sub readlink {
88+ my $self = shift;
89+ my ($path) = @_;
90+
91+ my $entity = $self->pickup($path);
92+ return -2 unless ($entity);
93+ return -1 unless ($entity->can('readlink'));
94+
95+ return $entity->readlink;
96+}
97+
98+sub getdir {
99+ my $self = shift;
100+ my ($path) = @_;
101+
102+ # die "this function must not be called.";
103+ return -1;
104+}
105+
106+sub mknod {
107+ my $self = shift;
108+ my ($path, $mode, $devno) = @_;
109+
110+ my ($dirname, $name) = ($path =~ m/^(.*)\/([^\/]+)$/);
111+ return -2 unless (defined($dirname) && defined($name)); # badname ?
112+
113+ my $dir = $self->pickup($dirname);
114+ return -2 unless ($dir);
115+
116+ return $dir->mknod($name, $mode, $devno);
117+}
118+
119+sub mkdir {
120+ my $self = shift;
121+ my ($path, $mode) = @_;
122+
123+ my ($dirname, $name) = ($path =~ m/^(.*)\/([^\/]+)$/);
124+ return -2 unless (defined($dirname) && defined($name)); # badname ?
125+
126+ my $dir = $self->pickup($dirname);
127+ return -2 unless ($dir);
128+
129+ return $dir->mkdir($name, $mode);
130+}
131+
132+sub unlink {
133+ my $self = shift;
134+ my ($path) = @_;
135+
136+ my ($dirname, $name) = ($path =~ m/^(.*)\/([^\/]+)$/);
137+ return -2 unless (defined($dirname) && defined($name)); # badname ?
138+
139+ my $dir = $self->pickup($dirname);
140+ return -2 unless ($dir);
141+
142+ return $dir->unlink($name);
143+}
144+
145+sub rmdir {
146+ my $self = shift;
147+ my ($path) = @_;
148+
149+ my ($dirname, $name) = ($path =~ m/^(.*)\/([^\/]+)$/);
150+ return -2 unless (defined($dirname) && defined($name)); # badname ?
151+
152+ my $dir = $self->pickup($dirname);
153+ return -2 unless ($dir);
154+
155+ return $dir->rmdir($name);
156+}
157+
158+sub symlink {
159+ my $self = shift;
160+ my ($existing, $symlink) = @_;
161+
162+ my ($dirname, $name) = ($symlink =~ m/^(.*)\/([^\/]+)$/);
163+ return -2 unless (defined($dirname) && defined($name)); # badname ?
164+
165+ my $dir = $self->pickup($dirname);
166+ return -2 unless ($dir);
167+
168+ return $dir->symlink($name, $existing);
169+}
170+
171+sub rename {
172+ my $self = shift;
173+ my ($old_name, $new_name) = @_;
174+
175+ my ($dirname1, $name1) = ($old_name =~ m/^(.*)\/([^\/]+)$/);
176+ return -2 unless (defined($dirname1) && defined($name1)); # badname ?
177+
178+ my ($dirname2, $name2) = ($new_name =~ m/^(.*)\/([^\/]+)$/);
179+ return -2 unless (defined($dirname2) && defined($name2)); # badname ?
180+
181+ my $dir1 = $self->pickup($dirname1);
182+ return -2 unless ($dir1);
183+
184+ my $dir2 = $self->pickup($dirname2);
185+ return -2 unless ($dir2);
186+
187+ return $dir1->rename($name1, $dir2, $name2);
188+}
189+
190+sub opendir {
191+ my $self = shift;
192+ my ($path) = @_;
193+
194+ my $entity = $self->pickup($path);
195+ return (-2) unless ($entity);
196+
197+ if ($entity->isa('test::fuse28::Directory')) {
198+ my $fh = $self->issue_handle($entity);
199+ return (0, $fh);
200+ }
201+ else {
202+ return (-2);
203+ }
204+}
205+
206+sub readdir {
207+ my $self = shift;
208+ my ($path, $offset, $dh) = @_;
209+
210+ my $dir = $self->{handle}->{$dh};
211+ return (-2) unless ($dir);
212+
213+ my @names = $dir->readdir;
214+
215+ if ($offset < @names) {
216+ return (@names[$offset..$#names], 0);
217+ }
218+
219+ return (0);
220+}
221+
222+sub releasedir {
223+ my $self = shift;
224+ my ($path, $dh) = @_;
225+
226+ if ($self->{handle}->{$dh}) {
227+ $self->release_handle($dh);
228+ return 0;
229+ }
230+
231+ return -2;
232+}
233+
234+sub chmod {
235+ my $self = shift;
236+ my ($path, $modes) = @_;
237+
238+ my $entity = $self->pickup($path);
239+ return -2 unless ($entity);
240+
241+ $entity->chmod($modes);
242+}
243+
244+sub chown {
245+ my $self = shift;
246+ my ($path, $uid, $gid) = @_;
247+
248+ my $entity = $self->pickup($path);
249+ return -2 unless ($entity);
250+
251+ $entity->chown($uid, $gid);
252+}
253+
254+sub ftruncate {
255+ my $self = shift;
256+ my ($path, $offset, $fh) = @_;
257+
258+ my $entity = $self->{handle}->{$fh};
259+ return (-2) unless ($entity);
260+ return (-1) unless ($entity->can('truncate'));
261+
262+ $entity->truncate($offset);
263+}
264+
265+sub truncate {
266+ my $self = shift;
267+ my ($path, $offset) = @_;
268+
269+ my $entity = $self->pickup($path);
270+ return -2 unless ($entity);
271+ return -1 unless ($entity->can('truncate'));
272+
273+ $entity->truncate($offset);
274+}
275+
276+sub utime {
277+ my $self = shift;
278+ my ($path, $atime, $mtime) = @_;
279+
280+ # die "utimens must be called";
281+ return -1;
282+}
283+
284+sub open {
285+ my $self = shift;
286+ my ($path, $flags, $fileinfo) = @_;
287+
288+ my $entity = $self->pickup($path);
289+ return (-2) unless ($entity);
290+
291+ return (0, $self->issue_handle($entity));
292+}
293+
294+sub write {
295+ my $self = shift;
296+ my ($path, $buffer, $offset, $fh) = @_;
297+
298+ my $entity = $self->{handle}->{$fh};
299+ return (-2) unless ($entity);
300+ return (-1) unless ($entity->can('write'));
301+
302+ $entity->write($buffer, $offset);
303+}
304+
305+sub read {
306+ my $self = shift;
307+ my ($path, $size, $offset, $fh) = @_;
308+
309+ my $entity = $self->{handle}->{$fh};
310+ return (-2) unless ($entity);
311+ return (-1) unless ($entity->can('read'));
312+
313+ $entity->read($size, $offset);
314+}
315+
316+sub statfs {
317+ my $self = shift;
318+
319+ return (255, 50000, 40000, 30000, 20000, 10000);
320+}
321+
322+sub utimens {
323+ my $self = shift;
324+ my ($path, $atime, $mtime) = @_;
325+
326+ my $entity = $self->pickup($path);
327+ return -2 unless ($entity);
328+
329+ return $entity->utimens($atime, $mtime);
330+}
331+
332+package test::fuse28::Entity;
333+
334+my $last_ino = 0;
335+
336+sub new {
337+ my $class = shift;
338+
339+ my $t = time;
340+
341+ my $self = {
342+ # ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
343+ # $atime,$mtime,$ctime,$blksize,$blocks)
344+ attr => [0, $last_ino++, 0, 1, $>+0, $)+0, 0, 0,
345+ $t, $t, $t, 1024, 0],
346+ };
347+
348+ $self->{attr}->[8] = $t;
349+ $self->{attr}->[9] = $t;
350+ $self->{attr}->[10] = $t;
351+
352+ bless $self, $class;
353+}
354+
355+sub attr {
356+ my $self = shift;
357+ return @{$self->{attr}};
358+}
359+
360+sub chmod {
361+ my $self = shift;
362+ my ($modes) = @_;
363+
364+ my $attr = $self->{attr}->[2] & ~(07777);
365+ $self->{attr}->[2] = $attr | $modes;
366+
367+ return 0;
368+}
369+
370+sub utimens {
371+ my $self = shift;
372+ my ($atime, $mtime) = @_;
373+
374+ my $attr = $self->{attr};
375+ $attr->[8] = $atime if ($atime >= 0);
376+ $attr->[9] = $mtime if ($mtime >= 0);
377+
378+ return 0;
379+}
380+
381+sub chown {
382+ my $self = shift;
383+ my ($uid, $gid) = @_;
384+
385+ $self->{attr}->[4] = $uid if ($uid >= 0);
386+ $self->{attr}->[5] = $gid if ($gid >= 0);
387+
388+ return 0;
389+}
390+
391+#
392+# Directory
393+#
394+package test::fuse28::Directory;
395+
396+use Fcntl qw(:mode);
397+use base qw(test::fuse28::Entity);
398+use Scalar::Util qw(weaken);
399+
400+sub new {
401+ my $class = shift;
402+ my $parent = shift;
403+
404+ my $self = $class->SUPER::new;
405+ $self->{attr}->[2] = S_IFDIR | S_IRWXU;
406+
407+ if (!defined($parent)) {
408+ $self->{parent} = $self;
409+ }
410+ else {
411+ $self->{parent} = $parent;
412+ }
413+
414+ $self->{children} = {};
415+
416+ # avoid cyclic reference
417+ weaken($self->{parent});
418+
419+ bless $self, $class;
420+}
421+
422+sub parent {
423+ my $self = shift;
424+ return $self->{parent};
425+}
426+
427+sub entity {
428+ my $self = shift;
429+ my $name = shift;
430+
431+ return $self if ($name eq '.');
432+ return $self->parent if ($name eq '..');
433+
434+ return $self->{children}->{$name};
435+}
436+
437+sub readdir {
438+ my $self = shift;
439+ return ('..', '.', keys %{$self->{children}});
440+}
441+
442+sub mknod {
443+ my $self = shift;
444+ my ($name, $mode, $devno) = @_;
445+
446+ my $umask = 0;
447+ $umask |= S_IRUSR if ($mode & 0400);
448+ $umask |= S_IWUSR if ($mode & 0200);
449+ $umask |= S_IXUSR if ($mode & 0100);
450+ $umask |= S_IRGRP if ($mode & 0040);
451+ $umask |= S_IWGRP if ($mode & 0020);
452+ $umask |= S_IXGRP if ($mode & 0010);
453+ $umask |= S_IROTH if ($mode & 0004);
454+ $umask |= S_IWOTH if ($mode & 0002);
455+ $umask |= S_IXOTH if ($mode & 0001);
456+
457+ if (S_ISREG($mode)) {
458+ my $newfile = test::fuse28::File->new;
459+ my $attr = S_IFREG | $umask;
460+ $newfile->{attr}->[2] = $attr;
461+ $self->{children}->{$name} = $newfile;
462+ return 0;
463+ }
464+ if (S_ISDIR($mode)) {
465+ return $self->mkdir($name, $mode);
466+ }
467+
468+ if (S_ISLNK($mode)) {
469+ return -1;
470+ }
471+ if (S_ISBLK($mode)) {
472+ return -1;
473+ }
474+ if (S_ISCHR($mode)) {
475+ return -1;
476+ }
477+ if (S_ISFIFO($mode)) {
478+ return -1;
479+ }
480+ if (S_ISSOCK($mode)) {
481+ return -1;
482+ }
483+
484+ return -1;
485+}
486+
487+sub mkdir {
488+ my $self = shift;
489+ my ($name, $mode) = @_;
490+
491+ my $newdir = test::fuse28::Directory->new($self);
492+ my $attr = S_IFDIR;
493+ $attr |= S_IRUSR if ($mode & 0400);
494+ $attr |= S_IWUSR if ($mode & 0200);
495+ $attr |= S_IXUSR if ($mode & 0100);
496+ $attr |= S_IRGRP if ($mode & 0040);
497+ $attr |= S_IWGRP if ($mode & 0020);
498+ $attr |= S_IXGRP if ($mode & 0010);
499+ $attr |= S_IROTH if ($mode & 0004);
500+ $attr |= S_IWOTH if ($mode & 0002);
501+ $attr |= S_IXOTH if ($mode & 0001);
502+ $newdir->{attr}->[2] = $attr;
503+
504+ $self->{children}->{$name} = $newdir;
505+
506+ return 0;
507+}
508+
509+sub unlink {
510+ my $self = shift;
511+ my ($name) = @_;
512+
513+ my $entity = $self->{children}->{$name};
514+ return -2 unless ($entity);
515+ delete $self->{children}->{$name};
516+
517+ return 0;
518+}
519+
520+sub rmdir {
521+ my $self = shift;
522+ my ($name) = @_;
523+
524+ my $entity = $self->{children}->{$name};
525+ return -2 unless ($entity);
526+ delete $self->{children}->{$name};
527+
528+ return 0;
529+}
530+
531+sub rename {
532+ my $self = shift;
533+ my ($old_name, $new_dir, $new_name) = @_;
534+
535+ my $entity = $self->{children}->{$old_name};
536+ return -2 unless ($entity);
537+
538+ delete $self->{children}->{$old_name};
539+ $new_dir->{children}->{$new_name} = $entity;
540+
541+ return 0;
542+}
543+
544+sub symlink {
545+ my $self = shift;
546+ my ($name, $existing) = @_;
547+
548+ my $link = test::fuse28::Symlink->new($existing);
549+ my $attr = S_IFLNK | 0777;
550+ $link->{attr}->[2] = $attr;
551+ $self->{children}->{$name} = $link;
552+
553+ return 0;
554+}
555+
556+#
557+# Normal File
558+#
559+package test::fuse28::File;
560+
561+use base qw(test::fuse28::Entity);
562+
563+sub new {
564+ my $class = shift;
565+
566+ my $self = $class->SUPER::new;
567+ $self->{content} = '';
568+
569+ bless $self, $class;
570+}
571+
572+sub write {
573+ my $self = shift;
574+ my ($buffer, $offset) = @_;
575+
576+ substr($self->{content}, $offset) = $buffer;
577+ $self->{attr}->[7] = length($self->{content});
578+ $self->{attr}->[12] = int(($self->{attr}->[7] + $self->{attr}->[11] - 1) / $self->{attr}->[11]);
579+
580+ return length($buffer);
581+}
582+
583+sub read {
584+ my $self = shift;
585+ my ($size, $offset) = @_;
586+
587+ return substr($self->{content}, $offset, $size);
588+}
589+
590+sub truncate {
591+ my $self = shift;
592+ my ($offset) = @_;
593+
594+ $self->{content} = substr($self->{content}, 0, $offset);
595+ $self->{attr}->[7] = length($self->{content});
596+
597+ return 0;
598+}
599+
600+#
601+# Symlink
602+#
603+package test::fuse28::Symlink;
604+
605+use base qw(test::fuse28::Entity);
606+use Scalar::Util qw(weaken);
607+
608+sub new {
609+ my $class = shift;
610+ my ($existing) = @_;
611+
612+ my $self = $class->SUPER::new;
613+ $self->{link} = $existing;
614+
615+ bless $self, $class;
616+}
617+
618+sub readlink {
619+ my $self = shift;
620+
621+ return $self->{link};
622+}
623+
624+1;
--- Fuse-Class/tags/Fuse-Class-0.02/t/10subclass.t (nonexistent)
+++ Fuse-Class/tags/Fuse-Class-0.02/t/10subclass.t (revision 76)
@@ -0,0 +1,89 @@
1+
2+use strict;
3+
4+use Test::More tests => 14;
5+
6+#################################################
7+package TestClass;
8+
9+use base qw(Fuse::Class);
10+
11+sub getdir {
12+ my $self = shift;
13+ my ($dir) = @_;
14+
15+ return (".", "..", "x$dir", 0);
16+}
17+
18+sub mknod {
19+ my $self = shift;
20+ my ($fname) = @_;
21+
22+ $! = Errno::EINTR;
23+ die "error";
24+}
25+
26+sub mkdir {
27+ my $self = shift;
28+ my ($fname) = @_;
29+
30+ $! = 0;
31+ die "error";
32+}
33+
34+#################################################
35+
36+package main;
37+
38+my %Fuse_main;
39+
40+#
41+# override Fuse::main for test
42+#
43+{
44+ no warnings "redefine";
45+ no strict "refs";
46+
47+ *Fuse::main = sub {
48+ %Fuse_main = @_;
49+ for my $k (keys %Fuse_main) {
50+ my $subname = $Fuse_main{$k};
51+ $Fuse_main{$k} = sub { &$subname(@_); };
52+ }
53+ };
54+}
55+
56+use Errno;
57+
58+my $fs = TestClass->new();
59+is(ref($fs), "TestClass", "constructor");
60+
61+$fs->main(mountpoint => "/never-found");
62+$Fuse::Class::_Module = $fs; # set in Fuse::Class
63+
64+# overrided method
65+my $getdir = $Fuse_main{getdir};
66+is_deeply([&$getdir("abc")], [".", "..", "xabc", 0]);
67+
68+# error (in $!)
69+my $mknod = $Fuse_main{mknod};
70+is(&$mknod("/never-found"), -Errno::EINTR());
71+
72+# error (not in $!)
73+my $mkdir = $Fuse_main{mkdir};
74+is(&$mkdir("/never-found"), -Errno::EPERM());
75+
76+# not implemented
77+my $getattr = $Fuse_main{getattr};
78+is($fs->can('getattr') ? &$getattr("/") : -Errno::EPERM(), -Errno::EPERM());
79+
80+# default implement
81+is($fs->readlink("/not/found"), -Errno::ENOENT());
82+is($fs->statfs(), -Errno::ENOANO());
83+is($fs->flush("/some/file"), 0);
84+is($fs->release("/some/file"), 0);
85+is($fs->fsync("/some/file"), 0);
86+is($fs->getxattr("/some/file"), 0);
87+is($fs->listxattr("/some/file"), 0);
88+is($fs->removexattr("/some/file"), 0);
89+is($fs->setxattr("/some/file", "name", "value", 0), -Errno::EOPNOTSUPP());
--- Fuse-Class/tags/Fuse-Class-0.02/t/80fuse28.t (nonexistent)
+++ Fuse-Class/tags/Fuse-Class-0.02/t/80fuse28.t (revision 76)
@@ -0,0 +1,158 @@
1+#
2+# test filesystem using test::fuse28.pm test mudule
3+#
4+
5+use strict;
6+use POSIX ":sys_wait_h";
7+use Test::Class;
8+use Test::More;
9+use Fuse;
10+
11+use test::fuse28;
12+
13+my $mount_point = "/tmp/fuse-class-test-$<-$$";
14+
15+my $reason = "no reason (test error?)";
16+
17+sub start_check {
18+ #
19+ # Fuse version must be 2.8 or later for this test.
20+ #
21+ my $version = Fuse::fuse_version;
22+ if ($version < 2.8) {
23+ $reason = "Fuse version is lower than 2.8.";
24+ return 0;
25+ }
26+
27+ #
28+ # fusermount command is available?
29+ #
30+ my $res = `fusermount -V 2>&1`;
31+ unless ($res =~ /version/) {
32+ $reason = "fusermount command is not available.";
33+ return 0;
34+ }
35+
36+ #
37+ # Test::Virtual::Filesystem
38+ #
39+ eval "use Test::Virtual::Filesystem;";
40+ if ($@) {
41+ $reason = "Test::Virtual::Filesystem is not available.";
42+ return 0;
43+ }
44+
45+ return 1;
46+}
47+
48+#
49+# start Fuse main loop in child process
50+#
51+sub child_process {
52+ mkdir $mount_point, 0777;
53+ diag $mount_point;
54+ die "$mount_point: cannot create directoy: $!" unless (-d $mount_point);
55+
56+ my $fs = new test::fuse28;
57+ $fs->main(mountpoint => $mount_point);
58+}
59+
60+sub cleanup {
61+ my $child_pid = shift;
62+
63+ my $kid = 0;
64+ my $n = 0;
65+ do {
66+ system("fusermount", "-u", $mount_point);
67+ sleep(1);
68+ $kid = waitpid $child_pid, WNOHANG;
69+ } while($kid != $child_pid && $n++ < 10);
70+
71+ rmdir $mount_point;
72+}
73+
74+#
75+# test start
76+#
77+unless (start_check) {
78+ plan skip_all => $reason;
79+}
80+else {
81+ eval "use Test::Virtual::Filesystem;";
82+ my $child_pid = -1;
83+
84+ eval {
85+ plan tests => 155;
86+
87+ $child_pid = fork();
88+ die $! if ($child_pid < 0);
89+
90+ if ($child_pid == 0) {
91+ child_process;
92+ exit 0;
93+ }
94+
95+ sleep(3);
96+
97+ my $test = Test::Virtual::Filesystem->new({mountdir => $mount_point,
98+ compatible => '0.08'});
99+ $test->enable_test_xattr(0);
100+ $test->enable_test_time(1);
101+ # $test->enable_test_atime(1);
102+ # $test->enable_test_mtime(1);
103+ # $test->enable_test_ctime(1);
104+ $test->enable_test_permissions(0);
105+ $test->enable_test_special(0);
106+ # $test->enable_test_fifo(0);
107+ $test->enable_test_symlink(1);
108+ # $test->enable_test_hardlink(0);
109+ # $test->enable_test_nlink(0);
110+ # $test->enable_test_chown(0);
111+
112+ $test->runtests;
113+
114+ # unlink
115+ {
116+ my $fname = "$mount_point/unlink-test";
117+ unlink $fname;
118+ open(my $fh, "> $fname");
119+ close($fh);
120+
121+ ok(-f $fname);
122+ unlink $fname;
123+ ok(!-f $fname);
124+ }
125+
126+ # chmod
127+ {
128+ my $fname = "$mount_point/chmod-test";
129+ unlink $fname;
130+ open(my $fh, "> $fname");
131+ close($fh);
132+ chmod(0642, $fname);
133+ my $perm = (stat $fname)[2] & 0777;
134+ ok($perm == 0642);
135+ }
136+
137+ # ftrunate
138+ {
139+ my $fname = "$mount_point/ftruncate-test";
140+ unlink $fname;
141+ open(my $fh1, "> $fname");
142+ print $fh1 "12345";
143+ close($fh1);
144+
145+ open(my $fh2, "+< $fname");
146+ truncate($fh2, 3);
147+ close($fh2);
148+
149+ my $size = (stat $fname)[7];
150+ ok($size == 3);
151+ }
152+ };
153+
154+ my $err = $@;
155+ cleanup($child_pid);
156+
157+ die $err if ($err);
158+}
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
--- Fuse-Class/tags/Fuse-Class-0.02/t/pod.t (nonexistent)
+++ Fuse-Class/tags/Fuse-Class-0.02/t/pod.t (revision 76)
@@ -0,0 +1,12 @@
1+#!perl -T
2+
3+use strict;
4+use warnings;
5+use Test::More;
6+
7+# Ensure a recent version of Test::Pod
8+my $min_tp = 1.22;
9+eval "use Test::Pod $min_tp";
10+plan skip_all => "Test::Pod $min_tp required for testing POD" if $@;
11+
12+all_pod_files_ok();
--- Fuse-Class/tags/Fuse-Class-0.02/t/pod-coverage.t (nonexistent)
+++ Fuse-Class/tags/Fuse-Class-0.02/t/pod-coverage.t (revision 76)
@@ -0,0 +1,18 @@
1+use strict;
2+use warnings;
3+use Test::More;
4+
5+# Ensure a recent version of Test::Pod::Coverage
6+my $min_tpc = 1.08;
7+eval "use Test::Pod::Coverage $min_tpc";
8+plan skip_all => "Test::Pod::Coverage $min_tpc required for testing POD coverage"
9+ if $@;
10+
11+# Test::Pod::Coverage doesn't require a minimum Pod::Coverage version,
12+# but older versions don't recognize some common documentation styles
13+my $min_pc = 0.18;
14+eval "use Pod::Coverage $min_pc";
15+plan skip_all => "Pod::Coverage $min_pc required for testing POD coverage"
16+ if $@;
17+
18+all_pod_coverage_ok();
--- Fuse-Class/tags/Fuse-Class-0.02/t/00-load.t (nonexistent)
+++ Fuse-Class/tags/Fuse-Class-0.02/t/00-load.t (revision 76)
@@ -0,0 +1,9 @@
1+#!perl -T
2+
3+use Test::More tests => 1;
4+
5+BEGIN {
6+ use_ok( 'Fuse::Class' );
7+}
8+
9+diag( "Testing Fuse::Class $Fuse::Class::VERSION, Perl $], $^X" );
--- Fuse-Class/tags/Fuse-Class-0.02/META.yml (nonexistent)
+++ Fuse-Class/tags/Fuse-Class-0.02/META.yml (revision 76)
@@ -0,0 +1,12 @@
1+# http://module-build.sourceforge.net/META-spec.html
2+#XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX#
3+name: Fuse-Class
4+version: 0.02
5+version_from: lib/Fuse/Class.pm
6+installdirs: site
7+requires:
8+ Fuse: 0
9+ Test::More: 0
10+
11+distribution_type: module
12+generated_by: ExtUtils::MakeMaker version 6.17
--- Fuse-Class/tags/Fuse-Class-0.02/lib/Fuse/Class.pm (nonexistent)
+++ Fuse-Class/tags/Fuse-Class-0.02/lib/Fuse/Class.pm (revision 76)
@@ -0,0 +1,517 @@
1+#
2+# Fuse::Class
3+#
4+# For implementation using class.
5+#
6+
7+package Fuse::Class;
8+
9+use warnings;
10+use strict;
11+
12+=head1 NAME
13+
14+Fuse::Class - Base clsas for Fuse module implementation using class.
15+
16+=head1 VERSION
17+
18+Version 0.02
19+
20+=cut
21+
22+our $VERSION = '0.02';
23+
24+=head1 SYNOPSIS
25+
26+Fuse::Class is just a abstract class. First, you must write subclass
27+overriding methods like named 'getattr'. (callbacks defined in Fuse)
28+
29+Subclass will be written like following:
30+
31+ package SampleFS;
32+
33+ use base qw(Fuse::Class);
34+
35+ sub getattr {
36+ my $self = shift; # instance or class is passed as first argment.
37+ my ($fname) = @_; # same as Fuse.
38+
39+ ...
40+
41+ return @attr; # same as Fuse.
42+ }
43+ ...
44+
45+To mount your filesystem:
46+
47+ use SampleFS;
48+
49+ my $fuse = SampleFS->new("your", "parameters", "here");
50+ $fuse->main(mountpoint => '/mnt/sample', mountopts => "allow_other");
51+
52+When file on your filesystem is opened it will be seen that method
53+is called like this:
54+
55+ $fuse->open($path_name, $flags, $file_info);
56+
57+=head1 DESCRIPTION
58+
59+This module supports writing Fuse callback as method.
60+Method name is same as Fuse callback, but first argment is object.
61+
62+This is a small change for Fuse, but you can use power of OO like
63+inheritance, encapsulation, ...
64+
65+Exception handling:
66+
67+Returned value will be treated as negative errno in Fuse way, but you can
68+use exception, too.
69+If exception is thrown in your method ("die" is called), $! will be used
70+as errno to notify error to Fuse.
71+
72+
73+=head1 EXPORT
74+
75+Nothing.
76+
77+=head1 CONSTRUCTOR
78+
79+=cut
80+
81+use Fuse;
82+use Errno;
83+
84+# instance calling main
85+use vars qw($_Module);
86+
87+=head2 new
88+
89+Create a new instance. This method is defined just for your convenience.
90+Default implementation returns blessed empty HASHREF.
91+
92+=cut
93+
94+#
95+# for your convenience.
96+#
97+sub new {
98+ my $class = shift;
99+ bless {}, $class;
100+}
101+
102+my @callback;
103+
104+=head1 METHODS
105+
106+=cut
107+
108+=head2 main(OPT_KEY1 => OPT_VALUE1, OPT_KEY2 => OPT_VALUE2, ...)
109+
110+Start a main loop. Filesystem is mounted to the mountpoint pointed by
111+option "mountpoint".
112+
113+Options are taken as key=>value pair selected from following:
114+
115+=over
116+
117+=item debug => boolean
118+
119+This option controls tracing on or off. (Default is off).
120+
121+=item mountpoint => "path_to_mountpoint"
122+
123+Directory name to mount filesystem like "/mnt/mypoint".
124+This option has no default value and is mandatory.
125+
126+=item mountopts => "opt1,op2,..."
127+
128+Comma separated options for FUSE kernel module.
129+
130+=item nullpath_ok => boolean
131+
132+If true, empty pathname is passed to the methods like read, write, flush,
133+release, fsync, readdir, releasedir, fsyncdir, ftruncate, fgetattr and lock.
134+
135+To use this option, you must return file/directory handle from
136+open, opendir and create, and you must operate file/directory by
137+that handle insted of pathname.
138+
139+Only effective on Fuse 2.8 or later.
140+
141+=back
142+
143+For more information, see the documentation of Fuse.
144+
145+=cut
146+
147+sub main {
148+ my $self = shift;
149+ my %attr = @_;
150+
151+ my @args;
152+ for my $opt (qw(debug mountpoint mountopts nullpath_ok)) {
153+ push(@args, $opt, $attr{$opt}) if (defined($attr{$opt}));
154+ }
155+
156+ local $_Module = $self;
157+
158+ my %fnmap;
159+ foreach my $fnname (@callback) {
160+ if ($_Module->can($fnname)) {
161+ $fnmap{$fnname} = __PACKAGE__ . '::_' . $fnname;
162+ }
163+ }
164+
165+ Fuse::main(@args, %fnmap);
166+}
167+
168+BEGIN {
169+ @callback = qw (getattr readlink getdir mknod mkdir unlink
170+ rmdir symlink rename link chmod chown truncate
171+ utime open read write statfs flush release fsync
172+ setxattr getxattr listxattr removexattr);
173+ if (Fuse->can('fuse_version')) {
174+ my $fuse_version = Fuse::fuse_version();
175+ if ($fuse_version >= 2.3) {
176+ push(@callback, qw(opendir readdir releasedir fsyncdir init destroy));
177+ }
178+ if ($fuse_version >= 2.5) {
179+ push(@callback, qw(access create ftruncate fgetattr));
180+ }
181+ if ($fuse_version >= 2.6) {
182+ push(@callback, qw(lock utimens bmap));
183+ }
184+ }
185+
186+ no strict "refs";
187+ for my $m (@callback) {
188+ my $method = __PACKAGE__ . "::_$m";
189+
190+ *$method = sub {
191+ my $method_name = $m;
192+
193+ if ($_Module->can($method_name)) {
194+ my @ret = eval {
195+ $_Module->$m(@_);
196+ };
197+ if ($@) {
198+ return $! ? -$! : -Errno::EPERM();
199+ }
200+ else {
201+ return (wantarray() ? @ret : $ret[0]);
202+ }
203+ }
204+ else {
205+ return -Errno::EPERM();
206+ }
207+ }
208+ }
209+}
210+
211+=head1 METHODS MAY OVERRIDDEN
212+
213+=cut
214+
215+=head2 getattr(PATH_NAME)
216+
217+Return a list of file attributes. Meaning of fields are same as
218+"stat" function like this:
219+
220+ ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
221+ $atime,$mtime,$ctime,$blksize,$blocks)
222+
223+On error, return scalar value like -ENOENT().
224+
225+=head2 readlink(PATH_NAME)
226+
227+This method is called to dereference symbolic link.
228+Return a destination path string or numeric error value.
229+
230+By Default implementation, returns -ENOENT().
231+You can leave this method if your FS does not have symlink.
232+
233+=cut
234+
235+sub readlink {
236+ return -Errno::ENOENT();
237+}
238+
239+=head2 getdir(DIRECTORY_NAME)
240+
241+Return a list of file/directory names and an errno (0 if success).
242+ex: ('..', '.', 'a', 'b', 0)
243+
244+If 'readdir' method is implemented, this function will never be called.
245+
246+=head2 mknod(PATH_NAME, MODE, DEVNO)
247+
248+Return an errno (0 if success).
249+This method is called to create an entity (device or file).
250+
251+=head2 mkdir(DIRECTORY_NAME, MODE)
252+
253+Returns an errno (0 if success).
254+This method is called to create a directory.
255+
256+=head2 unlink(PATH_NAME)
257+
258+Returns an errno (0 if success).
259+This method is called to remove an entity (device, file or symlink).
260+
261+=head2 rmdir(PATH_NAME)
262+
263+Returns an errno (0 if success).
264+This method is called to remove a directory.
265+
266+=head2 symlink(EXISTING_PATH_NAME, SYMLINK_NAME)
267+
268+Returns an errno (0 if success).
269+This method is called to create a symbolic link.
270+
271+=head2 rename(OLD_NAME, NEW_NAME)
272+
273+Returns an errno (0 if success).
274+This method is called to rename/move a entity.
275+
276+=head2 link(EXISTING_PATH_NAME, HADLINK_NAME)
277+
278+Return an errno (0 if success).
279+This method is called to create a hard link.
280+
281+=head2 chmod(PATH_NAME, MODE).
282+
283+Return an errno (0 if success).
284+This method is called to change permissions on a entity.
285+
286+=head2 chown(PATH_NAME, UID, GID).
287+
288+Return an errno (0 if success).
289+This method is called to change ownership of a entity.
290+
291+=head2 truncate(PATH_NAME, OFFSET).
292+
293+Return an errno (0 if success).
294+This method is called to truncate a file at the given offset.
295+
296+=head2 utime(PATH_NAME, ACCESS_TIME, MODIF_TIME).
297+
298+Return an errno (0 if success).
299+This method is called to change atime/mtime on a entity.
300+
301+=head2 open(PATH_NAME, FLAGS, FILE_INFO)
302+
303+Returns an errno, and a file handle (optional)
304+
305+First style means like this:
306+
307+ return 0; # success
308+
309+and second one is following:
310+
311+ return (0, $file_handle_you_made); # success and handle
312+
313+FLAGS is an OR-combined value of flags (O_RDONLY, O_SYNC, etc).
314+FILE_INFO is a hashref.
315+
316+Returned file handle will be passed to subsequent method call
317+to operate on opend file.
318+
319+=head2 read(PATH_NAME, SIZE, OFFSET, FILE_HANDLE)
320+
321+Returns an errno, or string scalar of read data.
322+
323+This method is called to read data (SIZE bytes)
324+at the given offset of opened file.
325+
326+=head2 write(PATH_NAME, BUFFER, OFFSET, FILE_HANDLE)
327+
328+Returns a written byte size or an errno.
329+
330+This method is called to write data (BUFFER)
331+at the given offset of opened file.
332+
333+=head2 statfs
334+
335+Returns status of filesystem in one of follwing style:
336+
337+=over
338+
339+=item -ENOANO()
340+
341+or
342+
343+=item $namelen, $files, $files_free, $blocks, $blocks_avail, $blocksize
344+
345+or
346+
347+=item -ENOANO(), $namelen, $files, $files_free, $blocks, $blocks_avail, $blocksize
348+
349+=back
350+
351+=cut
352+
353+sub statfs {
354+ return -Errno::ENOANO();
355+}
356+
357+=head2 flush(PATH_NAME, FILE_HANDLE)
358+
359+Returns an errno (0 if success).
360+This method is called to synchronize any cached data.
361+
362+=cut
363+
364+sub flush {
365+ return 0;
366+}
367+
368+=head2 release(PATH_NAME, FLAGS, FILE_HANDLE)
369+
370+Return an errno (0 if success).
371+
372+FLAGS is a same value passed when 'open' is called.
373+
374+Called to indicate that there are no more references to the file and flags.
375+
376+=cut
377+
378+sub release {
379+ return 0;
380+}
381+
382+=head2 fsync(PATH_NAME, DATA_SYNC, FILE_HANDLE)
383+
384+Return an errno (0 if success).
385+
386+Called to synchronize file contents.
387+
388+DATA_SYNC indicates 'user data only'. If DATA_SYNC is non-zero,
389+only the user data should be synchronized. Otherwise synchronize
390+user and meta data.
391+
392+=cut
393+
394+sub fsync {
395+ return 0;
396+}
397+
398+=head2 setxattr(PATH_NAME, ATTR_NAME, ATTR_VALUE, FLAGS)
399+
400+FLAGS is OR-ed value of Fuse::XATTR_CREATE and Fuse::XATTR_REPLACE
401+
402+Return an errno (0 if success).
403+
404+This method is called to set extended attribute.
405+
406+-EOPNOTSUPP means that setting the attribute is rejected.
407+
408+If XATTR_CREATE is passed and the attribute already exists, return -EEXIST.
409+
410+If XATTR_REPLACE is passed and the attribute does not exist, return -ENOATTR.
411+
412+By default implementation, returns -EOPNOTSUPP.
413+You can leave this method if your FS does not have any extended attributes.
414+
415+=cut
416+
417+sub setxattr {
418+ return -Errno::EOPNOTSUPP();
419+}
420+
421+=head2 getxattr(PATH_NAME, ATTR_NAME)
422+
423+Return attribute value or errno (0 if no value).
424+
425+This method is called to get extended attribute value.
426+
427+By default implementation, returns 0.
428+You can leave this method if your FS does not have any extended attributes.
429+
430+=cut
431+
432+sub getxattr {
433+ return 0;
434+}
435+
436+=head2 listxattr(PATH_NAME)
437+
438+Returns a list of attribute names and an errno (0 if success).
439+ex: ('attr1', 'attr2', 'attr3', 0)
440+
441+By default implementation, returns 0.
442+You can leave this method if your FS does not have any extended attributes.
443+
444+=cut
445+
446+sub listxattr {
447+ return 0;
448+}
449+
450+=head2 removexattr(PATH_NAME, ATTR_NAME)
451+
452+Return an errno (0 if success).
453+
454+This method is called to remove an attribute from entity.
455+
456+By default implementation, returns 0.
457+You can leave this method if your FS does not have any extended attributes.
458+
459+=cut
460+
461+sub removexattr {
462+ return 0;
463+}
464+
465+=head2 opendir(DIRECTORY_NAME)
466+
467+Returns an errno, and a directory handle (optional).
468+
469+This method is called to open a directory for reading.
470+If special handling is required to open a directory, this method
471+can be implemented.
472+
473+Supported by Fuse version 2.3 or later.
474+
475+=cut
476+
477+# sub opendir {
478+# return -Errno::EOPNOTSUPP();
479+# }
480+
481+=head2 readdir(DIRECTORY_NAME, OFFSET, HANDLE)
482+
483+(HANDLE is optional. see opendir)
484+
485+Returns ...
486+ex: ('..', '.', 'a', 'b', 0)
487+
488+Supported by Fuse version 2.3 or later.
489+
490+=cut
491+
492+# sub readdir {
493+# return -Errno::EOPNOTSUPP();
494+# }
495+
496+=head1 AUTHOR
497+
498+Toshimitsu FUJIWARA, C<< <tttfjw at gmail.com> >>
499+
500+=head1 BUGS
501+
502+Threading is not tested.
503+
504+=head1 COPYRIGHT & LICENSE
505+
506+Copyright 2008-2011 Toshimitsu FUJIWARA, all rights reserved.
507+
508+This program is free software; you can redistribute it and/or modify it
509+under the same terms as Perl itself.
510+
511+=head1 SEE ALSO
512+
513+Fuse
514+
515+=cut
516+
517+1; # End of xxx
--- Fuse-Class/tags/Fuse-Class-0.02/README (nonexistent)
+++ Fuse-Class/tags/Fuse-Class-0.02/README (revision 76)
@@ -0,0 +1,38 @@
1+Fuse-Class
2+
3+Fuse::Class - Base clsas for Fuse module implementation using class.
4+
5+This module supports writing Fuse callback as method.
6+Method name is same as Fuse callback, but first argment is object.
7+
8+This is a small change for Fuse, but you can use power of OO like
9+inheritance, encapsulation, ...
10+
11+
12+INSTALLATION
13+
14+To install this module, run the following commands:
15+
16+ perl Makefile.PL
17+ make
18+ make test
19+ make install
20+
21+(For the full test, you need Test::Virtual::Filesystem module.)
22+
23+
24+SUPPORT AND DOCUMENTATION
25+
26+After installing, you can find documentation for this module with the
27+perldoc command.
28+
29+ perldoc Fuse::Class
30+
31+
32+COPYRIGHT AND LICENCE
33+
34+Copyright (C) 2008 Toshimitsu FUJIWARA
35+
36+This program is free software; you can redistribute it and/or modify it
37+under the same terms as Perl itself.
38+
Show on old repository browser