st_mode分析

在参考多篇文章后,自己做出的小结。

在Linux中,可以利用stat()函数来获取一个文件的状态。

#include <sys/stat.h>
#include <unistd.h>
 
int stat(const char *file_name, struct stat *buf);

这个函数通过文件名filename获取文件信息,并保存在buf所指的结构体stat中。执行成功返回0,失败返回-1。

struct stat的定义如下:

struct stat  
{  
    dev_t       st_dev;     /* ID of device containing file -文件所在设备的ID*/  
    ino_t       st_ino;     /* inode number -inode节点号*/
    mode_t      st_mode;    /* 文件的类型和存取的权限*/  
    nlink_t     st_nlink;   /* number of hard links -链向此文件的连接数(硬连接)*/  
    uid_t       st_uid;     /* user ID of owner -user id*/  
    gid_t       st_gid;     /* group ID of owner - group id*/  
    dev_t       st_rdev;    /* device ID (if special file) -设备号,针对设备文件*/  
    off_t       st_size;    /* total size, in bytes -文件大小,字节为单位*/  
    blksize_t   st_blksize; /* blocksize for filesystem I/O -系统块的大小*/  
    blkcnt_t    st_blocks;  /* number of blocks allocated -文件所占块数*/  
    time_t      st_atime;   /* time of last access -最近存取时间*/  
    time_t      st_mtime;   /* time of last modification -最近修改时间*/  
    time_t      st_ctime;   /* time of last status change -最后权限修改时间 */  
}; 

其中, st_mode这个变量用来判断文件类型,它的类型为mode_t,其实就是普通的unsigned int,但是只是用了低16位。
在这里插入图456213片描述
st_mode 主要包含了 3 部分信息:
a. 15bit ~ 12bit 保存文件类型
b. 11bit ~ 9bit 保存执行文件时设置的信息
c. 8bit ~ 0bit 保存文件访问权限

一、bit15 ~ bit12 , 文件类型属性区域

在现代linux操作系统上文件类型共分为7种,分别是:
- : 普通文件(regular file)
d : 目录(directory)
c : 字符设备(character device)
b : 块设备(block device)
p : 管道(FIFO)
l : 符号链接文件(symbolic link)
s : 套接口文件(socket)

所以文件类型属性只需3bit就够了。

二、bit11 ~ bit9,权限的特殊属性区域
bit11:set-user-ID位,执行时设置用户ID
bit10:set-group-ID位,执行时设置组ID
bit9:sticky位,仅对目录有效。设置后所有用户都可在这个目录下创建文件,但该目录下的文件只能被owner和root删除

下面来解释sticky位的作用:
首先要明白,要删除一个文件,一定要有这个文件的上级目录的写权限,可以没有文件的写权限。且没有一个目录的写权限,就不能在这个目录下创建文件。

sticky就是能使一个目录既可以让任何用户写入文件,又不让用户删除这个目录下他人的文件。sticky一般只用在目录上,普通文件的sticky位会被linux内核忽略。

sticky位出现执行许可x的位置上,用t表示(子目录不继承该权限,要再设置)。如下方的代码:

$ ls -dl /tmp  
drwxrwxrwt 15 root root  .........  // 注意 other 用户的权限位,x 变成了 t

那么原来的执行标志x到哪里去了呢? 系统是这样规定的, 假如本来在该位上有x, 则这些特别标志 (suid, sgid, sticky) 显示为小写字母 (s, s, t). 否则, 显示为大写字母 (S, S, T) 。

另外

chmod 777 abc  
chmod +t abc  

等价于

chmod 1777 abc 

即在设置sticky位后,目录的权限多了一个最高位的1。

三、bit8 ~ bit0,权限属性区域
即st_mode字段的最低9位,代表文件的许可权限,标识了文件所有者(owner)、组用户(group)、其他用户(other)的读(r)、写(w)、执行(x)权限。

四、实例分析
例一:st_mode 10进制值是 33204,转换成 8 进制后为 100664
图1 33204 填到 st_mode 中
        图1 33204 填到 st_mode 中

根据图1 我们可以得到如下信息:

  • 1000: 这是一个常规文件
  • 000: 执行时设置信息为空,黏着位为 0
  • 110-110-100: 用户权限为 RW-,组员权限为RW-,其他人权限为R--

例2:st_mode 值为 35309. 转换成 8 进制后为 104755
在这里插入图片描述
        图2 35309填充 st_mode

分析图2,可以知道:

  • 1000:这是一个普通文件
  • 100:suid 为 1
  • 111-101-101:用户权限为 RWX,组员权限为R-X,其他人权限为R-X

五、宏
通过手工分析 st_mode 字段,实际上是很不方便的。实际写程序,可使用 st_mode & 掩码来得到 st_mode 中特定的部分。比如:

st_mode & 0170000 : 得到文件类型
st_mode & 0007000 : 得到执行文件时设置信息
st_mode & 0000777 : 得到权限位
st_mode & 00100: 判断所有者是否可执行
(以上数字均为八进制)

为了方便使用,用 linux 预定义的一些宏来代替这些生硬的数字。这些宏定义在 include <sys/stat.h> 头文件中。

//bit15 ~ bit12 , 文件类型属性区域
#define  S_IFMT      0170000     文件类型的位遮罩
#define  S_IFSOCK    0140000     socket
#define  S_IFLNK     0120000     符号链接(symbolic link)
#define  S_IFREG     0100000     一般文件
#define  S_IFBLK     0060000     区块装置(block device)
#define  S_IFDIR     0040000     目录
#define  S_IFCHR     0020000     字符装置(character device)
#define  S_IFIFO     0010000     先进先出(fifo)

#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)  //提供了一些宏来帮助用户执行&操作,是则返回1
#define S_ISLNK(m)  (((m) & S_IFMT) == S_IFLNK)  
#define S_ISREG(m)  (((m) & S_IFMT) == S_IFREG)
#define S_ISBLK(m)  (((m) & S_IFMT) == S_IFBLK)
#define S_ISDIR(m)  (((m) & S_IFMT) == S_IFDIR)
#define S_ISCHR(m)  (((m) & S_IFMT) == S_IFCHR)
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)

//bit11 ~ bit9,权限的特殊属性区域
#define  S_ISUID      0004000     文件的(set user-id on execution)位
#define  S_ISGID      0002000     文件的(set group-id on execution)位
#define  S_ISVTX      0001000     文件的sticky位

//bit8 ~ bit0,权限属性区域
//文件所有者(owner)
#define S_IRWXU 00700	/* mask for file owner permissions */
#define S_IRUSR 00400	/* owner has read permission */
#define S_IWUSR 00200	/* owner has write permission */
#define S_IXUSR 00100	/* owner has execute permission */
 //组用户(group)
#define S_IRWXG 00070	/* mask for group permissions */
#define S_IRGRP 00040	/* group has read permission */
#define S_IWGRP 00020	/* group has write permission */
#define S_IXGRP 00010	/* group has execute permission */
 //其他用户(other)
#define S_IRWXO 00007	/* mask for permissions for others (not in group) */
#define S_IROTH 00004	/* others have read permission */
#define S_IWOTH 00002	/* others have write permission */
#define S_IXOTH 00001	/* others have execute permission */

以上宏可以自由组合使用。

  • 14
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值