• R/O
  • SSH
  • HTTPS

perl-fuse-fv: Commit


Commit MetaInfo

Revision73 (tree)
Zeit2011-08-21 21:15:53
Autortofjw

Log Message

fuse28.pm passes all tests.

Ändern Zusammenfassung

Diff

--- Fuse-Class/trunk/test/fuse28.pm (revision 72)
+++ Fuse-Class/trunk/test/fuse28.pm (revision 73)
@@ -15,30 +15,19 @@
1515 sub new {
1616 my $class = shift;
1717
18- my $t = 12345;
19-
2018 my $self = {
21- content => {
22- '/' => {
23- attr => [0, 0,
24- Fcntl::S_IFDIR
25- | Fcntl::S_IRWXU | Fcntl::S_IRWXG | Fcntl::S_IRWXO,
26- 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
27- }
28- },
19+ root => test::fuse28::Directory->new,
2920
3021 handle => {
3122 }
3223 };
3324
34- use Data::Dumper;
35- print Dumper($self);
3625 return bless $self, $class;
3726 }
3827
3928 sub issue_handle {
4029 my $self = shift;
41- my ($path) = @_;
30+ my $obj = shift;
4231
4332 my $i = 0;
4433 while ($self->{handle}->{$i}) {
@@ -45,7 +34,7 @@
4534 $i++;
4635 }
4736
48- $self->{handle}->{$i} = [$path, $self->{content}->{$path}];
37+ $self->{handle}->{$i} = $obj;
4938
5039 return $i;
5140 }
@@ -57,19 +46,53 @@
5746 delete $self->{handle}->{$fh};
5847 }
5948
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+
6077 sub getattr {
6178 my $self = shift;
6279 my ($path) = @_;
6380
64- return -2 unless ($self->{content}->{$path});
81+ my $entity = $self->pickup($path);
82+ return -2 unless ($entity);
6583
66- return @{$self->{content}->{$path}->{attr}};
84+ return $entity->attr;
6785 }
6886
6987 sub readlink {
7088 my $self = shift;
89+ my ($path) = @_;
7190
72- return '/readlink/result';
91+ my $entity = $self->pickup($path);
92+ return -2 unless ($entity);
93+ return -1 unless ($entity->can('readlink'));
94+
95+ return $entity->readlink;
7396 }
7497
7598 sub getdir {
@@ -76,7 +99,8 @@
7699 my $self = shift;
77100 my ($path) = @_;
78101
79- die "this function must not be called.";
102+ # die "this function must not be called.";
103+ return -1;
80104 }
81105
82106 sub mknod {
@@ -83,18 +107,13 @@
83107 my $self = shift;
84108 my ($path, $mode, $devno) = @_;
85109
86- return -1 if ($self->{content}->{$path});
87-
88- my $t = time;
110+ my ($dirname, $name) = ($path =~ m/^(.*)\/([^\/]+)$/);
111+ return -2 unless (defined($dirname) && defined($name)); # badname ?
89112
90- $self->{content}->{$path} = {
91- attr => [0, 0, $mode, 1,
92- $>+0, $)+0, $devno, 0, $t, $t, $t,
93- 4096, 0,
94- ],
95- content => '',
96- };
97- return 0;
113+ my $dir = $self->pickup($dirname);
114+ return -2 unless ($dir);
115+
116+ return $dir->mknod($name, $mode, $devno);
98117 }
99118
100119 sub mkdir {
@@ -101,19 +120,13 @@
101120 my $self = shift;
102121 my ($path, $mode) = @_;
103122
104- return -1 if ($self->{content}->{$path});
123+ my ($dirname, $name) = ($path =~ m/^(.*)\/([^\/]+)$/);
124+ return -2 unless (defined($dirname) && defined($name)); # badname ?
105125
106- $mode |= Fcntl::S_IFDIR;
107- my $t = time;
126+ my $dir = $self->pickup($dirname);
127+ return -2 unless ($dir);
108128
109- $self->{content}->{$path} = {
110- attr => [0, 0, $mode, 1,
111- $>+0, $)+0, 0, 0, $t, $t, $t,
112- 1, 0,
113- ],
114- content => '',
115- };
116- return 0;
129+ return $dir->mkdir($name, $mode);
117130 }
118131
119132 sub unlink {
@@ -120,9 +133,13 @@
120133 my $self = shift;
121134 my ($path) = @_;
122135
123- delete $self->{content}->{$path};
136+ my ($dirname, $name) = ($path =~ m/^(.*)\/([^\/]+)$/);
137+ return -2 unless (defined($dirname) && defined($name)); # badname ?
124138
125- return 0;
139+ my $dir = $self->pickup($dirname);
140+ return -2 unless ($dir);
141+
142+ return $dir->unlink($name);
126143 }
127144
128145 sub rmdir {
@@ -129,30 +146,61 @@
129146 my $self = shift;
130147 my ($path) = @_;
131148
132- my $s = '/';
133- my $prefix = $path;
134- $prefix .= $s unless ($prefix =~ /\Q$s\E$/);
149+ my ($dirname, $name) = ($path =~ m/^(.*)\/([^\/]+)$/);
150+ return -2 unless (defined($dirname) && defined($name)); # badname ?
135151
136- my @names = grep { m|^\Q$prefix\E| } keys %{$self->{content}};
137- unshift(@names, $path);
152+ my $dir = $self->pickup($dirname);
153+ return -2 unless ($dir);
138154
139- for my $p (@names) {
140- delete $self->{content}->{$p};
141- }
155+ return $dir->rmdir($name);
156+}
142157
143- # use Data::Dumper;
144- # print STDERR Dumper($self);
158+sub symlink {
159+ my $self = shift;
160+ my ($existing, $symlink) = @_;
145161
146- return 0;
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);
147169 }
148170
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+
149190 sub opendir {
150191 my $self = shift;
151192 my ($path) = @_;
152193
153- return (-2) unless ($self->{content}->{$path});
194+ my $entity = $self->pickup($path);
195+ return (-2) unless ($entity);
154196
155- return (0, $self->issue_handle($path));
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+ }
156204 }
157205
158206 sub readdir {
@@ -159,19 +207,11 @@
159207 my $self = shift;
160208 my ($path, $offset, $dh) = @_;
161209
162- return (-2) unless (defined($self->{handle}->{$dh}));
210+ my $dir = $self->{handle}->{$dh};
211+ return (-2) unless ($dir);
163212
164- my $s = '/';
165- my $prefix = $self->{handle}->{$dh}->[0];
166- $prefix .= $s unless ($prefix =~ /\Q$s\E$/);
213+ my @names = $dir->readdir;
167214
168- my @names =
169- map { substr($_, length($prefix)) }
170- sort
171- grep { m|^\Q$prefix\E[^\Q$s\E]+$| } keys %{$self->{content}};
172-
173- unshift(@names, '.');
174-
175215 if ($offset < @names) {
176216 return (@names[$offset..$#names], 0);
177217 }
@@ -191,18 +231,46 @@
191231 return -2;
192232 }
193233
194-sub truncate {
234+sub chmod {
195235 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;
196256 my ($path, $offset, $fh) = @_;
197257
198- return -2 unless (defined($self->{content}->{$path}));
258+ my $entity = $self->{handle}->{$fh};
259+ return (-2) unless ($entity);
260+ return (-1) unless ($entity->can('truncate'));
199261
200- my $data = $self->{content}->{$path}->{content};
201- return -1 unless (defined($data));
262+ $entity->truncate($offset);
263+}
202264
203- $self->{content}->{$path}->{content} = substr($data, 0, $offset);
265+sub truncate {
266+ my $self = shift;
267+ my ($path, $offset) = @_;
204268
205- return 0;
269+ my $entity = $self->pickup($path);
270+ return -2 unless ($entity);
271+ return -1 unless ($entity->can('truncate'));
272+
273+ $entity->truncate($offset);
206274 }
207275
208276 sub utime {
@@ -209,7 +277,8 @@
209277 my $self = shift;
210278 my ($path, $atime, $mtime) = @_;
211279
212- die "utimens must be called";
280+ # die "utimens must be called";
281+ return -1;
213282 }
214283
215284 sub open {
@@ -216,13 +285,10 @@
216285 my $self = shift;
217286 my ($path, $flags, $fileinfo) = @_;
218287
219- print STDERR "open: $path, $flags\n";
220- # use Data::Dumper;
221- # print STDERR Dumper($fileinfo);
288+ my $entity = $self->pickup($path);
289+ return (-2) unless ($entity);
222290
223- return (-2) unless ($self->{content}->{$path});
224-
225- return (0, $self->issue_handle($path));
291+ return (0, $self->issue_handle($entity));
226292 }
227293
228294 sub write {
@@ -229,15 +295,11 @@
229295 my $self = shift;
230296 my ($path, $buffer, $offset, $fh) = @_;
231297
232- return (-2) unless (defined($self->{handle}->{$fh}));
298+ my $entity = $self->{handle}->{$fh};
299+ return (-2) unless ($entity);
300+ return (-1) unless ($entity->can('write'));
233301
234- my $file = $self->{handle}->{$fh}->[1];
235- my $data = $file->{content};
236- substr($data, $offset) = $buffer;
237- $file->{content} = $data;
238- $file->{attr}->[7] = length($data);
239-
240- return length($buffer);
302+ $entity->write($buffer, $offset);
241303 }
242304
243305 sub read {
@@ -244,12 +306,11 @@
244306 my $self = shift;
245307 my ($path, $size, $offset, $fh) = @_;
246308
247- return (-2) unless (defined($self->{handle}->{$fh}));
309+ my $entity = $self->{handle}->{$fh};
310+ return (-2) unless ($entity);
311+ return (-1) unless ($entity->can('read'));
248312
249- my $file = $self->{handle}->{$fh}->[1];
250- my $data = $file->{content};
251-
252- return substr($data, $offset, $size);
313+ $entity->read($size, $offset);
253314 }
254315
255316 sub statfs {
@@ -262,14 +323,302 @@
262323 my $self = shift;
263324 my ($path, $atime, $mtime) = @_;
264325
265- return -2 unless ($self->{content}->{$path});
326+ my $entity = $self->pickup($path);
327+ return -2 unless ($entity);
266328
267- my $attr = $self->{content}->{$path}->{attr};
329+ return $entity->utimens($atime, $mtime);
330+}
268331
269- $attr->[8] = $atime;
270- $attr->[9] = $mtime;
271-
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+
272367 return 0;
273368 }
274369
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+
275624 1;
--- Fuse-Class/trunk/t/80fuse28.t (revision 72)
+++ Fuse-Class/trunk/t/80fuse28.t (revision 73)
@@ -82,8 +82,8 @@
8282 my $child_pid = -1;
8383
8484 eval {
85- plan tests => 1;
86- is(1, 1);
85+ plan tests => 155;
86+
8787 $child_pid = fork();
8888 die $! if ($child_pid < 0);
8989
@@ -95,20 +95,68 @@
9595 sleep(3);
9696
9797 my $test = Test::Virtual::Filesystem->new({mountdir => $mount_point,
98- compatible => '0.03'});
99- $test->enable_test_xattr(1);
100- # $test->enable_test_chown(1);
98+ compatible => '0.08'});
99+ $test->enable_test_xattr(0);
100+ $test->enable_test_time(1);
101101 # $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+
102112 $test->runtests;
103113
104- system("df");
114+ #
115+ # not tested? by T:V:F
116+ #
117+
118+ # unlink
119+ {
120+ my $fname = "$mount_point/unlink-test";
121+ unlink $fname;
122+ open(my $fh, "> $fname");
123+ close($fh);
124+
125+ ok(-f $fname);
126+ unlink $fname;
127+ ok(!-f $fname);
128+ }
129+
130+ # chmod
131+ {
132+ my $fname = "$mount_point/chmod-test";
133+ unlink $fname;
134+ open(my $fh, "> $fname");
135+ close($fh);
136+ chmod(0642, $fname);
137+ my $perm = (stat $fname)[2] & 0777;
138+ ok($perm == 0642);
139+ }
140+
141+ # ftrunate
142+ {
143+ my $fname = "$mount_point/ftruncate-test";
144+ unlink $fname;
145+ open(my $fh1, "> $fname");
146+ print $fh1 "12345";
147+ close($fh1);
148+
149+ open(my $fh2, "+< $fname");
150+ truncate($fh2, 3);
151+ close($fh2);
152+
153+ my $size = (stat $fname)[7];
154+ ok($size == 3);
155+ }
105156 };
106157
107158 my $err = $@;
108159 cleanup($child_pid);
109160
110- if ($child_pid > 0) {
111- }
112-
113161 die $err if ($err);
114162 }
--- Fuse-Class/trunk/META.yml (revision 72)
+++ Fuse-Class/trunk/META.yml (revision 73)
@@ -1,7 +1,7 @@
11 # http://module-build.sourceforge.net/META-spec.html
22 #XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX#
33 name: Fuse-Class
4-version: 0.01
4+version: 0.02
55 version_from: lib/Fuse/Class.pm
66 installdirs: site
77 requires:
--- Fuse-Class/trunk/lib/Fuse/Class.pm (revision 72)
+++ Fuse-Class/trunk/lib/Fuse/Class.pm (revision 73)
@@ -239,7 +239,7 @@
239239 =head2 getdir(DIRECTORY_NAME)
240240
241241 Return a list of file/directory names and an errno (0 if success).
242-ex: ('.', 'a', 'b', 0)
242+ex: ('..', '.', 'a', 'b', 0)
243243
244244 If 'readdir' method is implemented, this function will never be called.
245245
@@ -470,6 +470,21 @@
470470 # return -Errno::EOPNOTSUPP();
471471 # }
472472
473+=head2 readdir(DIRECTORY_NAME, OFFSET, HANDLE)
474+
475+(HANDLE is optional. see opendir)
476+
477+Returns ...
478+ex: ('..', '.', 'a', 'b', 0)
479+
480+Supported by Fuse version 2.3 or later.
481+
482+=cut
483+
484+# sub readdir {
485+# return -Errno::EOPNOTSUPP();
486+# }
487+
473488 =head1 AUTHOR
474489
475490 Toshimitsu FUJIWARA, C<< <tttfjw at gmail.com> >>
Show on old repository browser