从stat函数输出了解并解码文件模式值

从stat函数输出了解并解码文件模式值,第1张

从stat函数输出了解并解码文件模式

您问题的模式对应于具有644个权限的常规文件(所有者为只读文件,其他所有人为只读文件),但请不要误解。

$ touch foo$ chmod 644 foo$ perl -le'print +(stat“ foo”)[2]'33188

的值

$mode
可以 看作是十进制整数,但是这样做并不是特别有启发性。看到八进制表示形式会使您更加熟悉。

$ perl -e'printf“%o  n”,(stat“ foo”)[2]'100644

与07777的按位与运算给出数字二进制表示形式的最后十二位。在Unix模式下,此 *** 作将给出许可或模式位,并丢弃所有类型信息。

$ perl -e'printf“%d  n”,(stat“ foo”)[2]&07777'#十进制,无用420$ perl -e'printf“%o  n”,(stat“ foo”)[2]&07777'#八进制,尤里卡!644

下面是一种更好的方法。继续阅读以获取所有详细信息。


模式位

从返回的第三个元素

stat
(对应于
st_mode
in
structstat
)是一个位字段,其中不同的位位置是二进制标志。

例如,

st_mode
POSIX名称中的一位
S_IWUSR
设置了该位的模式的文件或目录可由其所有者写。一个相关的位是
S_IROTH
,当置位时表示其他用户(
所有者或组中的任何一个)都不能读取该特定文件或目录。

在为perlfunc文档

stat
提供了常用的模式位的名称。我们可以检查它们的价值。

#! /usr/bin/env perluse strict;use warnings;use Fcntl ':mode';my $perldoc_f_stat = q(  # Permissions: read, write, execute, for user, group, others.  S_IRWXU S_IRUSR S_IWUSR S_IXUSR  S_IRWXG S_IRGRP S_IWGRP S_IXGRP  S_IRWXO S_IROTH S_IWOTH S_IXOTH  # Setuid/Setgid/Stickiness/SaveText.  # Note that the exact meaning of these is system dependent.  S_ISUID S_ISGID S_ISVTX S_ISTXT  # File types.  Not necessarily all are available on your system.  S_IFREG S_IFDIR S_IFLNK S_IFBLK S_IFCHR S_IFIFO S_IFSOCK S_IFWHT S_ENFMT);my %mask;foreach my $sym ($perldoc_f_stat =~ /b(S_Iw+)b/g) {  my $val = eval { no strict 'refs'; &$sym() };  if (defined $val) {    $mask{$sym} = $val;  }  else {    printf "%-10s - undefinedn", $sym;  }}my @descending = sort { $mask{$b} <=> $mask{$a} } keys %mask;printf "%-10s - %9on", $_, $mask{$_} for @descending;

在Red Hat Enterprise Linux和System V系列中的其他 *** 作系统上,以上程序的输出将为

S_ISTXT-未定义S_IFWHT-未定义S_IFSOCK-140000S_IFLNK-120000S_IFREG-100000S_IFBLK-60000S_IFDIR-40000S_IFCHR-20000S_IFIFO-10000S_ISUID-4000S_ISGID-2000S_ISVTX-1000S_IRWXU-700S_IRUSR-400S_IWUSR-200S_IXUSR-100S_IRWXG-70S_IRGRP-40S_IWGRP-20S_IXGRP-10S_IRWXO-7S_IROTH-4S_IWOTH-2S_IXOTH-1
位旋转

上面的数字是八进制数(以8为底),因此任何给定的数字都必须为0-7,并且具有位置值8 n ,其中 n
是小数点左侧的从零开始的位置数。要查看它们如何映射到位,八进制具有方便的属性,即每个数字对应于三个位。4、2和1都是2的精确幂,因此以二进制形式分别是100、10和1。二进制中的七个(=
4 + 2 +1)是111,因此70 8是111000 2。后一个示例说明了如何来回转换是直接的。

与位域,你不在乎究竟 是什么 在那个位置有点值,但 是否 是零或非零,所以

if ($mode & $mask) {

测试是否设置了

$mode
对应的任何位
$mask
。举一个简单的例子,给定4位整数1011和掩码0100,它们的按位与为

  1011& 0100------  0000

因此,该位置上的位是清楚的,而不是0010或1100的掩码。

清除1011的最高有效位看起来像

    1011      1011& ~(1000) = & 0111 ------   0011

回想一下,

~
在Perl中是按位补码。

为了完整起见,请按如下所示使用按位OR进行设置

$bits |= $mask;
八进制和文件权限

对于Unix权限,八进制数字直接映射到三位非常方便,因为它们以三位一组出现。例如,产生上面输出的程序的权限为

-rwxr-xr-x 1个gbacon用户1096年2月24日20:34 modebits

也就是说,所有者可以读取,写入和执行;但是其他所有人都可以阅读和执行。八进制为755,这是紧凑的缩写形式。根据上表,该模式下的设置位为

  • S_IRUSR
  • S_IWUSR
  • S_IXUSR
  • S_IRGRP
  • S_IXGRP
  • S_IROTH
  • S_IXOTH

通过在上面的程序中添加几行,我们可以从您的问题中分解模式。

my $mode = 33188;print "nBits set in mode $mode:n";foreach my $sym (@descending) {    if (($mode & $mask{$sym}) == $mask{$sym}) {        print "  - $symn";        $mode &= ~$mask{$sym};    }}printf "extra bits: %on", $mode if $mode;

模式测试必须格外小心,因为某些掩码是多个位的简写形式。当一些位被置位但不是全部被置位时,进行测试以获取准确的掩码返回可以避免误报。

循环还会从所有检测到的命中清除位,因此最后我们可以检查是否已考虑到每个位。输出是

在模式33188中设置的位:  -S_IFREG  -S_IRUSR  -S_IWUSR  -S_IRGRP  -S_IROTH

没有额外的警告,所以我们得到了一切。

那魔术07777

将7777 8转换为二进制得到

0b111_111_111_111
。回想一下7 8是111
2,四个7对应于4×3。该掩码对于选择最后十二个设置的位很有用。回顾我们之前生成的位掩码

S_ISUID-4000S_ISGID-2000S_ISVTX-1000S_IRWXU-700S_IRWXG-70S_IRWXO-7

我们看到最后9位是用户,组和其他用户的权限。在它们之前的三位是setuid,setgroupid,有时也称为粘性位。例如,

sendmail
我系统上的完整模式为
-rwxr-sr-x
或34285 10。按位与的结果是

  (dec)      (oct)     (bin)  34285     102755     1000010111101101&  4095 = &   7777 = &     111111111111-------   --------   ------------------   1517 =     2755 =        10111101101

丢弃模式下的高位为

S_IFREG
,表明它是一个常规文件。请注意,与十进制或二进制的相同信息相比,八进制表示的模式更清晰。

stat
文档提到了一个有用的功能。

…的

S_IF*
功能是

S_IMODE($mode)

的部分
$mode
包含所述许可位和的setuid / setgid的/粘性位

在中

ext/Fcntl/Fcntl.xs
,我们在最后一行找到其实现和一个熟悉的常量。

voidS_IMODE(...)    PREINIT:        dXSTARG;        SV *mode;    PPCODE:        if (items > 0) mode = ST(0);        else { mode = &PL_sv_undef; EXTEND(SP, 1);        }        PUSHu(SvUV(mode) & 07777);

为了避免在源代码中使用幻数的错误做法,请编写

my $permissions = S_IMODE $mode;

使用

S_IMODE
Fcntl模块提供的功能和其他功能还隐藏了低级位混乱,并专注于程序所需的域级信息。该文档继续

S_IFMT($mode)

$mode
包含文件类型 的部分,可以使用(例如)
S_IFREG
或以下功能进行位与运算

# The operators -f, -d, -l, -b, -c, -p, and -S.S_ISREG($mode) S_ISDIR($mode) S_ISLNK($mode)S_ISBLK($mode) S_ISCHR($mode) S_ISFIFO($mode) S_ISSOCK($mode)# No direct -X operator counterpart, but for the first one# the -g operator is often equivalent.  The ENFMT stands for# record flocking enforcement, a platform-dependent feature.S_ISENFMT($mode) S_ISWHT($mode)

使用这些常量和函数可以更直接地表达您的意图,从而使您的程序更加清晰。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5015159.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-14
下一篇 2022-11-15

发表评论

登录后才能评论

评论列表(0条)

保存