+ my($a, $fio, $fList, $outputFunc) = @_;
+ my $name = $a->{relPath};
+ my $n = $name;
+ my $type = $fio->mode2type($a->{mode});
+ my $extraAttribs = {};
+
+ $n =~ s/^\Q$fio->{xfer}{pathHdrSrc}//;
+ $fio->log("Sending $name (remote=$n)") if ( $fio->{logLevel} >= 4 );
+ if ( $type == BPC_FTYPE_CHARDEV
+ || $type == BPC_FTYPE_BLOCKDEV
+ || $type == BPC_FTYPE_SYMLINK ) {
+ my $fh = BackupPC::FileZIO->open($a->{fullPath}, 0, $a->{compress});
+ my($str, $rdSize);
+ if ( defined($fh) ) {
+ $rdSize = $fh->read(\$str, $a->{size} + 1024);
+ if ( $type == BPC_FTYPE_SYMLINK ) {
+ #
+ # Reconstruct symbolic link
+ #
+ $extraAttribs = { link => $str };
+ if ( $rdSize != $a->{size} ) {
+ # ERROR
+ $fio->log("$name: can't read exactly $a->{size} bytes");
+ $fio->{stats}{errorCnt}++;
+ }
+ } elsif ( $str =~ /(\d*),(\d*)/ ) {
+ #
+ # Reconstruct char or block special major/minor device num
+ #
+ # Note: char/block devices have $a->{size} = 0, so we
+ # can't do an error check on $rdSize.
+ #
+ $extraAttribs = { rdev => $1 * 256 + $2 };
+ } else {
+ $fio->log("$name: unexpected special file contents $str");
+ $fio->{stats}{errorCnt}++;
+ }
+ $fh->close;
+ } else {
+ # ERROR
+ $fio->log("$name: can't open");
+ $fio->{stats}{errorCnt}++;
+ }
+ }
+ my $f = {
+ name => $n,
+ #dev => 0, # later, when we support hardlinks
+ #inode => 0, # later, when we support hardlinks
+ mode => $a->{mode},
+ uid => $a->{uid},
+ gid => $a->{gid},
+ mtime => $a->{mtime},
+ size => $a->{size},
+ %$extraAttribs,
+ };
+ $fList->encode($f);
+ $f->{name} = "$fio->{xfer}{pathHdrDest}/$f->{name}";
+ $f->{name} =~ s{//+}{/}g;
+ $fio->logFileAction("restore", $f) if ( $fio->{logLevel} >= 1 );