line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# |
2
|
|
|
|
|
|
|
# |
3
|
|
|
|
|
|
|
# Stat::lsMode |
4
|
|
|
|
|
|
|
# |
5
|
|
|
|
|
|
|
# Copyright 1998 M-J. Dominus |
6
|
|
|
|
|
|
|
# (mjd-perl-lsmode@plover.com) |
7
|
|
|
|
|
|
|
# |
8
|
|
|
|
|
|
|
# You may distribute this module under the same terms as Perl itself. |
9
|
|
|
|
|
|
|
# |
10
|
|
|
|
|
|
|
# $Revision: 1.2 $ $Date: 1998/04/20 01:27:25 $ |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
package Stat::lsMode; |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
$VERSION = '0.50'; |
16
|
|
|
|
|
|
|
|
17
|
1
|
|
|
1
|
|
2436
|
use Carp; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
90
|
|
18
|
1
|
|
|
1
|
|
5
|
use Exporter; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
1241
|
|
19
|
|
|
|
|
|
|
@ISA = qw(Exporter); |
20
|
|
|
|
|
|
|
@EXPORT = qw(format_mode file_mode format_perms); |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
@perms = qw(--- --x -w- -wx r-- r-x rw- rwx); |
23
|
|
|
|
|
|
|
@ftype = qw(. p c ? d ? b ? - ? l ? s ? ? ?); |
24
|
|
|
|
|
|
|
$ftype[0] = ''; |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
$NOVICE_MODE = 1; # Default on? |
27
|
|
|
|
|
|
|
sub novice { |
28
|
0
|
|
|
0
|
0
|
0
|
my $pack = shift; |
29
|
0
|
0
|
|
|
|
0
|
croak "novice_mode requires one boolean argument" unless @_ == 1; |
30
|
0
|
|
|
|
|
0
|
my $old = $NOVICE_MODE; # Should this be localized t $pack? |
31
|
0
|
|
|
|
|
0
|
$NOVICE_MODE = $_[0]; |
32
|
0
|
|
|
|
|
0
|
$old; |
33
|
|
|
|
|
|
|
} |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
sub format_mode { |
36
|
14
|
50
|
|
14
|
1
|
236
|
croak "format_mode requires a mode as an argument" unless @_ >= 1; |
37
|
14
|
|
|
|
|
18
|
my $mode = shift; |
38
|
14
|
|
|
|
|
19
|
my %opts = @_; |
39
|
|
|
|
|
|
|
|
40
|
14
|
50
|
|
|
|
26
|
unless (defined $mode) { |
41
|
0
|
0
|
|
|
|
0
|
return wantarray() ? () : undef; |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
|
44
|
14
|
50
|
|
|
|
35
|
_novice_warning($mode) if $NOVICE_MODE; |
45
|
|
|
|
|
|
|
|
46
|
14
|
|
|
|
|
17
|
my $setids = ($mode & 07000)>>9; |
47
|
14
|
|
|
|
|
34
|
my @permstrs = @perms[($mode&0700)>>6, ($mode&0070)>>3, $mode&0007]; |
48
|
14
|
|
|
|
|
21
|
my $ftype = $ftype[($mode & 0170000)>>12]; |
49
|
14
|
50
|
|
|
|
26
|
my @ftype = $opts{no_ftype} ? () : ($ftype); |
50
|
|
|
|
|
|
|
|
51
|
14
|
50
|
|
|
|
25
|
if ($setids) { |
52
|
0
|
0
|
|
|
|
0
|
if ($setids & 01) { # Sticky bit |
53
|
0
|
0
|
|
|
|
0
|
$permstrs[2] =~ s/([-x])$/$1 eq 'x' ? 't' : 'T'/e; |
|
0
|
|
|
|
|
0
|
|
54
|
|
|
|
|
|
|
} |
55
|
0
|
0
|
|
|
|
0
|
if ($setids & 04) { # Setuid bit |
56
|
0
|
0
|
|
|
|
0
|
$permstrs[0] =~ s/([-x])$/$1 eq 'x' ? 's' : 'S'/e; |
|
0
|
|
|
|
|
0
|
|
57
|
|
|
|
|
|
|
} |
58
|
0
|
0
|
|
|
|
0
|
if ($setids & 02) { # Setgid bit |
59
|
0
|
0
|
|
|
|
0
|
$permstrs[1] =~ s/([-x])$/$1 eq 'x' ? 's' : 'S'/e; |
|
0
|
|
|
|
|
0
|
|
60
|
|
|
|
|
|
|
} |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
|
63
|
14
|
50
|
|
|
|
43
|
if (wantarray) { |
64
|
0
|
|
|
|
|
0
|
(@ftype, @permstrs); |
65
|
|
|
|
|
|
|
} else { |
66
|
14
|
|
|
|
|
54
|
join '', @ftype, @permstrs; |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
sub file_mode { |
71
|
6
|
50
|
|
6
|
1
|
927
|
croak "file_mode requires one filename as an argument" unless @_ == 1; |
72
|
6
|
|
|
|
|
8
|
my $file = shift; |
73
|
6
|
|
|
|
|
145
|
my $mode = (lstat $file)[2]; |
74
|
|
|
|
|
|
|
|
75
|
6
|
50
|
|
|
|
16
|
unless (defined $mode) { |
76
|
0
|
0
|
|
|
|
0
|
if (wantarray) { |
77
|
0
|
|
|
|
|
0
|
return (); |
78
|
|
|
|
|
|
|
} else { |
79
|
0
|
0
|
|
|
|
0
|
carp "Couldn't get mode for file `$file': $!" if $NOVICE_MODE; |
80
|
0
|
|
|
|
|
0
|
return undef; |
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
|
84
|
6
|
|
|
|
|
11
|
format_mode($mode, @_); |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
sub format_perms { |
91
|
0
|
0
|
|
0
|
0
|
0
|
croak "format_perms requires a permission mode as an argument" unless @_ == 1; |
92
|
0
|
|
|
|
|
0
|
format_mode($_[0], no_ftype => 1); |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
# None of these are really plausible modes. |
96
|
|
|
|
|
|
|
# They are all almost certain to have occurred |
97
|
|
|
|
|
|
|
# when someone used decimal instead of octal to specify a mode. |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
@badmodes = (777, 775, 755, 770, 700, 750, |
100
|
|
|
|
|
|
|
751, |
101
|
|
|
|
|
|
|
666, 664, 644, 660, 600, 640, |
102
|
|
|
|
|
|
|
444, 440, |
103
|
|
|
|
|
|
|
400, # 400 = rw--w---- which is just barely plausible. |
104
|
|
|
|
|
|
|
# 000 *is* OK. It means just what you think. |
105
|
|
|
|
|
|
|
711, 771, 751, 551, 111, |
106
|
|
|
|
|
|
|
); |
107
|
|
|
|
|
|
|
%badmode = map {($_ => 1)} @badmodes; |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# Novices like to ask for the bits for mode `666' instead of `0666'. |
110
|
|
|
|
|
|
|
# Try to detect and diagnose that. |
111
|
|
|
|
|
|
|
sub _novice_warning { |
112
|
14
|
|
|
14
|
|
14
|
my $mode = shift; |
113
|
14
|
50
|
|
|
|
35
|
if ($badmode{$mode}) { |
114
|
0
|
|
|
|
|
|
carp "mode $mode is very surprising. Perhaps you meant 0$mode"; |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
=head1 NAME |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
Stat::lsMode - format file modes like the C command does |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
=head1 SYNOPSIS |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
use Stat::lsMode; |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
$mode = (stat $file)[2]; |
127
|
|
|
|
|
|
|
$permissions = format_mode($mode); |
128
|
|
|
|
|
|
|
# $permissions is now something like `drwxr-xr-x' |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
$permissions = file_mode($file); # Same as above |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
$permissions = format_perms(0644); # Produces just 'rw-r--r--' |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
$permissions = format_perms(644); # This generates a warning message: |
135
|
|
|
|
|
|
|
# mode 644 is very surprising. Perhaps you meant 0644... |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
Stat::lsMode->novice(0); # Disable warning messages |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
=head1 DESCRIPTION |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
C generates mode and permission strings that look like |
142
|
|
|
|
|
|
|
the ones generated by the Unix C command. For example, a |
143
|
|
|
|
|
|
|
regular file that is readable by everyone and writable only by its |
144
|
|
|
|
|
|
|
owner has the mode string C<-rw-r--r-->. C will either |
145
|
|
|
|
|
|
|
examine the file and produce the right mode string for you, or you can |
146
|
|
|
|
|
|
|
pass it the mode that you get back from Perl's C call. |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
=head2 C |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
Given a mode number (such as the third element of the list returned by |
151
|
|
|
|
|
|
|
C), return the appopriate ten-character mode string as it would |
152
|
|
|
|
|
|
|
have been generated by C. For example, |
153
|
|
|
|
|
|
|
consider a directory that is readable and searchable by everyone, and |
154
|
|
|
|
|
|
|
also writable by its owner. Such a directory will have mode 040755. |
155
|
|
|
|
|
|
|
When passed this value, C will return the string |
156
|
|
|
|
|
|
|
C. |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
If C is passed a permission number like C<0755>, it will |
159
|
|
|
|
|
|
|
return a nine-character string insted, with no leading character to |
160
|
|
|
|
|
|
|
say what the file type is. For example, C will |
161
|
|
|
|
|
|
|
return just C, without the leading C. |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
=head2 C |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
Given a filename, do C on the file to determine the mode, and |
166
|
|
|
|
|
|
|
return the mode, formatted as above. |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=head2 Novice Operation Mode |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
A common mistake when dealing with permission modes is to use C<644> |
171
|
|
|
|
|
|
|
where you meant to use C<0644>. Every permission has a numeric |
172
|
|
|
|
|
|
|
representation, but the representation only makes sense when you write |
173
|
|
|
|
|
|
|
the number in octal. The decimal number 644 corresponds to a |
174
|
|
|
|
|
|
|
permission setting, but not the one you think. If you write it in |
175
|
|
|
|
|
|
|
octal you get 01204, which corresponds to the unlikely permissions |
176
|
|
|
|
|
|
|
C<-w----r-T>, not to C. |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
The appearance of the bizarre permission C<-w----r-T> in a program is |
179
|
|
|
|
|
|
|
almost a sure sign that someone used C<644> when they meant to use |
180
|
|
|
|
|
|
|
C<0644>. By default, this module will detect the use of such unlikely |
181
|
|
|
|
|
|
|
permissions and issue a warning if you try to format them. To disable |
182
|
|
|
|
|
|
|
these warnings, use |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
Stat::lsMode->novice(0); # disable novice mode |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
Stat::lsMode->novice(1); # enable novice mode again |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
The surprising permissions that are diagnosed by this mode are: |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
111 => --xr-xrwx |
191
|
|
|
|
|
|
|
400 => rw--w---- |
192
|
|
|
|
|
|
|
440 => rw-rwx--- |
193
|
|
|
|
|
|
|
444 => rw-rwxr-- |
194
|
|
|
|
|
|
|
551 => ---r--rwt |
195
|
|
|
|
|
|
|
600 => --x-wx--T |
196
|
|
|
|
|
|
|
640 => -w------T |
197
|
|
|
|
|
|
|
644 => -w----r-T |
198
|
|
|
|
|
|
|
660 => -w--w-r-T |
199
|
|
|
|
|
|
|
664 => -w--wx--T |
200
|
|
|
|
|
|
|
666 => -w--wx-wT |
201
|
|
|
|
|
|
|
700 => -w-rwxr-T |
202
|
|
|
|
|
|
|
711 => -wx---rwt |
203
|
|
|
|
|
|
|
750 => -wxr-xrwT |
204
|
|
|
|
|
|
|
751 => -wxr-xrwt |
205
|
|
|
|
|
|
|
751 => -wxr-xrwt |
206
|
|
|
|
|
|
|
755 => -wxrw--wt |
207
|
|
|
|
|
|
|
770 => r------wT |
208
|
|
|
|
|
|
|
771 => r------wt |
209
|
|
|
|
|
|
|
775 => r-----rwt |
210
|
|
|
|
|
|
|
777 => r----x--t |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
Of these, only 400 is remotely plausible. |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
=head1 BUGS |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
As far as I know, the precise definition of the mode bits is portable |
217
|
|
|
|
|
|
|
between varieties of Unix. The module should, however, examine |
218
|
|
|
|
|
|
|
C or use some other method to find out if there are any local |
219
|
|
|
|
|
|
|
variations, because Unix being Unix, someone somewhere probably does |
220
|
|
|
|
|
|
|
it differently. |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
Maybe it C should have an option that says that if the file |
223
|
|
|
|
|
|
|
is a symlink, to format the mode of the pointed to file instead of the |
224
|
|
|
|
|
|
|
mode of the link itself, the way C does. |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
=head1 SEE ALSO |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
=over 4 |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
=item * |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
C. |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
=item * |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
L |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
=item * |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
L |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
=item * |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
L |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
=back |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
=head1 AUTHOR |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
Mark-Jason Dominus (C). |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
=cut |
253
|
|
|
|
|
|
|
|