2 # Copyright (c) 1996, Carnegie Mellon University
5 # See CMUCS/CMU_copyright.pm for use and distribution information
7 package OpenAFS
::errtrans
;
11 OpenAFS::errtrans - com_err error translation
16 $code = errcode($name);
17 $code = errcode($pkg, $err);
18 $string = errstr($code, [$volerrs]);
22 This module translates "common" error codes such as those produced
23 by MIT's com_err package, and used extensively in AFS. It also knows
24 how to translate system error codes, negative error codes used by Rx,
25 and a few "special" error codes used by AFS's volume package.
27 In order to work, these routines depend on the existence of error
28 table files in $err_table_dir, which is usually /usr/local/lib/errtbl.
29 Each file should be named after a com_err error package, and contain
30 the definition for that package.
32 Note that the AFS version of com_err translates package names to uppercase
33 before generating error codes, so a table which claims to define the 'pt'
34 package actually defines the 'PT' package when compiled by AFS's compile_et.
35 Tables that are normally fed to AFS's compile_et should be installed using
36 the _uppercase_ version of the package name.
38 The error tables used in AFS are part of copyrighted AFS source code, and
39 are not included with this package. However, I have included a utility
40 (gen_et) which can generate error tables from the .h files normally
41 produced by compile_et, and Transarc provides many of these header files
42 with binary AFS distributions (in .../include/afs). See the gen_et
43 program for more details.
47 use OpenAFS
::CMU_copyright
;
48 use OpenAFS
::util
qw(:DEFAULT :afs_internal);
49 use OpenAFS
::config
qw($err_table_dir);
57 @EXPORT = qw(&errcode &errstr);
60 @NumToChar = ('', 'A'..'Z', 'a'..'z', '0'..'9', '_');
61 %CharToNum = map(($NumToChar[$_], $_), (1 .. $#NumToChar));
63 %Vol_Codes = ( VSALVAGE
=> 101,
75 %Vol_Desc = ( 101 => "volume needs to be salvaged",
76 102 => "no such entry (vnode)",
77 103 => "volume does not exist / did not salvage",
78 104 => "volume already exists",
79 105 => "volume out of service",
80 106 => "volume offline (utility running)",
81 107 => "volume already online",
82 108 => "unknown volume error 108",
83 109 => "unknown volume error 109",
84 110 => "volume temporarily busy",
87 %Rx_Codes = ( RX_CALL_DEAD
=> -1,
88 RX_INVALID_OPERATION
=> -2,
89 RX_CALL_TIMEOUT
=> -3,
91 RX_PROTOCOL_ERROR
=> -5,
95 RXGEN_CC_MARSHAL
=> -450,
96 RXGEN_CC_UNMARSHAL
=> -451,
97 RXGEN_SS_MARSHAL
=> -452,
98 RXGEN_SS_UNMARSHAL
=> -453,
100 RXGEN_OPCODE
=> -455,
101 RXGEN_SS_XDRFREE
=> -456,
102 RXGEN_CC_XDRFREE
=> -457
104 %Rx_Desc = ( -1 => "server or network not responding",
105 -2 => "invalid RPC (Rx) operation",
106 -3 => "server not responding promptly",
107 -4 => "Rx unexpected EOF",
108 -5 => "Rx protocol error",
109 -6 => "Rx user abort",
110 -7 => "port address already in use",
111 -8 => "Rx message size incorrect",
112 -450 => "Rx client: XDR marshall failed",
113 -451 => "Rx client: XDR unmarshall failed",
114 -452 => "Rx server: XDR marshall failed",
115 -453 => "Rx server: XDR unmarshall failed",
116 -454 => "Rx: Decode failed",
117 -455 => "Rx: Invalid RPC opcode",
118 -456 => "Rx server: XDR free failed",
119 -457 => "Rx client: XDR free failed",
120 map(($_ => "RPC interface mismatch ($_)"), (-499 .. -458)),
121 -999 => "Unknown error"
126 my(@tbl) = split(//, $_[0]);
129 @tbl = @tbl[0..3] if (@tbl > 4);
130 foreach (@tbl) { $n = ($n << 6) + $CharToNum{$_} }
140 $tbl = @NumToChar[$n & 0x3f] . $tbl;
147 sub _load_system_errors
{
151 return if ($did_include{$file});
152 # print "Loading $file...\n";
153 $did_include{$file} = 'yes';
154 if (open($fh, "/usr/include/$file")) {
156 if (/^\#define\s*(E\w+)\s*(\d+)/) {
158 } elsif (/^\#include\s*\"([^"]+)\"/
159 || /^\#include\s*\<([^>]+)\>/) {
160 &_load_system_errors
($1);
168 # Load an error table into memory
169 sub _load_error_table
{
171 my($fh, @words, $curval, $tval, $nval);
172 my($tid, $tfn, $code, $val, $desc);
174 return if ($Have_Table{$pkg});
175 # Read in the input file, and split it into words
177 return unless open($fh, "$err_table_dir/$pkg");
178 # print "Loading $pkg...\n";
179 line
: while (<$fh>) {
180 s/^\s*//; # Strip leading whitespace
183 if (/^(error_table|et)\s*/) { push(@words, 'et'); $_ = $' }
184 elsif (/^(error_code|ec)\s*/) { push(@words, 'ec
'); $_ = $' }
185 elsif (/^end\s*/) { push(@words, 'end'); $_ = $' }
186 elsif (/^(\w+)\s*/) { push(@words, $1); $_ = $' }
187 elsif (/^\"([^"]*)\"\s*/) { push(@words, $1); $_ = $' }
188 elsif (/^([,=])\s*/) { push(@words, $1); $_ = $' }
189 else { close($fh); return }
194 # Parse the table header
195 $_ = shift(@words); return unless ($_ eq 'et');
196 if ($words[1] eq 'ec') { $tid = shift(@words) }
197 elsif ($words[2] eq 'ec') { ($tfn, $tid) = splice(@words, 0, 2) }
200 $Have_Table{$tid} = 'yes';
203 $tid = $_ if ($_ eq $pkg);
205 $tval = &_tbl_to_num
($tid);
206 $Have_Table{$pkg} = 'yes';
207 # print "Package $pkg: table-id = $tid, table-fun = $tfn, base = $tval\n";
210 $_ = shift(@words); return unless ($_ eq 'ec');
211 $code = shift(@words);
214 $val = shift(@words);
219 return unless ($_ eq ',');
220 $desc = shift(@words);
221 $nval = $tval + $val;
223 $Desc{$nval} = $desc;
224 $Codes{$code} = $nval;
225 # print " code $code: value = $nval ($tval + $val), desc = \"$desc\"\n";
229 =head2 errcode($name)
231 Returns the numeric error code corresponding to the specified error
232 name. This routine knows about names of system errors, a few special
233 Rx and volume-package errors, and any errors defined in installed
234 error tables. If the specified error code is not found, returns -999.
236 =head2 errcode($pkg, $code)
238 Shifts $code into the specified error package, and returns the
239 resulting com_err code. This can be used to generate error codes
240 for _any_ valid com_err package.
246 my($pkg, $code) = @_;
247 &_tbl_to_num
($pkg) + $code;
250 my($dir, @tbls, $code);
252 &_load_system_errors
("errno.h");
253 if ($Vol_Codes{$name}) { $Vol_Codes{$name} }
254 elsif ($Rx_Codes{$name}) { $Rx_Codes{$name} }
255 elsif ($Codes{$name}) { $Codes{$name} }
257 if ($name =~ /^E/) { # Might be a POSIX error constant
259 $code = &POSIX
::constant
($name, 0);
260 if (!$!) { return $code; }
263 if (opendir($dir, $err_table_dir)) {
264 @tbls = grep(!/^\.?\.$/, readdir($dir));
266 foreach (@tbls) { &_load_error_table
($_) }
268 $Codes{$name} ?
$Codes{$name} : -999;
274 =head2 errstr($code, [$volerrs])
276 Returns the error string corresponding to a specified com_err, Rx,
277 or system error code. If $volerrs is specified and non-zero, then
278 volume-package errors are considered before system errors with the
284 my($code, $volerrs) = @_;
287 if ($Rx_Desc{$code}) { return $Rx_Desc{$code} }
288 if ($volerrs && $Vol_Desc{$code}) { return $Vol_Desc{$code} }
290 $pkg = &_num_to_tbl
($code);
294 if (/^(Error )?\d+$/) { $Vol_Desc{$sub} ?
$Vol_Desc{$sub} : "Error $sub" }
297 &_load_error_table
($pkg);
298 $Desc{$code} ?
$Desc{$code} : "Unknown code $pkg $sub ($code)";
306 The CMUCS AFStools, including this module are
307 Copyright (c) 1996, Carnegie Mellon University. All rights reserved.
308 For use and redistribution information, see CMUCS/CMU_copyright.pm