package Brackup::GPGProcess;
use strict;
use warnings;
use Brackup::Util qw(tempfile);
use POSIX qw(_exit);

sub new {
    my ($class, $pchunk) = @_;

    my ($destfh, $destfn) = tempfile();

    my $no_fork = 0;  # if true (perhaps on Windows?), then don't fork... do all inline.

    my $pid = $no_fork ? 0 : fork;
    if (!defined $pid) {
        die "Failed to fork: $!";
    }

    # caller (parent)
    if ($pid) {
        return bless {
            destfn    => $destfn,
            pid       => $pid,
            running   => 1,
        }, $class;
    }

    # child:  encrypt and exit(0)...
    my $enc = $pchunk->root->encrypt($pchunk->raw_chunkref);
    my $enc_len = length($enc);

    binmode($destfh);
    print $destfh $enc
        or die "failed to print: $!";
    close $destfh
        or die "failed to close: $!";

    my $wrote_size = -s $destfn;
    unless (defined $wrote_size && $wrote_size == $enc_len) {
        unless (-e $destfn) {
            # if the file's gone, that likely means the parent process
            # already terminated and unlinked our temp file, in
            # which case we should just exit (with error code), rather
            # than spewing error messages to stderr.
            POSIX::_exit(1);
        }
        $wrote_size = "<undef>" unless defined $wrote_size;
        die "size not right (expected $enc_len; got $wrote_size)";
    }

    if ($no_fork) {
        return bless {
            destfn => $destfn,
            pid    => 0,
        }, $class;
    }

    # Note: we have to do this, to avoid some END block, somewhere,
    # from cleaning up something or doing something.  probably tempfiles
    # being destroyed in File::Temp.
    POSIX::_exit(0);
}

sub pid { $_[0]{pid} }

sub running { $_[0]{running} }
sub note_stopped { $_[0]{running} = 0; }

sub chunkref {
    my ($self) = @_;
    die "Still running!" if $self->{running};

    open(my $fh, $self->{destfn})
        or die "Failed to open gpg temp file $self->{destfn}: $!";
    binmode($fh);
    my $data = do { local $/; <$fh>; };
    die "No data in file" unless length $data;
    close($fh);
    unlink($self->{destfn}) or die "couldn't delete destfn";

    # unlink
    return \$data;
}

sub size_on_disk {
    my $self = shift;
    return -s $self->{destfn};
}

1;



syntax highlighted by Code2HTML, v. 0.9.1