]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/GitCatFile.pm
update copyright headers and email addresses
[public-inbox.git] / lib / PublicInbox / GitCatFile.pm
index b75389e2fdb3ebf5958c5366dffd5356dfbf22d6..4f16762e56c8959eaaed4c7d91d3a7e647f7e729 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2014, Eric Wong <normalperson@yhbt.net> and all contributors
+# Copyright (C) 2014-2015 all contributors <meta@public-inbox.org>
 # License: GPLv2 or later (https://www.gnu.org/licenses/gpl-2.0.txt)
 # This is based on code in Git.pm which is GPLv2, but modified to avoid
 # dependence on environment variables for compatibility with mod_perl.
@@ -6,30 +6,20 @@
 package PublicInbox::GitCatFile;
 use strict;
 use warnings;
-use Fcntl qw(F_GETFD F_SETFD FD_CLOEXEC);
 use POSIX qw(dup2);
-require IO::Handle;
 
 sub new {
        my ($class, $git_dir) = @_;
        bless { git_dir => $git_dir }, $class;
 }
 
-sub set_cloexec {
-       my ($fh) = @_;
-       my $flags = fcntl($fh, F_GETFD, 0) or die "fcntl(F_GETFD): $!\n";
-       fcntl($fh, F_SETFD, $flags | FD_CLOEXEC) or die "fcntl(F_SETFD): $!\n";
-}
-
 sub _cat_file_begin {
        my ($self) = @_;
        return if $self->{pid};
        my ($in_r, $in_w, $out_r, $out_w);
 
        pipe($in_r, $in_w) or die "pipe failed: $!\n";
-       set_cloexec($_) foreach ($in_r, $in_w);
        pipe($out_r, $out_w) or die "pipe failed: $!\n";
-       set_cloexec($_) foreach ($out_r, $out_w);
 
        my @cmd = ('git', "--git-dir=$self->{git_dir}", qw(cat-file --batch));
        my $pid = fork;
@@ -42,7 +32,6 @@ sub _cat_file_begin {
        close $out_r or die "close failed: $!\n";
        close $in_w or die "close failed: $!\n";
 
-       $out_w->autoflush(1);
        $self->{in} = $in_r;
        $self->{out} = $out_w;
        $self->{pid} = $pid;
@@ -51,8 +40,16 @@ sub _cat_file_begin {
 sub cat_file {
        my ($self, $object) = @_;
 
+       $object .= "\n";
+       my $len = bytes::length($object);
+
        $self->_cat_file_begin;
-       print { $self->{out} } $object, "\n" or die "write error: $!\n";
+       my $written = syswrite($self->{out}, $object);
+       if (!defined $written) {
+               die "pipe write error: $!\n";
+       } elsif ($written != $len) {
+               die "wrote too little to pipe ($written < $len)\n";
+       }
 
        my $in = $self->{in};
        my $head = <$in>;
@@ -62,17 +59,17 @@ sub cat_file {
 
        my $size = $1;
        my $bytes_left = $size;
-       my $buf;
+       my $offset = 0;
        my $rv = '';
 
        while ($bytes_left) {
-               my $read = read($in, $buf, $bytes_left);
-               defined($read) or die "read pipe failed: $!\n";
-               $rv .= $buf;
+               my $read = read($in, $rv, $bytes_left, $offset);
+               defined($read) or die "sysread pipe failed: $!\n";
                $bytes_left -= $read;
+               $offset += $read;
        }
 
-       my $read = read($in, $buf, 1);
+       my $read = read($in, my $buf, 1);
        defined($read) or die "read pipe failed: $!\n";
        if ($read != 1 || $buf ne "\n") {
                die "newline missing after blob\n";