File Coverage

blib/lib/IPC/PerlSSH/Library/IO.pm
Criterion Covered Total %
statement 9 9 100.0
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 12 12 100.0


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2009-2011 -- leonerd@leonerd.org.uk
5              
6             package IPC::PerlSSH::Library::IO;
7              
8 1     1   6 use strict;
  1         2  
  1         54  
9 1     1   7 use warnings;
  1         3  
  1         89  
10              
11 1     1   7 use IPC::PerlSSH::Library;
  1         3  
  1         3158  
12              
13             our $VERSION = '0.16';
14              
15             =head1 NAME
16              
17             C - a library of file IO functions for
18             C
19              
20             =head1 SYNOPSIS
21              
22             use IPC::PerlSSH;
23              
24             my $ips = IPC::PerlSSH->new( Host => "over.there" );
25              
26             $ips->use_library( "IO", qw( open fchmod write close ) );
27              
28             my $fd = $ips->call( "open", ">", "secret.txt" );
29             $ips->call( "fchmod", $fd, 0600 );
30             $ips->call( "write", $fd, "s3kr1t\n" );
31             $ips->call( "close" );
32              
33             =head1 DESCRIPTION
34              
35             This module provides a library of functions for interacting with remote IO
36             filehandles. It provides simple wrappers around the perl IO functions, taking
37             or returning file descriptor numbers instead of filehandle objects. This
38             allows filehandles to remain open in the remote perl instance, across many
39             Cs.
40              
41             Because the filehandles remain open, the program must take care to call
42             C at the appropriate time, so as not to leak file descriptors in the
43             remote perl.
44              
45             =cut
46              
47             init q[
48             use IO::Handle;
49              
50             our %handles;
51              
52             sub store_handle
53             {
54             my $fh = shift;
55             my $fd = $fh->fileno;
56             $handles{$fd} = $fh;
57             return $fd;
58             }
59              
60             sub get_handle
61             {
62             my $fd = shift;
63             $fd > 2 or die "Cannot operate on STD{IN|OUT|ERR}\n";
64             return $handles{$fd} || die "No handle on fileno $fd\n";
65             }
66             ];
67              
68             =head1 FUNCTIONS
69              
70             =cut
71              
72             =head2 open
73              
74             Open a new filehandle in the remote perl and return its FD number.
75              
76             my $fd = $ips->call( "open", $mode, @args )
77              
78             The filehandle is put into unbuffered mode, such that subsequent C
79             calls will send the data directly to the underlying operating system.
80              
81             The C<$mode> argument supports the full range of perl open modes, including
82             pipe opens with C<-|>. If using a pipe open, you can close the file handle
83             with C instead of C to obtain the child process exit status.
84              
85             In the case of pipe opens, L provides a selection
86             of functions that may be more convenient for executing a child program on the
87             remote perl, if interaction during its execution is not required.
88              
89             In the case of simple C / C / C or C / C /
90             C sequences, see also the L functions
91             C and C.
92              
93             =cut
94              
95             func open => q{
96             my ( $mode, @args ) = @_;
97             open( my $fh, $mode, @args ) or die "Cannot open() - $!\n";
98             $fh->autoflush;
99             store_handle( $fh );
100             };
101              
102             =head2 close
103              
104             Close a remote filehandle.
105              
106             $ips->call( "close", $fd )
107              
108             =cut
109              
110             func close => q{
111             our %handles;
112             undef $handles{shift()};
113             };
114              
115             =head2 pclose
116              
117             Close a remote filehandle which was part of a pipe-open, and return the child
118             process exit status.
119              
120             $exitstatus = $ips->call( "pclose", $fd )
121              
122             =cut
123              
124             func pclose => q{
125             our %handles;
126             my $fd = shift;
127             my $fh = get_handle( $fd );
128             undef $handles{$fd};
129             close $fh;
130             return $?;
131             };
132              
133             =head2 read
134              
135             Perform a single read call on a remote filehandle.
136              
137             my $data = $ips->call( "read", $fd, $length )
138              
139             Returns empty string on EOF.
140              
141             =cut
142              
143             func read => q{
144             my $fh = get_handle( shift );
145             defined( $fh->read( my $data, $_[0] ) ) or die "Cannot read() - $!\n";
146             return $data;
147             };
148              
149             =head2 getline
150              
151             Read a single line from the remote filehandle.
152              
153             my $line = $ips->call( "getline", $fd );
154              
155             Returns empty string on EOF.
156              
157             =cut
158              
159             func getline => q{
160             my $fh = get_handle( shift );
161             defined( my $line = $fh->getline() ) or die "Cannot getline() - $!\n";
162             return $line;
163             };
164              
165             =head2 write
166              
167             Perform a single write call on a remote filehandle.
168              
169             $ips->call( "write", $fd, $data )
170              
171             Note this is called C to match the system call, rather than C.
172              
173             =cut
174              
175             func write => q{
176             my $fh = get_handle( shift );
177             defined( $fh->print( $_[0] ) ) or die "Cannot write() - $!\n";
178             };
179              
180             =head2 tell
181              
182             Return the current file position on a remote filehandle.
183              
184             my $pos = $ips->call( "tell", $fd )
185              
186             =cut
187              
188             func tell => q{
189             my $fh = get_handle( shift );
190             return tell($fh);
191             };
192              
193             =head2 seek
194              
195             Seek to the given position in the remote filehandle and return the new
196             position.
197              
198             my $newpos = $ips->call( "seek", $fd, $pos, $whence )
199              
200             You may find it useful to import the C constants from the C
201             module.
202              
203             =cut
204              
205             func seek => q{
206             my $fh = get_handle( shift );
207             seek( $fh, $_[0], $_[1] ) or die "Cannot seek() - $!\n";
208             return tell($fh);
209             };
210              
211             =head2 truncate
212              
213             Truncates the file to the given length.
214              
215             $ips->call( "truncate", $fd, $len );
216              
217             =cut
218              
219             func truncate => q{
220             my $fh = get_handle( shift );
221             $fh->truncate( $_[0] ) or die "Cannot truncate() - $!\n";
222             };
223              
224             =head2 fstat
225              
226             Returns the status of the file (see L).
227              
228             my ( $dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime,
229             $mtime, $ctime, $blksize, $blocks ) = $ips->call( "fstat", $fd )
230              
231             =cut
232              
233             func fstat => q{
234             my $fh = get_handle( shift );
235             my @s = stat( $fh ) or die "Cannot stat() - $!\n";
236             @s;
237             };
238              
239             =head2 fchmod
240              
241             Change the permissions on the remote filehandle.
242              
243             $ips->call( "fchmod", $fd, 0755 )
244              
245             Note the order of arguments does not match perl's C.
246              
247             Only works on versions of remote F 5.8.8 and above.
248              
249             =cut
250              
251             func fchmod => q{
252             die "Perl too old for fchmod()" if $] < 5.008008;
253             my $fh = get_handle( shift );
254             chmod( $_[0], $fh ) or die "Cannot chmod() - $!\n";
255             };
256              
257             =head2 fchown
258              
259             Changes the owner (and group) of the remote filehandle.
260              
261             $ips->call( "fchown", $uid, $gid )
262              
263             Note the order of arguments does not match perl's C.
264              
265             Only works on versions of remote F 5.8.8 and above.
266              
267             =cut
268              
269             func fchown => q{
270             die "Perl too old for fchown()" if $] < 5.008008;
271             my $fh = get_handle( shift );
272             chown( $_[0], $_[1], $fh ) or die "Cannot chown() - $!\n";
273             };
274              
275             =head1 AUTHOR
276              
277             Paul Evans
278              
279             =cut
280              
281             0x55AA;