Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / tests / OpenAFS / fs.pm
1 # CMUCS AFStools
2 # Copyright (c) 1996, 2001 Carnegie Mellon University
3 # All rights reserved.
4 #
5 # See CMU_copyright.ph for use and distribution information
6 #
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.
12 #:
13
14 package OpenAFS::fs;
15 use OpenAFS::CMU_copyright;
16 use OpenAFS::util qw(:DEFAULT :afs_internal);
17 use OpenAFS::wrapper;
18 use Exporter;
19
20 $VERSION = '';
21 $VERSION = '1.00';
22 @ISA = qw(Exporter);
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
43 &AFS_fs_wscell);
44
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.
55 #:
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
67 #: keys as you go.
68 #:
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.
73 #:
74 $AFS_Help{fs_getacl} = '$path => (\@posacl, \@negacl)';
75 sub AFS_fs_getacl {
76 my($path) = @_;
77 my(@args, @posacl, @negacl, $neg);
78
79 @args = ('listacl', '-path', $path);
80 &wrapper('fs', \@args,
81 [
82 [ '^(Normal|Negative) rights\:', sub {
83 $neg = ($_[0] eq 'Negative');
84 }],
85 [ '^ (.*) (\S+)$', sub { #',{
86 if ($neg) {
87 push(@negacl, [@_]);
88 } else {
89 push(@posacl, [@_]);
90 }
91 }]]);
92 (\@posacl, \@negacl);
93 }
94
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?';
104 sub AFS_fs_setacl {
105 my($paths, $posacl, $negacl, $clear) = @_;
106 my($ace, $U, $access);
107
108 if (@$posacl) {
109 @args = ('setacl', '-dir', @$paths);
110 push(@args, '-clear') if ($clear);
111 push(@args, '-acl');
112 foreach $e (@$posacl) {
113 ($U, $access) = @$e;
114 $access = 'none' if ($access eq '');
115 push(@args, $U, $access);
116 }
117 &wrapper('fs', \@args);
118 }
119 if (@$negacl) {
120 @args = ('setacl', '-dir', @$paths, '-negative');
121 push(@args, '-clear') if ($clear && !@$posacl);
122 push(@args, '-acl');
123 foreach $e (@$negacl) {
124 ($U, $access) = @$e;
125 $access = 'none' if ($access eq '');
126 push(@args, $U, $access);
127 }
128 &wrapper('fs', \@args);
129 }
130 if ($clear && !@$posacl && !@$negacl) {
131 @args = ('setacl', '-dir', @$paths,
132 '-acl', 'system:anyuser', 'none', '-clear');
133 &wrapper('fs', \@args);
134 }
135 1;
136 }
137
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'.
141 #:
142 $AFS_Help{'fs_cleanacl'} = '\@paths => Success?';
143 sub AFS_fs_cleanacl {
144 my($paths) = @_;
145 my(@args);
146
147 @args = ('cleanacl', '-path', @$paths);
148 &wrapper('fs', \@args);
149 1;
150 }
151
152 #: AFS_fs_getquota($path) [listquota]
153 #: Get the quota on the specified path.
154 #: On success, returns the quota.
155 #:
156 $AFS_Help{'fs_getquota'} = '$path => $quota';
157 sub AFS_fs_getquota {
158 my($path) = @_;
159 my(@args, $quota);
160
161 @args = ('listquota', '-path', $path);
162 &wrapper('fs', \@args,
163 [[ '^\S+\s+(\d+)\s+\d+\s+\d+\%', \$quota ]]);
164 $quota;
165 }
166
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
171 #:
172 $AFS_Help{'fs_setquota'} = '$path, $quota => Success?';
173 sub AFS_fs_setquota {
174 my($path, $quota) = @_;
175 my(@args);
176
177 @args = ('setquota', '-path', $path, '-max', $quota);
178 &wrapper('fs', \@args);
179 1;
180 }
181
182 #: AFS_fs_whereis($path) [whereis, whichcell]
183 #: Locate the fileserver housing the specified path, and the cell in which it
184 #: is located.
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.
189 #:
190 $AFS_Help{'fs_whereis'} = '$path => ($cell, @servers)';
191 sub AFS_fs_whereis {
192 my($path) = @_;
193 my(@args, $cell, @servers);
194
195 @args = ('whichcell', '-path', $path);
196 &wrapper('fs', \@args,
197 [[ "lives in cell \'(.*)\'", \$cell ]]);
198
199 @args = ('whereis', '-path', $path);
200 &wrapper('fs', \@args,
201 [[ 'is on host(s?)\s*(.*)', sub {
202 @servers = split(' ', $_[1]);
203 }]]);
204 ($cell, @servers);
205 }
206
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:
211 #: - vol_name
212 #: - vol_id
213 #: - quota_max
214 #: - quota_used
215 #: - quota_pctused
216 #: - part_size
217 #: - part_avail
218 #: - part_used
219 #: - part_pctused
220 #:
221 $AFS_Help{'fs_examine'} = '$path => %info';
222 sub AFS_fs_examine {
223 my($path) = @_;
224 my(@args, %info);
225
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;
236 } else {
237 $info{'quota_pctused'} = ($info{'quota_used'} / $info{'quota_max'}) * 100;
238 $info{'quota_pctused'} =~ s/\..*//;
239 }
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/\..*//;
243 %info;
244 }
245
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?';
250 sub AFS_fs_setvol {
251 my($path, $maxquota, $motd) = @_;
252 my(@args);
253
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);
258 1;
259 }
260
261
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 {
268 my($path) = @_;
269 my(@args, $vol);
270
271 @args = ('lsmount', '-dir', $path);
272 &wrapper('fs', \@args,
273 [[ "mount point for volume '(.+)'", \$vol ]]);
274 $vol;
275 }
276
277
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?';
285 sub AFS_fs_mkmount {
286 my($path, $vol, $cell, $rwmount, $fast) = @_;
287 my(@args);
288
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);
294 1;
295 }
296
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?';
301 sub AFS_fs_rmmount {
302 my($path) = @_;
303 my(@args);
304
305 @args = ('rmmount', '-dir', $path);
306 &wrapper('fs', \@args);
307 1;
308 }
309
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 {
315 my(@args);
316
317 @args = ('checkvolumes');
318 &wrapper('fs', \@args);
319 1;
320 }
321
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?';
326 sub AFS_fs_flush {
327 my($paths) = @_;
328 my(@args);
329
330 @args = ('flush');
331 push(@args, '-path', @$paths) if $paths;
332 &wrapper('fs', \@args);
333 1;
334 }
335
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 {
341 my($paths) = @_;
342 my(@args);
343
344 @args = ('flushmount');
345 push(@args, '-path', @$paths) if $paths;
346 &wrapper('fs', \@args);
347 1;
348 }
349
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 {
355 my($paths) = @_;
356 my(@args);
357
358 @args = ('flushvolume');
359 push(@args, '-path', @$paths) if $paths;
360 &wrapper('fs', \@args);
361 1;
362 }
363
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 {
370 my($mode) = @_;
371 my(@args);
372
373 @args = ('messages', '-show', $mode);
374 &wrapper('fs', \@args);
375 1;
376 }
377
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?';
382 sub AFS_fs_newcell {
383 my($cell, $dbservers, $linkedcell) = @_;
384 my(@args);
385
386 @args = ('newcell', '-name', $cell, '-servers', @$dbservers);
387 push(@args, '-linkedcell', $linkedcell) if $linkedcell;
388 &wrapper('fs', \@args);
389 1;
390 }
391
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) = @_;
401 my(@args);
402
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);
408 1;
409 }
410
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) = @_;
420 my(@args);
421
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);
427 1;
428 }
429
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 {
435 my($size) = @_;
436 my(@args);
437
438 @args = ('setcachesize', '-blocks', $size);
439 &wrapper('fs', \@args);
440 1;
441 }
442
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?';
449 sub AFS_fs_setcell {
450 my($cells, $suid) = @_;
451 my(@args);
452
453 @args = ('setcell', '-cell', @$cells);
454 push(@args, '-suid') if $suid;
455 push(@args, '-nosuid') if defined($suid) && !$suid;
456 &wrapper('fs', \@args);
457 1;
458 }
459
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 {
467 my($enable) = @_;
468 my(@args);
469
470 @args = ('setcrypt', '-crypt', $enable ? 'on' : 'off');
471 &wrapper('fs', \@args);
472 1;
473 }
474
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 {
480 my($addrs) = @_;
481 my(@args);
482
483 @args = ('setclientaddrs');
484 push(@args, '-address', @$addrs) if $addrs;
485 &wrapper('fs', \@args);
486 1;
487 }
488
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?';
494 sub AFS_fs_copyacl {
495 my($from, $to, $clear) = @_;
496 my(@args);
497
498 @args = ('copyacl', '-fromdir', $from, '-todir', @$to);
499 push(@args, '-clear') if $clear;
500 &wrapper('fs', \@args);
501 1;
502 }
503
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);
515
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],
526 ]);
527 ($ndef, \%sizes);
528 }
529
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) = @_;
538 my(@args, $srv);
539
540 @args = ('setserverprefs');
541 if ($fsprefs && %$fsprefs) {
542 push(@args, '-servers');
543 foreach $srv (keys %$fsprefs) {
544 push(@args, $srv, $$fsprefs{$srv});
545 }
546 }
547 if ($vlprefs && %$vlprefs) {
548 push(@args, '-vlservers');
549 foreach $srv (keys %$vlprefs) {
550 push(@args, $srv, $$vlprefs{$srv});
551 }
552 }
553 &wrapper('fs', \@args);
554 1;
555 }
556
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) = @_;
565 my(@args, @down);
566
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])) }],
574 ]);
575 @down;
576 }
577
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 {
584 my($interval) = @_;
585 my(@args, $oldinterval);
586
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],
591 ]);
592 $oldinterval;
593 }
594
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) = @_;
610 my(@args, %modes);
611
612 @args = ('exportafs', '-type', $type);
613 foreach (qw(start convert uidcheck submounts)) {
614 push(@args, "-$_", $$options{$_} ? 'on' : 'off') if exists($$options{$_});
615 }
616
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 }],
626 ]);
627 %modes;
628 }
629
630
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);
637
638 @args = ('getcacheparms');
639 &wrapper('fs', \@args, [
640 [q/AFS using (\d+) of the cache's available (\d+) 1K byte blocks/,
641 \$used, \$size],
642 ]);
643 ($size, $used);
644 }
645
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 {
653 my($cells) = @_;
654 my(@args, %status);
655
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 }],
660 ]);
661 %status;
662 }
663
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 {
668 my(@args, @addrs);
669
670 @args = ('getclientaddrs');
671 &wrapper('fs', \@args, [
672 ['^(\d+\.\d+\.\d+\.\d+)', \@addrs ]
673 ]);
674 @addrs;
675 }
676
677 #: AFS_fs_getcrypt
678 #: Returns the cache manager encryption flag
679 $AFS_Help{'fs_getcrypt'} = 'void => $crypt';
680 sub AFS_fs_getcrypt {
681 my(@args, $crypt);
682
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 }],
687 ]);
688 $crypt;
689 }
690
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) = @_;
702 my(@args, %prefs);
703
704 @args = ('getserverprefs');
705 push(@args, '-numeric') if $numeric;
706 push(@args, '-vlservers') if $vlservers;
707 &wrapper('fs', \@args, [
708 ['^(\S+)\s*(\d+)', \%prefs],
709 ]);
710 %prefs;
711 }
712
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 {
722 my($numeric) = @_;
723 my(@args, %cells);
724
725 @args = ('listcells');
726 push(@args, '-numeric') if $numeric;
727 &wrapper('fs', \@args, [
728 ['^Cell (\S+) on hosts (.*)\.',
729 sub { $cells{$_[0]} = [ split(' ', $_[1]) ] }],
730 ]);
731 %cells;
732 }
733
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 {
740 my($server) = @_;
741 my(@args);
742
743 @args = ('monitor', '-server', defined($server) ? $server : 'off');
744 &wrapper('fs', \@args);
745 1;
746 }
747
748 #: AFS_fs_getmonitor
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 {
752 my(@args, $server);
753
754 @args = ('monitor');
755 &wrapper('fs', \@args, [
756 ['Using host (.*) for monitor services\.', \$server],
757 ]);
758 $server;
759 }
760
761 #: AFS_fs_getsysname
762 #: Returns the current list of system type names
763 $AFS_Help{'fs_getsysname'} = 'void => @sys';
764 sub AFS_fs_getsysname {
765 my(@args, @sys);
766
767 @args = ('sysname');
768 &wrapper('fs', \@args, [
769 [q/Current sysname is '(.*)'/, \@sys],
770 [q/Current sysname list is '(.*)'/,
771 sub { push(@sys, split(q/' '/, $_[0])) }],
772 ]);
773 @sys;
774 }
775
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 {
781 my($sys) = @_;
782 my(@args);
783
784 @args = ('sysname', '-newsys', @$sys);
785 &wrapper('fs', \@args);
786 1;
787 }
788
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 {
795 my($paths) = @_;
796 my(@args, %where);
797
798 @args = ('whichcell', '-path', @$paths);
799 &wrapper('fs', \@args, [
800 [q/^File (.*) lives in cell '(.*)'/, \%where],
801 ]);
802 %where;
803 }
804
805 #: AFS_fs_wscell
806 #: Returns the name of the workstation's home cell
807 $AFS_Help{'fs_wscell'} = 'void => $cell';
808 sub AFS_fs_wscell {
809 my(@args, $cell);
810
811 @args = ('wscell');
812 &wrapper('fs', \@args, [
813 [q/^This workstation belongs to cell '(.*)'/, \$cell],
814 ]);
815 $cell;
816 }
817