Brackup

 view release on metacpan or  search on metacpan

lib/Brackup/File.pm  view on Meta::CPAN

package Brackup::File;
# "everything is a file"
#  ... this class includes symlinks and directories

use strict;
use warnings;
use Carp qw(croak);
use File::stat ();
use Fcntl qw(S_ISREG S_ISDIR S_ISLNK S_ISFIFO O_RDONLY);
use Digest::SHA1;
use String::Escape qw(printable);
use Brackup::PositionedChunk;
use Brackup::Chunker::Default;
use Brackup::Chunker::MP3;

sub new {
    my ($class, %opts) = @_;
    my $self = bless {}, $class;

    $self->{root} = delete $opts{root};
    $self->{path} = delete $opts{path};
    $self->{stat} = delete $opts{stat};  # File::stat object
    croak("Unknown options: " . join(', ', keys %opts)) if %opts;

    die "No root object provided." unless $self->{root} && $self->{root}->isa("Brackup::Root");
    die "No path provided." unless defined($self->{path});  # note: permit "0"
    $self->{path} =~ s!^\./!!;

    return $self;
}

sub root {
    my $self = shift;
    return $self->{root};
}

# returns File::stat object
sub stat {
    my $self = shift;
    return $self->{stat} if $self->{stat};
    my $path = $self->fullpath;
    my $stat = File::stat::lstat($path);
    return $self->{stat} = $stat;
}

sub size {
    my $self = shift;
    return $self->stat->size;
}

sub is_dir {
    my $self = shift;
    return S_ISDIR($self->stat->mode);
}

sub is_link {
    my $self = shift;
    my $result = eval { S_ISLNK($self->stat->mode) };
    $result = -l $self->fullpath unless defined($result);
    return $result;
}

sub is_file {
    my $self = shift;
    return S_ISREG($self->stat->mode);
}

sub is_fifo {
    my $self = shift;
    return S_ISFIFO($self->stat->mode);
}

# Returns file type like find's -type
sub type {
    my $self = shift;
    return "f" if $self->is_file;
    return "d" if $self->is_dir;
    return "l" if $self->is_link;
    return "p" if $self->is_fifo;
    return "";
}

sub fullpath {
    my $self = shift;
    return $self->{root}->path . "/" . $self->{path};
}

# a scalar that hopefully uniquely represents a single version of a file in time.
sub cachekey {
    my $self = shift;
    my $st   = $self->stat;
    return "[" . $self->{root}->name . "]" . $self->{path} . ":" . join(",", $st->ctime, $st->mtime, $st->size, $st->ino);
}

# Returns the appropriate FileChunker class for the provided file's
# type.  In most cases this FileChunker will be very dumb, just making
# equal-sized chunks for, say, 5MB, but in specialized cases (like mp3
# files), the chunks will be one (or two) small ones for the ID3v1/v2
# chunks, and one big chunk for the audio bytes (which might be cut
# into its own small chunks).  This way the mp3 metadata can be
# changed without needing to back up the entire file again ... just
# the changed metadata.



( run in 3.743 seconds using v1.01-cache-2.11-cpan-2398b32b56e )