Fuse-PDF
view release on metacpan or search on metacpan
lib/Fuse/PDF/FS.pm view on Meta::CPAN
$xattr->{value}->{$key} = CAM::PDF::Node->new('string', $value, $o, $g);
$self->{fs}->{mtime}->{value} = time;
$self->{dirty} = 1;
return 0;
}
sub fs_getxattr {
my ($self, $abspath, $key) = @_;
my $f = $self->_file($abspath);
return -$f if !ref $f;
my $xattr = $f->{xattr};
return 0 if !$xattr;
return 0 if !exists $xattr->{value}->{$key};
return $xattr->{value}->{$key}->{value};
}
sub fs_listxattr {
my ($self, $abspath, $key) = @_;
my $f = $self->_file($abspath);
return -$f if !ref $f;
my $xattr = $f->{xattr};
return ($xattr ? keys %{ $xattr->{value} } : ()), 0;
}
sub fs_removexattr {
my ($self, $abspath, $key) = @_;
my $f = $self->_file($abspath);
return -$f if !ref $f;
my $xattr = $f->{xattr};
return -ENOATTR() if !$xattr;
return -ENOATTR() if !exists $xattr->{value}->{$key};
delete $xattr->{value}->{$key};
$self->{fs}->{mtime}->{value} = time;
$self->{dirty} = 1;
return 0;
}
# --------------------------------------------------
sub _parent {
my ($self, $path) = @_;
my ($errno, $dirs, $paths) = $self->_readpath($path, 1);
return $errno if $errno;
return $dirs->[-2], $paths->[-1], $dirs->[-1]; ## no critic(MagicNumber)
}
sub _file {
my ($self, $path) = @_;
my ($errno, $dirs, $paths) = $self->_readpath($path);
return $errno if $errno;
return $dirs->[-1];
}
sub _readpath {
my ($self, $path, $parent, $nsymlinks) = @_;
$nsymlinks ||= 0;
my @dirs = ($self->{fs}->{root}->{value});
my @path = split m{/}xms, $path;
my @realpath;
for (my $i = 0; $i < @path; ++$i) { ##no critic(ProhibitCStyleForLoops)
my $entry = $path[$i];
next if q{} eq $entry;
my $type = $dirs[-1]->{type}->{value};
return ENOTDIR() if 'd' ne $type;
next if q{.} eq $entry;
if (q{..} eq $entry) {
pop @dirs;
pop @realpath;
return EACCESS() if !@dirs; # tried to get parent of root
next;
}
push @realpath, $entry;
my $next = $dirs[-1]->{content}->{value}->{$entry};
if (!$next) {
if ($parent && $i == $#path) {
push @dirs, undef;
return 0, \@dirs, \@realpath;
}
return ENOENT();
}
my $f = $next->{value};
if ('l' eq $f->{type}->{value}) {
if ($i != $#path) {
return ELOOP() if ++$nsymlinks >= $ELOOP_LIMIT;
my $linkpath = $f->{content}->{value};
# cannot leave the filesystem
return EACCESS() if $linkpath =~ m{\A /}xms;
splice @path, $i, 1, split m{/}xms, $linkpath;
return $self->_readpath((join q{/}, @path), $parent, $nsymlinks);
}
}
push @dirs, $f;
}
return 0, \@dirs, \@realpath;
}
sub _newfile {
my ($self, $parent, $perm) = @_;
my ($o, $g) = ($parent->{objnum}, $parent->{gennum});
return $self->_newentry($o, $g, S_IFREG | $perm,
'f', CAM::PDF::Node->new('string', q{}, $o, $g));
}
sub _newsymlink {
my ($self, $parent, $src) = @_;
my ($o, $g) = ($parent->{objnum}, $parent->{gennum});
return $self->_newentry($o, $g, S_IFLNK | $DEFAULT_SYMLINK_PERMS,
'l', CAM::PDF::Node->new('string', $src, $o, $g));
}
sub _newdir {
my ($self, $parent, $perm) = @_;
# MUST NOT create an new PDF objects
my ($o, $g) = ($parent->{objnum}, $parent->{gennum});
my $dir = $self->_newentry($o, $g, S_IFDIR() | $perm,
'd', CAM::PDF::Node->new('dictionary', {}, $o, $g));
$dir->{value}->{nlink}->{value}++;
return $dir;
}
sub _newentry { ##no critic(ProhibitManyArgs)
my ($self, $o, $g, $perm, $type, $content) = @_;
# MUST NOT create an new PDF objects if type = 'd'
my $now = time;
return CAM::PDF::Node->new('dictionary', {
content => $content,
type => CAM::PDF::Node->new('string', $type, $o, $g),
inode => CAM::PDF::Node->new('number', 0, $o, $g),
mode => CAM::PDF::Node->new('number', $perm, $o, $g),
nlink => CAM::PDF::Node->new('number', 1, $o, $g),
mtime => CAM::PDF::Node->new('number', $now, $o, $g),
ctime => CAM::PDF::Node->new('number', $now, $o, $g),
}, $o, $g);
}
1;
__END__
=pod
=for stopwords pdf runtime EIO
=head1 NAME
Fuse::PDF::FS - In-PDF implementation of a filesystem.
( run in 0.983 second using v1.01-cache-2.11-cpan-71847e10f99 )