2 # Copyright (c) 1996, 2001 Carnegie Mellon University
5 # See CMU_copyright.ph for use and distribution information
7 #: * fs.pm - Wrappers around the FS commands (fileserver/cache manager)
8 #: * This module provides wrappers around the various FS commands, which
9 #: * perform fileserver and cache manager control operations. Right now,
10 #: * these are nothing more than wrappers around 'fs'; someday, we might
11 #: * talk to the cache manager directly, but not anytime soon.
15 use OpenAFS::CMU_copyright;
16 use OpenAFS::util qw(:DEFAULT :afs_internal);
23 @EXPORT = qw(&AFS_fs_getacl &AFS_fs_setacl
24 &AFS_fs_cleanacl &AFS_fs_getquota
25 &AFS_fs_setquota &AFS_fs_whereis
26 &AFS_fs_examine &AFS_fs_setvol
27 &AFS_fs_getmount &AFS_fs_mkmount
28 &AFS_fs_rmmount &AFS_fs_checkvolumes
29 &AFS_fs_flush &AFS_fs_flushmount
30 &AFS_fs_flushvolume &AFS_fs_messages
31 &AFS_fs_newcell &AFS_fs_rxstatpeer
32 &AFS_fs_rxstatproc &AFS_fs_setcachesize
33 &AFS_fs_setcell &AFS_fs_setcrypt
34 &AFS_fs_setclientaddrs &AFS_fs_copyacl
35 &AFS_fs_storebehind &AFS_fs_setserverprefs
36 &AFS_fs_checkservers &AFS_fs_checkservers_interval
37 &AFS_fs_exportafs &AFS_fs_getcacheparms
38 &AFS_fs_getcellstatus &AFS_fs_getclientaddrs
39 &AFS_fs_getcrypt &AFS_fs_getserverprefs
40 &AFS_fs_listcells &AFS_fs_setmonitor
41 &AFS_fs_getmonitor &AFS_fs_getsysname
42 &AFS_fs_setsysname &AFS_fs_whichcell
45 #: ACL-management functions:
46 #: AFS access control lists are represented as a Perl list (or usually, a
47 #: reference to such a list). Each element in such a list corresponds to
48 #: a single access control entry, and is a reference to a 2-element list
49 #: consisting of a PTS entity (name or ID), and a set of rights. The
50 #: rights are expressed in the usual publically-visible AFS notation, as
51 #: a string of characters drawn from the class [rlidwkaABCDEFGH]. No
52 #: rights are denoted by the empty string; such an ACE will never returned
53 #: by this library, but may be used as an argument to remove a particular
54 #: ACE from a directory's ACL.
56 #: One might be inclined to ask why we chose this representation, instead of
57 #: using an associative array, as might seem obvious. The answer is that
58 #: doing so would have implied a nonambiguity that isn't there. Suppose you
59 #: have an ACL %x, and want to know if there is an entry for user $U on that
60 #: list. You might think you could do this by looking at $x{$U}. The
61 #: problem here is that two values for $U (one numeric and one not) refer to
62 #: the same PTS entity, even though they would reference different elements
63 #: in such an ACL. So, we instead chose a representation that wasn't a hash,
64 #: so people wouldn't try to do hash-like things to it. If you really want
65 #: to be able to do hash-like operations, you should turn the list-form ACL
66 #: into a hash table, and be sure to do name-to-number translation on all the
69 #: AFS_fs_getacl($path)
70 #: Get the ACL on a specified path.
71 #: On success, return a list of two references to ACLs; the first is the
72 #: positive ACL for the specified path, and the second is the negative ACL.
74 $AFS_Help{fs_getacl} = '$path => (\@posacl, \@negacl)';
77 my(@args, @posacl, @negacl, $neg);
79 @args = ('listacl', '-path', $path);
80 &wrapper('fs', \@args,
82 [ '^(Normal|Negative) rights\:', sub {
83 $neg = ($_[0] eq 'Negative');
85 [ '^ (.*) (\S+)$', sub { #',{
95 #: AFS_fs_setacl(\@paths, \@posacl, \@negacl, [$clear])
96 #: Set the ACL on a specified path. Like the 'fs setacl' command, this
97 #: function normally only changes ACEs that are mentioned in one of the two
98 #: argument lists. If a given ACE already exists, it is changed; if not, it
99 #: is added. To delete a single ACE, specify the word 'none' or the empty
100 #: string in the rights field. ACEs that already exist but are not mentioned
101 #: are left untouched, unless $clear is specified. In that case, all
102 #: existing ACE's (both positive and negative) are deleted.
103 $AFS_Help{fs_setacl} = '\@paths, \@posacl, \@negacl, [$clear] => Success?';
105 my($paths, $posacl, $negacl, $clear) = @_;
106 my($ace, $U, $access);
109 @args = ('setacl', '-dir', @$paths);
110 push(@args, '-clear') if ($clear);
112 foreach $e (@$posacl) {
114 $access = 'none' if ($access eq '');
115 push(@args, $U, $access);
117 &wrapper('fs', \@args);
120 @args = ('setacl', '-dir', @$paths, '-negative');
121 push(@args, '-clear') if ($clear && !@$posacl);
123 foreach $e (@$negacl) {
125 $access = 'none' if ($access eq '');
126 push(@args, $U, $access);
128 &wrapper('fs', \@args);
130 if ($clear && !@$posacl && !@$negacl) {
131 @args = ('setacl', '-dir', @$paths,
132 '-acl', 'system:anyuser', 'none', '-clear');
133 &wrapper('fs', \@args);
138 #: AFS_fs_cleanacl(\@paths)
139 #: Clean the ACL on the specified path, removing any ACEs which refer to PTS
140 #: entities that no longer exist. All the work is done by 'fs'.
142 $AFS_Help{'fs_cleanacl'} = '\@paths => Success?';
143 sub AFS_fs_cleanacl {
147 @args = ('cleanacl', '-path', @$paths);
148 &wrapper('fs', \@args);
152 #: AFS_fs_getquota($path) [listquota]
153 #: Get the quota on the specified path.
154 #: On success, returns the quota.
156 $AFS_Help{'fs_getquota'} = '$path => $quota';
157 sub AFS_fs_getquota {
161 @args = ('listquota', '-path', $path);
162 &wrapper('fs', \@args,
163 [[ '^\S+\s+(\d+)\s+\d+\s+\d+\%', \$quota ]]);
167 #: AFS_fs_setquota($path, $quota) [setquota]
168 #: Set the quota on the specified path to $quota. If $quota is
169 #: given as 0, there will be no limit to the volume's size.
170 #: On success, return 1
172 $AFS_Help{'fs_setquota'} = '$path, $quota => Success?';
173 sub AFS_fs_setquota {
174 my($path, $quota) = @_;
177 @args = ('setquota', '-path', $path, '-max', $quota);
178 &wrapper('fs', \@args);
182 #: AFS_fs_whereis($path) [whereis, whichcell]
183 #: Locate the fileserver housing the specified path, and the cell in which it
185 #: On success, returns a list of 2 or more elements. The first element is the
186 #: name of the cell in which the volume is located. The remaining elements
187 #: the names of servers housing the volume; for a replicated volume, there may
188 #: (should) be more than one such server.
190 $AFS_Help{'fs_whereis'} = '$path => ($cell, @servers)';
193 my(@args, $cell, @servers);
195 @args = ('whichcell', '-path', $path);
196 &wrapper('fs', \@args,
197 [[ "lives in cell \'(.*)\'", \$cell ]]);
199 @args = ('whereis', '-path', $path);
200 &wrapper('fs', \@args,
201 [[ 'is on host(s?)\s*(.*)', sub {
202 @servers = split(' ', $_[1]);
207 #: AFS_fs_examine($path)
208 #: Get information about the volume containing the specified path.
209 #: On success, return an associative array containing some or all
210 #: of the following elements:
221 $AFS_Help{'fs_examine'} = '$path => %info';
226 @args = ('examine', '-path', $path);
227 %info = &wrapper('fs', \@args,
228 [[ 'vid = (\d+) named (\S+)', 'vol_id', 'vol_name' ],
229 [ 'disk quota is (\d+|unlimited)', 'quota_max' ],
230 [ 'blocks used are (\d+)', 'quota_used' ],
231 [ '(\d+) blocks available out of (\d+)',
232 'part_avail', 'part_size']]);
233 if ($info{'quota_max'} eq 'unlimited') {
234 $info{'quota_max'} = 0;
235 $info{'quota_pctused'} = 0;
237 $info{'quota_pctused'} = ($info{'quota_used'} / $info{'quota_max'}) * 100;
238 $info{'quota_pctused'} =~ s/\..*//;
240 $info{'part_used'} = $info{'part_size'} - $info{'part_avail'};
241 $info{'part_pctused'} = ($info{'part_used'} / $info{'part_size'}) * 100;
242 $info{'part_pctused'} =~ s/\..*//;
246 #: AFS_fs_setvol($path, [$maxquota], [$motd])
247 #: Set information about the volume containing the specified path.
248 #: On success, return 1.
249 $AFS_Help{'fs_setvol'} = '$path, [$maxquota], [$motd] => Success?';
251 my($path, $maxquota, $motd) = @_;
254 @args = ('setvol', '-path', $path);
255 push(@args, '-max', $maxquota) if ($maxquota || $maxquota eq '0');
256 push(@args, '-motd', $motd) if ($motd);
257 &wrapper('fs', \@args);
262 #: AFS_fs_getmount($path)
263 #: Get the contents of the specified AFS mount point.
264 #: On success, return the contents of the specified mount point.
265 #: If the specified path is not a mount point, return the empty string.
266 $AFS_Help{'fs_getmount'} = '$path => $vol';
267 sub AFS_fs_getmount {
271 @args = ('lsmount', '-dir', $path);
272 &wrapper('fs', \@args,
273 [[ "mount point for volume '(.+)'", \$vol ]]);
278 #: AFS_fs_mkmount($path, $vol, [$cell], [$rwmount], [$fast])
279 #: Create an AFS mount point at $path, leading to the volume $vol.
280 #: If $cell is specified, create a cellular mount point to that cell.
281 #: If $rwmount is specified and nonzero, create a read-write mount point.
282 #: If $fast is specified and nonzero, don't check to see if the volume exists.
283 #: On success, return 1.
284 $AFS_Help{'fs_mkmount'} = '$path, $vol, [$cell], [$rwmount], [$fast] => Success?';
286 my($path, $vol, $cell, $rwmount, $fast) = @_;
289 @args = ('mkmount', '-dir', $path, '-vol', $vol);
290 push(@args, '-cell', $cell) if ($cell);
291 push(@args, '-rw') if ($rwmount);
292 push(@args, '-fast') if ($fast);
293 &wrapper('fs', \@args);
297 #: AFS_fs_rmmount($path) [rmmount]
298 #: Remove an AFS mount point at $path
299 #: On success, return 1
300 $AFS_Help{'fs_rmmount'} = '$path => Success?';
305 @args = ('rmmount', '-dir', $path);
306 &wrapper('fs', \@args);
310 #: AFS_fs_checkvolumes()
311 #: Check/update volume ID cache
312 #: On success, return 1
313 $AFS_Help{'fs_checkvolumes'} = '=> Success?';
314 sub AFS_fs_checkvolumes {
317 @args = ('checkvolumes');
318 &wrapper('fs', \@args);
322 #: AFS_fs_flush(\@paths)
323 #: Flush files named by @paths from the cache
324 #: On success, return 1
325 $AFS_Help{'fs_flush'} = '\@paths => Success?';
331 push(@args, '-path', @$paths) if $paths;
332 &wrapper('fs', \@args);
336 #: AFS_fs_flushmount(\@paths)
337 #: Flush mount points named by @paths from the cache
338 #: On success, return 1
339 $AFS_Help{'fs_flushmount'} = '\@paths => Success?';
340 sub AFS_fs_flushmount {
344 @args = ('flushmount');
345 push(@args, '-path', @$paths) if $paths;
346 &wrapper('fs', \@args);
350 #: AFS_fs_flushvolume(\@paths)
351 #: Flush volumes containing @paths from the cache
352 #: On success, return 1
353 $AFS_Help{'fs_flushvolume'} = '\@paths => Success?';
354 sub AFS_fs_flushvolume {
358 @args = ('flushvolume');
359 push(@args, '-path', @$paths) if $paths;
360 &wrapper('fs', \@args);
364 #: AFS_fs_messages($mode)
365 #: Set cache manager message mode
366 #: Valid modes are 'user', 'console', 'all', 'none'
367 #: On success, return 1
368 $AFS_Help{'fs_messages'} = '$mode => Success?';
369 sub AFS_fs_messages {
373 @args = ('messages', '-show', $mode);
374 &wrapper('fs', \@args);
378 #: AFS_fs_newcell($cell, \@dbservers, [$linkedcell])
379 #: Add a new cell to the cache manager's list, or updating an existing cell
380 #: On success, return 1
381 $AFS_Help{'fs_newcell'} = '$cell, \@dbservers, [$linkedcell] => Success?';
383 my($cell, $dbservers, $linkedcell) = @_;
386 @args = ('newcell', '-name', $cell, '-servers', @$dbservers);
387 push(@args, '-linkedcell', $linkedcell) if $linkedcell;
388 &wrapper('fs', \@args);
392 #: AFS_fs_rxstatpeer($enable, [$clear])
393 #: Control per-peer Rx statistics:
394 #: - if $enable is 1, enable stats
395 #: - if $enable is 0, disable stats
396 #: - if $clear is 1, clear stats
397 #: On success, return 1
398 $AFS_Help{'fs_rxstatpeer'} = '$enable, [$clear] => Success?';
399 sub AFS_fs_rxstatpeer {
400 my($enable, $clear) = @_;
403 @args = ('rxstatpeer');
404 push(@args, '-enable') if $enable;
405 push(@args, '-disable') if defined($enable) && !$enable;
406 push(@args, '-clear') if $clear;
407 &wrapper('fs', \@args);
411 #: AFS_fs_rxstatproc($enable, [$clear])
412 #: Control per-process Rx statistics:
413 #: - if $enable is 1, enable stats
414 #: - if $enable is 0, disable stats
415 #: - if $clear is 1, clear stats
416 #: On success, return 1
417 $AFS_Help{'fs_rxstatproc'} = '$enable, [$clear] => Success?';
418 sub AFS_fs_rxstatproc {
419 my($enable, $clear) = @_;
422 @args = ('rxstatproc');
423 push(@args, '-enable') if $enable;
424 push(@args, '-disable') if defined($enable) && !$enable;
425 push(@args, '-clear') if $clear;
426 &wrapper('fs', \@args);
430 #: AFS_fs_setcachesize($size)
431 #: Set the cache size to $size K
432 #: On success, return 1
433 $AFS_Help{'fs_setcachesize'} = '$size => Success?';
434 sub AFS_fs_setcachesize {
438 @args = ('setcachesize', '-blocks', $size);
439 &wrapper('fs', \@args);
443 #: AFS_fs_setcell(\@cells, $suid)
444 #: Set cell control bits for @cells
445 #: - if $suid is 1, enable suid programs
446 #: - if $suid is 0, disable suid programs
447 #: On success, return 1
448 $AFS_Help{'fs_setcell'} = '\@cells, [$suid] => Success?';
450 my($cells, $suid) = @_;
453 @args = ('setcell', '-cell', @$cells);
454 push(@args, '-suid') if $suid;
455 push(@args, '-nosuid') if defined($suid) && !$suid;
456 &wrapper('fs', \@args);
460 #: AFS_fs_setcrypt($enable)
461 #: Control cache manager encryption
462 #: - if $enable is 1, enable encrypted connections
463 #: - if $enable is 0, disable encrypted connections
464 #: On success, return 1
465 $AFS_Help{'fs_setcrypt'} = '$enable => Success?';
466 sub AFS_fs_setcrypt {
470 @args = ('setcrypt', '-crypt', $enable ? 'on' : 'off');
471 &wrapper('fs', \@args);
475 #: AFS_fs_setclientaddrs(\@addrs)
476 #: Set client network interface addresses
477 #: On success, return 1
478 $AFS_Help{'fs_setclientaddrs'} = '\@addrs => Success?';
479 sub AFS_fs_setclientaddrs {
483 @args = ('setclientaddrs');
484 push(@args, '-address', @$addrs) if $addrs;
485 &wrapper('fs', \@args);
489 #: AFS_fs_copyacl($from, \@to, [$clear])
490 #: Copy the access control list on $from to each directory named in @to.
491 #: If $clear is specified and nonzero, the target ACL's are cleared first
492 #: On success, return 1
493 $AFS_Help{'fs_copyacl'} = '$from, \@to, [$clear] => Success?';
495 my($from, $to, $clear) = @_;
498 @args = ('copyacl', '-fromdir', $from, '-todir', @$to);
499 push(@args, '-clear') if $clear;
500 &wrapper('fs', \@args);
504 #: AFS_fs_storebehind(\@paths, [$size], [$def])
505 #: Set amount of date to store after file close
506 #: If $size is specified, the size for each file in @paths is set to $size.
507 #: If $default is specified, the default size is set to $default.
508 #: Returns the new or current default value, and a hash mapping filenames
509 #: to their storebehind sizes. A hash entry whose value is undef indicates
510 #: that the corresponding file will use the default size.
511 $AFS_Help{'fs_storebehind'} = '\@paths, [$size], [$def] => ($def, \%sizes)';
512 sub AFS_fs_storebehind {
513 my($paths, $size, $def) = @_;
514 my(@args, %sizes, $ndef);
516 @args = ('storebehind', '-verbose');
517 push(@args, '-kbytes', $size) if defined($size);
518 push(@args, '-files', @$paths) if $paths && @$paths;
519 push(@args, '-allfiles', $def) if defined($def);
520 &wrapper('fs', \@args, [
521 ['^Will store up to (\d+) kbytes of (.*) asynchronously',
522 sub { $sizes{$_[1]} = $_[0] }],
523 ['^Will store (.*) according to default',
524 sub { $sizes{$_[0]} = undef }],
525 ['^Default store asynchrony is (\d+) kbytes', \$ndef],
530 #: AFS_fs_setserverprefs(\%fsprefs, \%vlprefs)
531 #: Set fileserver and/or VLDB server preference ranks
532 #: Each of %fsprefs and %vlprefs maps server names to the rank to be
533 #: assigned to the specified servers.
534 #: On success, return 1.
535 $AFS_Help{'fs_setserverprefs'} = '\%fsprefs, \%vlprefs => Success?';
536 sub AFS_fs_setserverprefs {
537 my($fsprefs, $vlprefs) = @_;
540 @args = ('setserverprefs');
541 if ($fsprefs && %$fsprefs) {
542 push(@args, '-servers');
543 foreach $srv (keys %$fsprefs) {
544 push(@args, $srv, $$fsprefs{$srv});
547 if ($vlprefs && %$vlprefs) {
548 push(@args, '-vlservers');
549 foreach $srv (keys %$vlprefs) {
550 push(@args, $srv, $$vlprefs{$srv});
553 &wrapper('fs', \@args);
557 #: AFS_fs_checkservers([$fast], [$allcells], [$cell])
558 #: Check to see what fileservers are down
559 #: If $cell is specified, fileservers in the specified cell are checked
560 #: If $allcells is specified and nonzero, fileservers in all cells are checked
561 #: If $fast is specified and nonzero, don't probe servers
562 $AFS_Help{'fs_checkservers'} = '[$fast], [$allcells], [$cell] => @down';
563 sub AFS_fs_checkservers {
564 my($fast, $allcells, $cell) = @_;
567 @args = ('checkservers');
568 push(@args, '-all') if $allcells;
569 push(@args, '-fast') if $fast;
570 push(@args, '-cell', $cell) if $cell;
571 &wrapper('fs', \@args, [
572 ['^These servers unavailable due to network or server problems: (.*)\.',
573 sub { push(@down, split(' ', $_[0])) }],
578 #: AFS_fs_checkservers_interval([$interval])
579 #: Get and/or set the down server check interval
580 #: If $interval is specified and nonzero, it is set as the new interval
581 #: On success, returns the old interval in seconds
582 $AFS_Help{'fs_checkservers_interval'} = '$interval => $oldinterval';
583 sub AFS_fs_checkservers_interval {
585 my(@args, $oldinterval);
587 @args = ('checkservers', '-interval', $interval);
588 &wrapper('fs', \@args, [
589 ['^The new down server probe interval \((\d+) secs\)', \$oldinterval],
590 ['^The current down server probe interval is (\d+) secs', \$oldinterval],
595 #: AFS_fs_exportafs($type, \%options);
596 #: Get and/or modify protocol translator settings
597 #: $type is the translator type, which must be 'nfs'
598 #: %options specifies the options to be set. Each key is the name of an
599 #: option, which is enabled if the value is 1, and disabled if the value
600 #: is 0. The following options are supported:
601 #: start Enable exporting of AFS
602 #: convert Copy AFS owner mode bits to UNIX group/other mode bits
603 #: uidcheck Strict UID checking
604 #: submounts Permit mounts of /afs subdirectories
605 #: On success, returns an associative array %modes, which is of the same
606 #: form, indicating which options are enabled.
607 $AFS_Help{'fs_exportafs'} = '$type, \%options => %modes';
608 sub AFS_fs_exportafs {
609 my($type, $options) = @_;
612 @args = ('exportafs', '-type', $type);
613 foreach (qw(start convert uidcheck submounts)) {
614 push(@args, "-$_", $$options{$_} ? 'on' : 'off') if exists($$options{$_});
617 &wrapper('fs', \@args, [
618 ['translator is disabled', sub { $modes{'start'} = 0 }],
619 ['translator is enabled', sub { $modes{'start'} = 1 }],
620 ['strict unix', sub { $modes{'convert'} = 0 }],
621 ['convert owner', sub { $modes{'convert'} = 1 }],
622 [q/no 'passwd sync'/, sub { $modes{'uidcheck'} = 0 }],
623 [q/strict 'passwd sync'/, sub { $modes{'uidcheck'} = 1 }],
624 ['Only mounts', sub { $modes{'submounts'} = 0 }],
625 ['Allow mounts', sub { $modes{'submounts'} = 1 }],
631 #: AFS_fs_getcacheparms()
632 #: Returns the size of the cache, and the amount of cache space used.
633 #: Sizes are returned in 1K blocks.
634 $AFS_Help{'fs_getcacheparms'} = 'void => ($size, $used)';
635 sub AFS_fs_getcacheparms {
636 my(@args, $size, $used);
638 @args = ('getcacheparms');
639 &wrapper('fs', \@args, [
640 [q/AFS using (\d+) of the cache's available (\d+) 1K byte blocks/,
646 #: AFS_fs_getcellstatus(\@cells)
647 #: Get cell control bits for cells listed in @cells.
648 #: On success, returns a hash mapping cells to their status; keys are
649 #: cell names, and values are 1 if SUID programs are permitted for that
650 #: cell, and 0 if not.
651 $AFS_Help{'fs_getcellstatus'} = '\@cells => %status';
652 sub AFS_fs_getcellstatus {
656 @args = ('getcellstatus', '-cell', @$cells);
657 &wrapper('fs', \@args, [
658 ['Cell (.*) status: setuid allowed', sub { $status{$_[0]} = 1 }],
659 ['Cell (.*) status: no setuid allowed', sub { $status{$_[0]} = 0 }],
664 #: AFS_fs_getclientaddrs
665 #: Returns a list of the client interface addresses
666 $AFS_Help{'fs_getclientaddrs'} = 'void => @addrs';
667 sub AFS_fs_getclientaddrs {
670 @args = ('getclientaddrs');
671 &wrapper('fs', \@args, [
672 ['^(\d+\.\d+\.\d+\.\d+)', \@addrs ]
678 #: Returns the cache manager encryption flag
679 $AFS_Help{'fs_getcrypt'} = 'void => $crypt';
680 sub AFS_fs_getcrypt {
683 @args = ('getcrypt');
684 &wrapper('fs', \@args, [
685 ['^Security level is currently clear', sub { $crypt = 0 }],
686 ['^Security level is currently crypt', sub { $crypt = 1 }],
691 #: AFS_fs_getserverprefs([$vlservers], [$numeric])
692 #: Get fileserver or vlserver preference ranks
693 #: If $vlservers is specified and nonzero, VLDB server ranks
694 #: are retrieved; otherwise fileserver ranks are retrieved.
695 #: If $numeric is specified and nonzero, servers are identified
696 #: by IP address instead of by hostname.
697 #: Returns a hash whose keys are server names or IP addresses, and
698 #: whose values are the ranks of those servers.
699 $AFS_Help{'fs_getserverprefs'} = '[$vlservers], [$numeric] => %prefs';
700 sub AFS_fs_getserverprefs {
701 my($vlservers, $numeric) = @_;
704 @args = ('getserverprefs');
705 push(@args, '-numeric') if $numeric;
706 push(@args, '-vlservers') if $vlservers;
707 &wrapper('fs', \@args, [
708 ['^(\S+)\s*(\d+)', \%prefs],
713 #: AFS_fs_listcells([$numeric')
714 #: Get a list of cells known to the cache manager, and the VLDB
715 #: servers for each cell.
716 #: If $numeric is specified and nonzero, VLDB servers are identified
717 #: by IP address instead of by hostname.
718 #: Returns a hash where each key is a cell name, and each value is
719 #: a list of VLDB servers for the corresponding cell.
720 $AFS_Help{'fs_listcells'} = '[$numeric] => %cells';
721 sub AFS_fs_listcells {
725 @args = ('listcells');
726 push(@args, '-numeric') if $numeric;
727 &wrapper('fs', \@args, [
728 ['^Cell (\S+) on hosts (.*)\.',
729 sub { $cells{$_[0]} = [ split(' ', $_[1]) ] }],
734 #: AFS_fs_setmonitor($server)
735 #: Set the cache manager monitor host to $server.
736 #: If $server is 'off' or undefined, monitoring is disabled.
737 #: On success, return 1.
738 $AFS_Help{'fs_setmonitor'} = '$server => Success?';
739 sub AFS_fs_setmonitor {
743 @args = ('monitor', '-server', defined($server) ? $server : 'off');
744 &wrapper('fs', \@args);
749 #: Return the cache manager monitor host, or undef if monitoring is disabled.
750 $AFS_Help{'fs_getmonitor'} = 'void => $server';
751 sub AFS_fs_getmonitor {
755 &wrapper('fs', \@args, [
756 ['Using host (.*) for monitor services\.', \$server],
762 #: Returns the current list of system type names
763 $AFS_Help{'fs_getsysname'} = 'void => @sys';
764 sub AFS_fs_getsysname {
768 &wrapper('fs', \@args, [
769 [q/Current sysname is '(.*)'/, \@sys],
770 [q/Current sysname list is '(.*)'/,
771 sub { push(@sys, split(q/' '/, $_[0])) }],
776 #: AFS_fs_setsysname(\@sys)
777 #: Sets the system type list to @sys
778 #: On success, return 1.
779 $AFS_Help{'fs_setsysname'} = '$server => Success?';
780 sub AFS_fs_setsysname {
784 @args = ('sysname', '-newsys', @$sys);
785 &wrapper('fs', \@args);
789 #: AFS_fs_whichcell(\@paths)
790 #: Get the cells containing the specified paths
791 #: Returns a hash in which each key is a pathname, and each value
792 #: is the name of the cell which contains the corresponding file.
793 $AFS_Help{'fs_whichcell'} = '\@paths => %where';
794 sub AFS_fs_whichcell {
798 @args = ('whichcell', '-path', @$paths);
799 &wrapper('fs', \@args, [
800 [q/^File (.*) lives in cell '(.*)'/, \%where],
806 #: Returns the name of the workstation's home cell
807 $AFS_Help{'fs_wscell'} = 'void => $cell';
812 &wrapper('fs', \@args, [
813 [q/^This workstation belongs to cell '(.*)'/, \$cell],