root/lang/perl/Net-FTP-Stepstone/trunk/lib/Net/FTP/Stepstone.pm @ 7839

Revision 7839, 5.0 kB (checked in by lopnor, 5 years ago)

lang/perl/Net-FTP-Stepstone: get rid of garbages from ls

Line 
1package Net::FTP::Stepstone;
2
3use strict;
4use strict;
5use base qw(Class::Accessor::Fast);
6use File::stat ();
7use File::Basename;
8use Time::Piece;
9
10our $VERSION = '0.02';
11__PACKAGE__->mk_accessors(qw(
12    cwd
13    lcwd
14    stepstone_addr
15    stepstone_user
16    ftp_addr
17    ftp_user
18    ftp_pass
19    ftp_port
20));
21
22sub new {
23    my $class = shift;
24    my $self = $class->SUPER::new(@_);
25    $self->cwd('.') unless $self->cwd;
26    $self->ftp_port(21) unless $self->ftp_port;
27    return $self;
28}
29
30sub ls {
31    my $self = shift;
32    my $arg = shift || '';
33    my @lines = $self->_ftp_command("ls $arg");
34    my @items = ();
35    for (@lines) {
36        my $name = (split(' ', $_))[8] or next;
37        $name =~ m{^\.{1,2}$} and next;
38        push @items, $name;
39    }
40    return @items;
41}
42
43sub stat {
44    my $self = shift;
45    my $arg = shift or return;
46    $arg =~ s{/$}{};
47    my $dir = dirname($arg);
48    my $base = basename($arg);
49    my @lines = $self->_ftp_command("ls $dir");
50    my $stob;
51    for (@lines) {
52        (split(' ', $_))[8] eq $base or next;
53        $stob = $self->_stat($_);
54    }
55    return $stob;
56}
57
58sub pwd {
59    my $self = shift;
60    if ($self->cwd eq '.') {
61        $self->_ftp_command('');
62    }
63    return $self->cwd;
64}
65
66sub lcd {
67    my $self = shift;
68    my $arg = shift;
69    $self->_ftp_command("lcd $arg");
70    $self->lcwd($arg);
71}
72
73for my $command (qw(cd get mget)) {
74    no strict 'refs';
75    *$command = sub {
76        my $self = shift;
77        my $arg = join ' ', @_;
78        my $res = $self->_ftp_command("$command $arg");
79        return $res unless $res =~ /^2/;
80        return;
81    };
82}
83
84sub _ftp_command {
85    my $self = shift;
86    my $command = shift || '';
87    $command = "lcd $self->{lcwd}\n".$command if $self->lcwd;
88    my $ftp_command = <<EOF;
89open $self->{ftp_addr} $self->{ftp_port}
90user $self->{ftp_user} $self->{ftp_pass}
91prompt
92type binary
93cd $self->{cwd}
94$command
95pwd
96close
97quit
98EOF
99    my @all = ` echo "$ftp_command" | ssh -l $self->{stepstone_user} $self->{stepstone_addr} ftp -n 2>/dev/null`;
100    my @lines = grep {$_ !~ m/not understood|Interactive mode off.|Local directory now/} @all;
101    if (my $last_line = $lines[-1]) {
102        my ($code, $cwd) = split '"', $last_line;
103        if ($code =~ /257/) {
104            $self->cwd($cwd);
105        } else {
106            return $last_line;
107        }
108    }
109    if (scalar @lines > 1) {
110        return @lines[0..($#lines -1)];
111    }
112    return undef;
113}
114
115sub _stat {
116    my $self = shift;
117    my $line = shift;
118    my ($mode, $nlink, $user, $group, $size, $month, $date, $time_or_year, $name) = split (" ", $line);
119    my ($time, $year);
120    if ($time_or_year =~ /:/) {
121        $time = $time_or_year;
122        $year = Time::Piece->strptime($month, "%b")->mon > localtime->mon ?
123            localtime->year - 1 : localtime->year;
124    } else {
125        $time = '00:00';
126        $year = $time_or_year;
127    }
128    my $mtime = Time::Piece->strptime(join(' ', $year, $month, $date, $time),"%Y %b %d %H:%M")->epoch;
129    my $uid = $self->_getent_passwd($user);
130    my $gid = $self->_getent_group($group);
131    my $stob = File::stat::populate(
132        0,                      # dev
133        0,                      # ino
134        $self->_mode($mode),    # mode
135        $nlink + 0,             # nlink
136        $uid + 0,               # uid
137        $gid + 0,               # gid
138        0,                      # rdev
139        $size + 0,              # size
140        0,                      # atime
141        $mtime + 0,             # mtime
142        0,                      # ctime
143        1,                      # blksize
144        $size + 0,              # blocks
145    );
146    return $stob;
147}
148
149for my $db (qw(group passwd)) {
150    no strict 'refs';
151    my $command = "_getent_$db";
152    *$command = sub {
153        my $self = shift;
154        my $name = shift;
155        my $val = `getent $db $name | cut -d: -f3`;
156        chomp $val;
157        $val = 99 unless length $val;
158        return $val;
159    }
160}
161
162sub _mode {
163    my $self = shift;
164    my $mode = shift;
165    my $val = 0;
166    my ($t,$u,$g,$o) = ($mode =~ /^(.)(...)(...)(...)$/);
167
168    for ($t){
169        $val |= 0010000 if /p/;
170        $val |= 0020000 if /c/;
171        $val |= 0040000 if /d/;
172        $val |= 0060000 if /b/;
173        $val |= 0100000 if /-/;
174        $val |= 0120000 if /l/;
175        $val |= 0140000 if /s/;
176    }
177
178    for ($u){
179        $val |= 0400 if /r/;
180        $val |= 0200 if /w/;
181        $val |= 0100 if /[xs]/;
182        $val |= 04000 if /[sS]/;
183    }
184
185    for ($g){
186        $val |= 0040 if /r/;
187        $val |= 0020 if /w/;
188        $val |= 0010 if /[xs]/;
189        $val |= 02000 if /[sS]/;
190    }
191
192    for ($o){
193        $val |= 0004 if /r/;
194        $val |= 0002 if /w/;
195        $val |= 0001 if /[xt]/;
196        $val |= 01000 if /[Tt]/;
197    }
198
199    return $val;
200}
201
202
2031;
204__END__
205
206=head1 NAME
207
208Net::FTP::Stepstone -
209
210=head1 SYNOPSIS
211
212  use Net::FTP::Stepstone;
213
214=head1 DESCRIPTION
215
216Net::FTP::Stepstone is
217
218=head1 AUTHOR
219
220Author E<lt>author@galaxyE<gt>
221
222This library is free software; you can redistribute it and/or modify
223it under the same terms as Perl itself.
224
225=head1 SEE ALSO
226
227L<>
228
229=cut
Note: See TracBrowser for help on using the browser.