line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Errno::AnyString; |
2
|
54
|
|
|
54
|
|
6265541
|
use strict; |
|
54
|
|
|
|
|
142
|
|
|
54
|
|
|
|
|
1798
|
|
3
|
54
|
|
|
54
|
|
285
|
use warnings; |
|
54
|
|
|
|
|
101
|
|
|
54
|
|
|
|
|
2898
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 NAME |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
Errno::AnyString - put arbitrary strings in $! |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
=head1 VERSION |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
Version 1.03 |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=cut |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
our $VERSION = '1.03'; |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 SYNOPSIS |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
C allows you to place an arbitrary error message in the special C<$!> variable, without disrupting C<$!>'s ability to pick up the result of the next system call that sets C. |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
It is useful if you are writing code that reports errors by setting C<$!>, and none of the standard system error messages fit. |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
use Errno qw/EIO/; |
24
|
|
|
|
|
|
|
use Errno::AnyString qw/custom_errstr/; |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
$! = custom_errstr "My hovercraft is full of eels"; |
27
|
|
|
|
|
|
|
print "$!\n"; # prints My hovercraft is full of eels |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
my $saved_errno = $!; |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
open my $fh, "<", "/no/such/file"; |
32
|
|
|
|
|
|
|
print "$!\n"; # prints No such file or directory |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
$! = EIO; |
35
|
|
|
|
|
|
|
print "$!\n"; # prints Input/output error |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
$! = $saved_errno; |
38
|
|
|
|
|
|
|
print "$!\n"; # prints My hovercraft is full of eels |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
You can also set the error strings for particular error numbers, for the lifetime of the Perl interpreter: |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
use Errno::AnyString qw/register_errstr/; |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
register_errstr "Wetware failure", 339864; |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
$! = 339864; |
47
|
|
|
|
|
|
|
print "$!\n"; # prints Wetware failure |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=head1 BACKGROUND |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
Perl's special C<$!> variable provides access to C, the "error number", which is an integer variable used by C library functions to record what went wrong when they fail. See L and L. |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
There is a fixed error message for each C value in use, and a C library function to translate C values into error messages. The magical C<$!> variable always holds the current value of C if you use it in a numeric context, and the corresponding error message if you use it in a string context. |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
open my $fh, "<", "/no/such/file"; # the failing open sets errno to 2 |
58
|
|
|
|
|
|
|
my $errno = $! + 0; # $errno now contains 2 |
59
|
|
|
|
|
|
|
my $err = "$!"; # $err now contains "No such file or directory" |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
You can also assign a number to C<$!>, to set the value of C. An C value of 22 means "invalid argument", so: |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
$! = 22; |
64
|
|
|
|
|
|
|
$errno = $! + 0; # $errno now contains 22 |
65
|
|
|
|
|
|
|
$err = "$!"; # $err now contains "Invalid argument" |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
What you can't do however is assign a string of your own choice to C<$!>. If you try, Perl just converts your string to an integer as best it can and puts that in C. |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
$! = "You broke it"; |
70
|
|
|
|
|
|
|
# gives an "Argument isn't numeric" warning and sets errno to 0 |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
=head1 DESCRIPTION |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
C allows you to set the error message strings that correspond to particular C values. It makes a change to the C<$!> magic so that the correct string is returned when C takes a value for which a string has been registered. The change to C<$!> is global and lasts until the Perl interpreter exits. |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
=cut |
77
|
|
|
|
|
|
|
|
78
|
54
|
|
|
54
|
|
269
|
use Exporter; |
|
54
|
|
|
|
|
116
|
|
|
54
|
|
|
|
|
1852
|
|
79
|
54
|
|
|
54
|
|
288
|
use Carp; |
|
54
|
|
|
|
|
93
|
|
|
54
|
|
|
|
|
3633
|
|
80
|
54
|
|
|
54
|
|
295
|
use Scalar::Util qw/dualvar tainted/; |
|
54
|
|
|
|
|
143
|
|
|
54
|
|
|
|
|
26601
|
|
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
require XSLoader; |
83
|
|
|
|
|
|
|
XSLoader::load('Errno::AnyString', $VERSION); |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
our @ISA = qw/Exporter/; |
86
|
|
|
|
|
|
|
our @EXPORT_OK = qw/custom_errstr register_errstr CUSTOM_ERRSTR_ERRNO/; |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
our (%Errno2Errstr, %_string2errno); |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
Errno::AnyString::_install_my_magic($!); |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
=head1 EXPORTS |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
Nothing is exported by default. The following are available for export. |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=head2 CUSTOM_ERRSTR_ERRNO |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
A constant with the value 458513437. This is the C value used by this module to indicate that a custom error string set with custom_errstr() is active. This value was chosen at random, to avoid picking an C value that something else uses. |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
=cut |
101
|
|
|
|
|
|
|
|
102
|
480
|
|
|
480
|
1
|
137618
|
sub CUSTOM_ERRSTR_ERRNO () { return 458513437; } |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
our $_next_registered_errno = CUSTOM_ERRSTR_ERRNO() + 1; |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
=head2 custom_errstr ( ERROR_STRING ) |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
Returns a value which will set the specified custom error string when assigned to C<$!>. |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
The returned value is actually a dual valued scalar with C as its numeric value and the specified error string as its string value. It's not just magical variables like C<$!> that can hold a number and a string at the same time, ordinary Perl scalars can do it as well. See L. |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
With C loaded, the C<$!> magic responds specially to a scalar with a numeric value of CUSTOM_ERRSTR_ERRNO being assigned to C<$!>: the string value of the scalar gets recorded as the registered string for C value CUSTOM_ERRSTR_ERRNO, replacing any previous registered string for that value. |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
This way of setting the custom error string was chosen because it works well with code that saves and restores the value of C<$!>. |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
$! = custom_errstr "Test string"; |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
my $saved_errno = $!; |
119
|
|
|
|
|
|
|
do_other_things(); |
120
|
|
|
|
|
|
|
$! = $saved_errno; |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
print "$!\n"; # prints Test string |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
When C<$!> is copied to C<$saved_errno>, C<$saved_errno> becomes dual valued with a number value of CUSTOM_ERRSTR_ERRNO and a string value of "Test string". When C<$saved_errno> gets copied back to C<$!> at the end, the number value of CUSTOM_ERRSTR_ERRNO triggers the modified C<$!> magic to register the string value of "Test string" as the custom error string for CUSTOM_ERRSTR_ERRNO. |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
This is important because code called from within do_other_things() might itself use custom_errstr() to set custom error strings, overwriting the registered error string of "Test string". Since C<$saved_errno> saves the error message string as well as the C value, the C<$!> magic can put the correct string back in place when the C<$saved_errno> value is restored. |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
=cut |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
sub custom_errstr ($) { |
131
|
202
|
100
|
|
202
|
1
|
5414829
|
tainted $_[0] and croak "Tainted error string used with Errno::AnyString"; |
132
|
|
|
|
|
|
|
|
133
|
198
|
|
|
|
|
559
|
return dualvar CUSTOM_ERRSTR_ERRNO, "$_[0]"; |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=head2 register_errstr ( ERROR_STRING [,ERRNO_VALUE] ) |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
register_errstr() can be used in a similar way to custom_errstr(): |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
$! = register_errstr "An error string"; |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
The difference is that register_errstr() permanently (i.e. for the lifetime of the Perl interpreter) assigns an C value to that error string. The error string is stored away, and will be used as the string value of C<$!> any time that C value is set in future. By default, register_errstr() picks a large C value that it has not yet assigned to any other string. |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
If you call register_errstr() repeatedly with the same error string, it will notice and use the same C value each time. That means it's safe to do something like: |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
$! = register_errstr "Too many foos defined"; |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
in code that could be called a large number of times, and register_errstr() will store only one copy of the string and use up only one C value. |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
You can specify the C value to use as a second parameter to register_errstr(), for example: |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
$! = register_errstr "my error string", 999999; |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
This sets the error string for C value 999999 (replacing any previously set error string for 999999) and assigns it to C<$!>. You can also call register_errstr() simply to register a bunch of new error codes, without assigning the return value to C<$!> each time: |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
register_errstr "Invalid foodb file", -20000; |
157
|
|
|
|
|
|
|
register_errstr "Invalid foodb parameter", -20001; |
158
|
|
|
|
|
|
|
register_errstr "foodb out of key slots", -20002; |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
# ... |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
$! = -20001; |
163
|
|
|
|
|
|
|
print "$!\n"; # prints Invalid foodb parameter |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
It is also possible to use register_errstr() to replace the standard system error messages. For example, to replace the "Permission denied" message; |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
use Errno qw/EACCES/; |
168
|
|
|
|
|
|
|
register_errstr "I'm sorry, Dave. I'm afraid I can't do that", EACCES; |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
open my $fh, ">/no_permission_to_write_here"; |
171
|
|
|
|
|
|
|
print "$!\n"; prints "I'm sorry, Dave. I'm afraid I can't do that" |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
This is not something I'd recommend, as it's likely to cause confusion. In general, when specifying the C value to register_errstr() one should take care to avoid values that are likely to be used for any other purpose. |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
Internally, the error strings registered by register_errstr() are kept in the C<%Errno::AnyString::Errno2Errstr> hash. You shouldn't go poking around in this hash yourself, but by localising it you can limit the scope of a register_errstr() registration: |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
{ |
178
|
|
|
|
|
|
|
local %Errno::AnyString::Errno2Errstr = %Errno::AnyString::Errno2Errstr; |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
register_errstr "I'm sorry, Dave. I'm afraid I can't do that", EACCES; |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
# here you have a silly error message in place of "Permission denied" |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
# here sanity is restored |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=cut |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
sub register_errstr ($;$) { |
189
|
40148
|
|
|
40148
|
1
|
340070
|
my ($str, $num) = @_; |
190
|
|
|
|
|
|
|
|
191
|
40148
|
100
|
|
|
|
99316
|
tainted $str and croak "Tainted error string used with Errno::AnyString"; |
192
|
|
|
|
|
|
|
|
193
|
40138
|
100
|
|
|
|
69635
|
unless (defined $num) { |
194
|
92
|
|
|
|
|
189
|
$num = $_string2errno{$str}; |
195
|
92
|
100
|
|
|
|
231
|
unless (defined $num) { |
196
|
64
|
|
|
|
|
106
|
$num = $_next_registered_errno++; |
197
|
64
|
|
|
|
|
178
|
$_string2errno{$str} = $num; |
198
|
|
|
|
|
|
|
} |
199
|
|
|
|
|
|
|
} |
200
|
40138
|
|
|
|
|
116903
|
$Errno2Errstr{$num} = "$str"; |
201
|
|
|
|
|
|
|
|
202
|
40138
|
|
|
|
|
107649
|
return dualvar $num, $str; |
203
|
|
|
|
|
|
|
} |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
=head1 INTER-OPERATION |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
This section is aimed at the authors of other modules that alter C<$!>'s behaviour, as a guide to ensuring clean inter-operation between Errno::AnyString and your module. |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
Errno::AnyString works by adding two instances of uvar magic to C<$!>, one at the head of the list and one at the tail. It does not modify or remove any existing magic from C<$!>. It should inter-operate cleanly with anything else that adds more magic to C<$!>, so long magic is added in a way that preserves existing uvar magic. |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
Emptying the C<%Errno::AnyString::Errno2Errstr> hash effectively turns off this module's interference with C<$!>, so you can get a "real" C<$!> value with: |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
my $e = do { local %Errno::AnyString::Errno2Errstr ; $! }; |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
=head1 AUTHOR |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
Dave Taylor, C<< >> |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
=head1 BUGS AND LIMITATIONS |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
=head2 C LEVEL STRERROR CALLS |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
If C level code attempts to get a textual error message based on C while a custom error string is set, it will get something like the following, depending on the platform: |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
Unknown error 458513437 |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
=head2 PURE NUMERIC RESTORE |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
If the string part of a saved custom_errstr() C<$!> value is lost, then restoring that value to C<$!> restores the string most recently set with custom_errstr(), which is not necessarily the string that was set when the C<$!> value was saved. |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
$! = custom_errstr "String 1"; |
232
|
|
|
|
|
|
|
my $saved_errno = 0 + $!; |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
$! = custom_errstr "String 2"; |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
$! = $saved_errno; |
237
|
|
|
|
|
|
|
print "$!\n"; # prints String 2 |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
Note that the Perl code that saved the error number had to go out of its way to discard the string part of C<$!>, so I think this combination is fairly unlikely in practice. |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
Error strings set with register_errstr() are not effected by this issue, since each gets its own unique C value. For this reason, register_errstr() should be used in preference to custom_errstr() if you have a small number of fixed error strings: |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
$! = register_errstr "Attempt to frob without a foo"; # good |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
However, register_errstr() uses up an C value and permanently stores the string each time it is called with a string it has not seen before. If your code could generate a large number of different error strings over the lifetime of the Perl interpreter, then using register_errstr() could cost a lot of memory. In such cases, custom_errstr() would be a better choice. |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
$! = register_errstr "failed at $line in $file: $why"; # less good |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
=head2 TAINT MODE |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
I'm currently unable to find a good way to propagate the taintedness of custom error strings through C<$!>, due to an interaction between taint magic, C<$!>'s dualvar behaviour and the SvPOK flag in some Perl versions. If Perl is in taint mode then passing a tainted error string to custom_errstr() or register_errstr() will cause an immediate croak with the message: |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
Tainted error string used with Errno::AnyString |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
=head2 OTHER BUGS |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
Please report any other bugs or feature requests to C, or through |
258
|
|
|
|
|
|
|
the web interface at L. I will be notified, and then you'll |
259
|
|
|
|
|
|
|
automatically be notified of progress on your bug as I make changes. |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
=head1 SUPPORT |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
perldoc Errno::AnyString |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
You can also look for information at: |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
=over 4 |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
L |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
L |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
=item * CPAN Ratings |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
L |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
=item * Search CPAN |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
L |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
=back |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
=head1 SEE ALSO |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
L, L, L, L |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
Copyright 2009 Dave Taylor, all rights reserved. |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
299
|
|
|
|
|
|
|
under the same terms as Perl itself. |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
=cut |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
1; # End of Errno::AnyString |