File Coverage

blib/lib/AFS/Command/FS.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             #
2             # $Id$
3             #
4             # (c) 2003-2004 Morgan Stanley and Co.
5             # See ..../src/LICENSE for terms of distribution.
6             #
7              
8             package AFS::Command::FS;
9              
10             require 5.6.0;
11              
12 1     1   1103 use strict;
  1         2  
  1         32  
13 1     1   5 use English;
  1         2  
  1         6  
14              
15 1     1   1124 use AFS::Command::Base;
  0            
  0            
16             use AFS::Object;
17             use AFS::Object::CacheManager;
18             use AFS::Object::Path;
19             use AFS::Object::Cell;
20             use AFS::Object::Server;
21             use AFS::Object::ACL;
22              
23             our @ISA = qw(AFS::Command::Base);
24             our $VERSION = '1.99';
25              
26             sub checkservers {
27              
28             my $self = shift;
29             my (%args) = @_;
30              
31             my $result = AFS::Object::CacheManager->new();
32              
33             $self->{operation} = "checkservers";
34              
35             return unless $self->_parse_arguments(%args);
36              
37             return unless $self->_save_stderr();
38              
39             my $errors = 0;
40              
41             $errors++ unless $self->_exec_cmds();
42              
43             my @servers = ();
44              
45             while ( defined($_ = $self->{handle}->getline()) ) {
46              
47             chomp;
48              
49             if ( /The current down server probe interval is (\d+) secs/ ) {
50             $result->_setAttribute( interval => $1 );
51             }
52              
53             if ( /These servers are still down:/ ) {
54             while ( defined($_ = $self->{handle}->getline()) ) {
55             s/^\s+//g;
56             s/\s+$//g;
57             push(@servers,$_);
58             }
59             }
60             }
61              
62             $result->_setAttribute( servers => \@servers );
63              
64             $errors++ unless $self->_reap_cmds();
65             $errors++ unless $self->_restore_stderr();
66              
67             return if $errors;
68             return $result;
69              
70             }
71              
72             sub diskfree {
73             my $self = shift;
74             return $self->_paths_method('diskfree',@_);
75             }
76              
77             sub examine {
78             my $self = shift;
79             return $self->_paths_method('examine',@_);
80             }
81              
82             sub listquota {
83             my $self = shift;
84             return $self->_paths_method('listquota',@_);
85             }
86              
87             sub quota {
88             my $self = shift;
89             return $self->_paths_method('quota',@_);
90             }
91              
92             sub storebehind {
93             my $self = shift;
94             return $self->_paths_method('storebehind',@_);
95             }
96              
97             sub whereis {
98             my $self = shift;
99             return $self->_paths_method('whereis',@_);
100             }
101              
102             sub whichcell {
103             my $self = shift;
104             return $self->_paths_method('whichcell',@_);
105             }
106              
107             sub listacl {
108             my $self = shift;
109             return $self->_paths_method('listacl',@_);
110             }
111              
112             sub _paths_method {
113              
114             my $self = shift;
115             my $operation = shift;
116             my (%args) = @_;
117              
118             my $result = AFS::Object::CacheManager->new();
119              
120             $self->{operation} = $operation;
121              
122             my $pathkey = $operation eq 'storebehind' ? 'files' : 'path';
123              
124             return unless $self->_parse_arguments(%args);
125              
126             my $errors = 0;
127              
128             $errors++ unless $self->_exec_cmds( stderr => 'stdout' );
129              
130             my @paths = ref $args{$pathkey} eq 'ARRAY' ? @{$args{$pathkey}} : ($args{$pathkey});
131             my %paths = map { $_ => 1 } @paths;
132              
133             my $default = undef; # Used by storebehind
134              
135             while ( defined($_ = $self->{handle}->getline()) ) {
136              
137             next if /^Volume Name/;
138              
139             my $path = AFS::Object::Path->new();
140              
141             if ( /fs: Invalid argument; it is possible that (.*) is not in AFS./ ||
142             /fs: no such cell as \'(.*)\'/ ||
143             /fs: File \'(.*)\' doesn\'t exist/ ||
144             /fs: You don\'t have the required access rights on \'(.*)\'/ ) {
145              
146             $path->_setAttribute
147             (
148             path => $1,
149             error => $_,
150             );
151              
152             delete $paths{$1};
153             @paths = grep($_ ne $1,@paths);
154              
155             } else {
156              
157             if ( $operation eq 'listacl' ) {
158              
159             if ( /^Access list for (.*) is/ ) {
160              
161             $path->_setAttribute( path => $1 );
162             delete $paths{$1};
163              
164             my $normal = AFS::Object::ACL->new();
165             my $negative = AFS::Object::ACL->new();
166              
167             my $type = 0;
168              
169             while ( defined($_ = $self->{handle}->getline()) ) {
170              
171             s/^\s+//g;
172             s/\s+$//g;
173             last if /^\s*$/;
174              
175             $type = 1, next if /^Normal rights:/;
176             $type = -1, next if /^Negative rights:/;
177              
178             my ($principal,$rights) = split;
179              
180             if ( $type == 1 ) {
181             $normal->_addEntry( $principal => $rights );
182             } elsif ( $type == -1 ) {
183             $negative->_addEntry( $principal => $rights );
184             }
185              
186             }
187              
188             $path->_setACLNormal($normal);
189             $path->_setACLNegative($negative);
190              
191             }
192              
193             }
194              
195             if ( $operation eq 'whichcell' ) {
196              
197             if ( /^File (\S+) lives in cell \'([^\']+)\'/ ) {
198              
199             $path->_setAttribute
200             (
201             path => $1,
202             cell => $2,
203             );
204             delete $paths{$1};
205              
206             }
207              
208             }
209              
210             if ( $operation eq 'whereis' ) {
211              
212             if ( /^File (.*) is on hosts? (.*)$/ ) {
213              
214             $path->_setAttribute
215             (
216             path => $1,
217             hosts => [split(/\s+/,$2)],
218             );
219             delete $paths{$1};
220              
221             }
222              
223             }
224              
225             if ( $operation eq 'storebehind' ) {
226              
227             if ( /Default store asynchrony is (\d+) kbytes/ ) {
228              
229             $default = $1;
230             next;
231              
232             } elsif ( /Will store (.*?) according to default./ ) {
233              
234             $path->_setAttribute
235             (
236             path => $1,
237             asynchrony => 'default',
238             );
239              
240             delete $paths{$1};
241             @paths = grep($_ ne $1,@paths);
242              
243             } elsif ( /Will store up to (\d+) kbytes of (.*?) asynchronously/ ) {
244              
245             $path->_setAttribute
246             (
247             path => $2,
248             asynchrony => $1,
249             );
250              
251             delete $paths{$2};
252             @paths = grep($_ ne $2,@paths);
253              
254             }
255              
256             }
257              
258             if ( $operation eq 'quota' ) {
259              
260             if ( /^\s*(\d{1,2})%/ ) {
261              
262             $path->_setAttribute
263             (
264             path => $paths[0],
265             percent => $1,
266             );
267             delete $paths{$paths[0]};
268             shift @paths;
269              
270             }
271              
272             }
273              
274             if ( $operation eq 'listquota' ) {
275              
276             #
277             # This is a bit lame. We want to be lazy and split on white
278             # space, so we get rid of this one annoying instance.
279             #
280             s/no limit/nolimit/g;
281              
282             my ($volname,$quota,$used,$percent,$partition) = split;
283              
284             $quota = 0 if $quota eq "nolimit";
285             $percent =~ s/\D//g; # want numeric result
286             $partition =~ s/\D//g; # want numeric result
287              
288             $path->_setAttribute
289             (
290             path => $paths[0],
291             volname => $volname,
292             quota => $quota,
293             used => $used,
294             percent => $percent,
295             partition => $partition,
296             );
297             delete $paths{$paths[0]};
298             shift @paths;
299              
300             }
301              
302             if ( $operation eq 'diskfree' ) {
303              
304             my ($volname,$total,$used,$avail,$percent) = split;
305             $percent =~ s/%//g; # Don't need it -- want numeric result
306              
307             $path->_setAttribute
308             (
309             path => $paths[0],
310             volname => $volname,
311             total => $total,
312             used => $used,
313             avail => $avail,
314             percent => $percent,
315             );
316             delete $paths{$paths[0]};
317             shift @paths;
318              
319             }
320              
321             if ( $operation eq 'examine' ) {
322              
323             if ( /Volume status for vid = (\d+) named (\S+)/ ) {
324              
325             $path->_setAttribute
326             (
327             path => $paths[0],
328             id => $1,
329             volname => $2,
330             );
331              
332             #
333             # Looking at Transarc's code, we can safely assume we'll
334             # get this output in the order shown. Note we ignore the
335             # "Message of the day" and "Offline reason" output for
336             # now. Read until we hit a blank line.
337             #
338             while ( defined($_ = $self->{handle}->getline()) ) {
339              
340             last if /^\s*$/;
341              
342             if ( /Current disk quota is (\d+|unlimited)/ ) {
343             $path->_setAttribute
344             (
345             quota => $1 eq "unlimited" ? 0 : $1,
346             );
347             }
348              
349             if ( /Current blocks used are (\d+)/ ) {
350             $path->_setAttribute( used => $1 );
351             }
352              
353             if ( /The partition has (\d+) blocks available out of (\d+)/ ) {
354             $path->_setAttribute
355             (
356             avail => $1,
357             total => $2,
358             );
359             }
360             }
361              
362             delete $paths{$paths[0]};
363             shift @paths;
364              
365             }
366              
367             }
368              
369             }
370              
371             $result->_addPath($path);
372              
373             }
374              
375             if ( $operation eq 'storebehind' ) {
376              
377             $result->_setAttribute( asynchrony => $default );
378              
379             #
380             # This is ugly, but we get the default last, and it would be nice
381             # to put this value into the Path objects as well, rather than the
382             # string 'default'.
383             #
384             foreach my $path ( $result->getPaths() ) {
385             if ( defined($path->asynchrony()) && $path->asynchrony() eq 'default' ) {
386             $path->_setAttribute( asynchrony => $default );
387             }
388             }
389             }
390              
391             foreach my $pathname ( keys %paths ) {
392              
393             my $path = AFS::Object::Path->new
394             (
395             path => $pathname,
396             error => "Unable to determine results",
397             );
398              
399             $result->_addPath($path);
400              
401             }
402              
403             $errors++ unless $self->_reap_cmds( allowstatus => 1 );
404              
405             return if $errors;
406             return $result;
407              
408             }
409              
410             sub exportafs {
411              
412             my $self = shift;
413             my (%args) = @_;
414              
415             my $result = AFS::Object->new();
416              
417             $self->{operation} = "exportafs";
418              
419             return unless $self->_parse_arguments(%args);
420              
421             return unless $self->_save_stderr();
422              
423             my $errors = 0;
424              
425             $errors++ unless $self->_exec_cmds();
426              
427             while ( defined($_ = $self->{handle}->getline()) ) {
428              
429             /translator is (currently )?enabled/ && do {
430             $result->_setAttribute( enabled => 1 );
431             };
432              
433             /translator is disabled/ && do {
434             $result->_setAttribute( enabled => 0 );
435             };
436              
437             /convert owner mode bits/ && do {
438             $result->_setAttribute( convert => 1 );
439             };
440              
441             /strict unix/ && do {
442             $result->_setAttribute( convert => 0 );
443             };
444              
445             /strict \'?passwd sync\'?/ && do {
446             $result->_setAttribute( uidcheck => 1 );
447             };
448              
449             /no \'?passwd sync\'?/ && do {
450             $result->_setAttribute( uidcheck => 0 );
451             };
452              
453             /allow mounts/i && do {
454             $result->_setAttribute( submounts => 1 );
455             };
456              
457             /Only mounts/i && do {
458             $result->_setAttribute( submounts => 0 );
459             };
460              
461             }
462              
463             $errors++ unless $self->_reap_cmds();
464             $errors++ unless $self->_restore_stderr();
465              
466             return if $errors;
467             return $result;
468              
469             }
470              
471             sub getcacheparms {
472              
473             my $self = shift;
474             my (%args) = @_;
475              
476             my $result = AFS::Object::CacheManager->new();
477              
478             $self->{operation} = "getcacheparms";
479              
480             return unless $self->_parse_arguments(%args);
481              
482             return unless $self->_save_stderr();
483              
484             my $errors = 0;
485              
486             $errors++ unless $self->_exec_cmds();
487              
488             while ( defined($_ = $self->{handle}->getline()) ) {
489             if ( /using (\d+) of the cache.s available (\d+) 1K/ ) {
490             $result->_setAttribute
491             (
492             used => $1,
493             avail => $2,
494             );
495             }
496             }
497              
498             $errors++ unless $self->_reap_cmds();
499             $errors++ unless $self->_restore_stderr();
500              
501             return if $errors;
502             return $result;
503              
504             }
505              
506             sub getcellstatus {
507              
508             my $self = shift;
509             my (%args) = @_;
510              
511             my $result = AFS::Object::CacheManager->new();
512              
513             $self->{operation} = "getcellstatus";
514              
515             return unless $self->_parse_arguments(%args);
516              
517             return unless $self->_save_stderr();
518              
519             my $errors = 0;
520              
521             $errors++ unless $self->_exec_cmds();
522              
523             while ( defined($_ = $self->{handle}->getline()) ) {
524              
525             if ( /Cell (\S+) status: (no )?setuid allowed/ ) {
526             my $cell = AFS::Object::Cell->new
527             (
528             cell => $1,
529             status => $2 ? 0 : 1,
530             );
531             $result->_addCell($cell);
532             }
533              
534             }
535              
536             $errors++ unless $self->_reap_cmds();
537             $errors++ unless $self->_restore_stderr();
538              
539             return if $errors;
540             return $result;
541              
542             }
543              
544             sub getclientaddrs {
545              
546             my $self = shift;
547             my (%args) = @_;
548              
549             my $result = AFS::Object::CacheManager->new();
550              
551             $self->{operation} = "getclientaddrs";
552              
553             return unless $self->_parse_arguments(%args);
554              
555             return unless $self->_save_stderr();
556              
557             my $errors = 0;
558              
559             $errors++ unless $self->_exec_cmds();
560              
561             my @addresses = ();
562              
563             while ( defined($_ = $self->{handle}->getline()) ) {
564             chomp;
565             s/^\s+//;
566             s/\s+$//;
567             push(@addresses,$_);
568             }
569              
570             $result->_setAttribute( addresses => \@addresses );
571              
572             $errors++ unless $self->_reap_cmds();
573             $errors++ unless $self->_restore_stderr();
574              
575             return if $errors;
576             return $result;
577              
578             }
579              
580             sub getcrypt {
581              
582             my $self = shift;
583             my (%args) = @_;
584              
585             my $result = AFS::Object::CacheManager->new();
586              
587             $self->{operation} = "getcrypt";
588              
589             return unless $self->_parse_arguments(%args);
590              
591             return unless $self->_save_stderr();
592              
593             my $errors = 0;
594              
595             $errors++ unless $self->_exec_cmds();
596              
597             while ( defined($_ = $self->{handle}->getline()) ) {
598              
599             if ( /Security level is currently (crypt|clear)/ ) {
600             $result->_setAttribute( crypt => ($1 eq 'crypt' ? 1 : 0) );
601             }
602              
603             }
604              
605             $errors++ unless $self->_reap_cmds();
606             $errors++ unless $self->_restore_stderr();
607              
608             return if $errors;
609             return $result;
610              
611             }
612              
613             sub getserverprefs {
614              
615             my $self = shift;
616             my (%args) = @_;
617              
618             my $result = AFS::Object::CacheManager->new();
619              
620             $self->{operation} = "getserverprefs";
621              
622             return unless $self->_parse_arguments(%args);
623              
624             return unless $self->_save_stderr();
625              
626             my $errors = 0;
627              
628             $errors++ unless $self->_exec_cmds();
629              
630             while ( defined($_ = $self->{handle}->getline()) ) {
631              
632             s/^\s+//g;
633             s/\s+$//g;
634              
635             my ($name,$preference) = split;
636              
637             my $server = AFS::Object::Server->new
638             (
639             server => $name,
640             preference => $preference,
641             );
642              
643             $result->_addServer($server);
644              
645             }
646              
647             $errors++ unless $self->_reap_cmds();
648             $errors++ unless $self->_restore_stderr();
649              
650             return if $errors;
651             return $result;
652              
653             }
654              
655             sub listaliases {
656              
657             my $self = shift;
658             my (%args) = @_;
659              
660             my $result = AFS::Object::CacheManager->new();
661              
662             $self->{operation} = "listaliases";
663              
664             return unless $self->_parse_arguments(%args);
665              
666             return unless $self->_save_stderr();
667              
668             my $errors = 0;
669              
670             $errors++ unless $self->_exec_cmds();
671              
672             while ( defined($_ = $self->{handle}->getline()) ) {
673              
674             if ( /Alias (.*) for cell (.*)/ ) {
675             my $cell = AFS::Object::Cell->new
676             (
677             cell => $2,
678             alias => $1,
679             );
680             $result->_addCell($cell);
681             }
682              
683             }
684              
685             $errors++ unless $self->_reap_cmds();
686             $errors++ unless $self->_restore_stderr();
687              
688             return if $errors;
689             return $result;
690              
691             }
692              
693             sub listcells {
694              
695             my $self = shift;
696             my (%args) = @_;
697              
698             my $result = AFS::Object::CacheManager->new();
699              
700             $self->{operation} = "listcells";
701              
702             return unless $self->_parse_arguments(%args);
703              
704             return unless $self->_save_stderr();
705              
706             my $errors = 0;
707              
708             $errors++ unless $self->_exec_cmds();
709              
710             while ( defined($_ = $self->{handle}->getline()) ) {
711              
712             if ( /^Cell (\S+) on hosts (.*)\.$/ ) {
713             my $cell = AFS::Object::Cell->new
714             (
715             cell => $1,
716             servers => [split(/\s+/,$2)],
717             );
718             $result->_addCell($cell);
719             }
720              
721             }
722              
723             $errors++ unless $self->_reap_cmds();
724             $errors++ unless $self->_restore_stderr();
725              
726             return if $errors;
727             return $result;
728              
729             }
730              
731             sub lsmount {
732              
733             my $self = shift;
734             my (%args) = @_;
735              
736             my $result = AFS::Object::CacheManager->new();
737              
738             $self->{operation} = "lsmount";
739              
740             return unless $self->_parse_arguments(%args);
741              
742             my $errors = 0;
743              
744             $errors++ unless $self->_exec_cmds( stderr => 'stdout' );
745              
746             my @dirs = ref $args{dir} eq 'ARRAY' ? @{$args{dir}} : ($args{dir});
747             my %dirs = map { $_ => 1 } @dirs;
748              
749             while ( defined($_ = $self->{handle}->getline()) ) {
750              
751             my $current = shift @dirs;
752             delete $dirs{$current};
753              
754             my $path = AFS::Object::Path->new( path => $current );
755              
756             if ( /fs: Can.t read target name/ ) {
757             $path->_setAttribute( error => $_ );
758             } elsif ( /fs: File '.*' doesn't exist/ ) {
759             $path->_setAttribute( error => $_ );
760             } elsif ( /fs: you may not use \'.\'/ ) {
761             $_ .= $self->{handle}->getline();
762             $path->_setAttribute( error => $_ );
763             } elsif ( /\'(.*?)\' is not a mount point/ ) {
764             $path->_setAttribute( error => $_ );
765             } elsif ( /^\'(.*?)\'.*?\'(.*?)\'$/ ) {
766              
767             my ($dir,$mount) = ($1,$2);
768              
769             $path->_setAttribute( symlink => 1 ) if /symbolic link/;
770             $path->_setAttribute( readwrite => 1 ) if $mount =~ /^%/;
771             $mount =~ s/^(%|\#)//;
772              
773             my ($volname,$cell) = reverse split(/:/,$mount);
774              
775             $path->_setAttribute( volname => $volname );
776             $path->_setAttribute( cell => $cell) if $cell;
777              
778             } else {
779              
780             $self->_Carp("fs lsmount: Unrecognized output: '$_'");
781             $errors++;
782             next;
783              
784             }
785              
786             $result->_addPath($path);
787              
788             }
789              
790             foreach my $dir ( keys %dirs ) {
791             my $path = AFS::Object::Path->new
792             (
793             path => $dir,
794             error => "Unable to determine results",
795             );
796             $result->_addPath($path);
797             }
798              
799             $errors++ unless $self->_reap_cmds( allowstatus => 1 );
800              
801             return if $errors;
802             return $result;
803              
804             }
805              
806             #
807             # This is deprecated in newer versions of OpenAFS
808             #
809             sub monitor {
810             my $self = shift;
811             $self->_Carp("fs monitor: This operation is deprecated and no longer supported");
812             return;
813             }
814              
815             sub sysname {
816              
817             my $self = shift;
818             my (%args) = @_;
819              
820             my $result = AFS::Object::CacheManager->new();
821              
822             $self->{operation} = "sysname";
823              
824             return unless $self->_parse_arguments(%args);
825              
826             return unless $self->_save_stderr();
827              
828             my $errors = 0;
829              
830             $errors++ unless $self->_exec_cmds();
831              
832             my @sysname = ();
833              
834             while ( defined($_ = $self->{handle}->getline()) ) {
835              
836             if ( /Current sysname is \'?([^\']+)\'?/ ) {
837             $result->_setAttribute( sysname => $1 );
838             } elsif ( s/Current sysname list is // ) {
839             while ( s/\'([^\']+)\'\s*// ) {
840             push(@sysname,$1);
841             }
842             $result->_setAttribute( sysnames => \@sysname );
843             $result->_setAttribute( sysname => $sysname[0] );
844             }
845              
846             }
847              
848             $errors++ unless $self->_reap_cmds();
849             $errors++ unless $self->_restore_stderr();
850              
851             return if $errors;
852             return $result;
853              
854             }
855              
856             sub wscell {
857              
858             my $self = shift;
859             my (%args) = @_;
860              
861             my $result = AFS::Object::CacheManager->new();
862              
863             $self->{operation} = "wscell";
864              
865             return unless $self->_parse_arguments(%args);
866              
867             return unless $self->_save_stderr();
868              
869             my $errors = 0;
870              
871             $errors++ unless $self->_exec_cmds();
872              
873             while ( defined($_ = $self->{handle}->getline()) ) {
874             next unless /belongs to cell\s+\'(.*)\'/;
875             $result->_setAttribute( cell => $1 );
876             }
877              
878             $errors++ unless $self->_reap_cmds();
879             $errors++ unless $self->_restore_stderr();
880              
881             return if $errors;
882             return $result;
883              
884             }
885              
886             1;
887