文件属性结构体详解,ls的详细信息,st_mode详细使用(文件属性)【linux】(p)

文件属性结构体详解

struct stat
 {
dev_t     st_dev;      	 /* 块设备号 */
ino_t     st_ino;        /* inode结点号,文件属性信息所存inode节点的编号 */ 
mode_t    st_mode;    	 /* 文件类型和文件权限*/  ls
nlink_t   st_nlink;      /* 链接数 */             ls
uid_t     st_uid;        /* 文件所属用户ID*/      ls
gid_t     st_gid;        /* 文件所属组ID */       ls
dev_t     st_rdev;       /* 字符设备ID */         
off_t     st_size;       /* 文件大小 */
blksize_t st_blksize;    /* 系统每次按块Io操作时,块的大小(一般是512或1024) */
blkcnt_t  st_blocks;  	 /* 块的索引号 */
time_t    st_atime;   	/* 最后一次访问时间,read*/  ls
time_t    st_mtime; 	 	/* 最后一次修改时间,write */
time_t    st_ctime;   	/* 最后一次属性修改的时间,如权限被修改,文件所有者(属主)被修改 */
 };

7类文件都有的属性

ino_t     st_ino;        /* inode结点号 */
mode_t    st_mode;    	 /* 文件类型和文件权限*/
nlink_t   st_nlink;      /* 链接数 */
uid_t     st_uid;        /* 文件所属用户ID*/
gid_t     st_gid;        /* 文件所属组ID */
off_t     st_size;       /* 文件大小 */
time_t    st_atime;   	/* 最后一次访问时间,read*/
time_t    st_mtime; 	 	/* 最后一次修改时间,write */
time_t    st_ctime;   	/* 最后一次属性修改的时间,如权限被修改,文件所有者(属主)被修改 */

以上是7类文件都有的属性。

dev_t     st_dev;  /* 块设备号 */ 
blksize_t st_blksize;    /* 系统每次按块Io操作时,块的大小(一般是512或1024) */
blkcnt_t  st_blocks;  	 /* 块的索引号 */

以上专门给块设备文件用的。

dev_t     st_rdev; /* 字符设备号(ID) */

上面是专门给字符设备用的

ls的详细信息

ls对应信息:

st_mode       st_link   st_uid    st_gid    st_size    st_atime       文件名
-rw-rw-r--         1    stu        stu       0        Feb  4 20:35    new.c

st_uid

在这里插入图片描述

用户id(用户编号),编号是唯一的,例子中的编号1000代表的就是stu这个用户。
在Linux下,是以编号形式来管理用户的,这有点像人名和身份证的关系。

st_gid

多个用户可以在一起组成一个组,其中的某个用户会担任组长,该用户的用户id,就是整个组的组id。
这就好比张三、李四、王五组成了一个组,张三当组长,张三的身份证号也被作为了整个组的组id,张三的名字也被作为了整个组的组名。
对于普通用户而言,自己一个人就是一组,组员和组长都是自己,所以一般情况下,ls显示文件的所属组时,就是所属用户亲自担任组长的那个组,而且组员就自己一人。

st_mode

在这里插入图片描述

ls显示的st_mode(比如-rw-rw-r–)

扫描二维码关注公众号,回复: 9056839 查看本文章

– :文件类型
-rw-rw-r–:文件权限
每三个为一组(-rw-rw-r–)

每组第一个:如果是-,表示不能读,如果是r,表示可以读
每组第二个:如果是-,表示不能写,如果是w,表示可以写
每组第三个:如果是-,表示不可以被cpu执行,如果是x,表示可以被执行。
如果是编译得到的可执行文件(里面所放的内容是机器指令),这个文件是可以被cpu执行。

第一组:代表的是文件所属用户,对该文件的操作权限
第二组:代表的是文件所属组里面,其它的组员用户,对该文件的操作权限
第三组:除了所属用户、所属组以外的,其它用户对该文件的操作权限。
举例:在普通用户下修改root用户的文件。

三组权限的大小关系

正常情况下:

所属用户的操作权限 >= 组员用户的操作权限 >= 其它不相干用户的操作权限

这就好比:
你自己的私人物品:
所属用户:你,你拥有最高操作权限
所属组:你和你的家人就是一个组,你的家人作为组员,拥有仅次于你的操作权限
外人:你家人以外的人,显然拥有最低操作权限,低到甚至是没有操作权限

将数字形式的st_mode,打印为-rwxrwxr-x形式

st_mode的本质
st_mode的本质就是一个数字,我们看到的rwx的形式,只是形态转换的结果。

st_mode的组成

我们以二进制来分析st_mode,以二进制表示时,st_mode有16位,包含三部分信息:
在这里插入图片描述

我们之后对于设置位进行说明。
我们对于文件进行查看:
在这里插入图片描述我们可以看到起始为十进制33204转化二进制形式为:
‭1000 000 110110100‬‬
文件类型:1000
设置位:000
文件权限:110 110 100‬‬

文件类型

12~15 bit用于表示文件类型
表示文件类型

八进制 二进制

  • 0100000(1000 000000000000):代表普通文件
  • 0040000(0100 000000000000):代表目录文件
  • 0060000(0110 000000000000):代表块设备文件
  • 0020000(0011 000000000000):代表字符设备文件
  • 0010000(0001 000000000000):代表管道文件
  • 0140000(1100 000000000000):代表套接字文件
  • 0120000(1010 000000000000):代表符号链接文件
    八进制第一个0是格式说明,表示八进制数。变换为二进制,前面4位表示文件类型。为了方便使用,在Linux系统提供的stat.h头文件中,给以上数字定义了宏名。

我们在linux平台中通过man 2 stat 查看:
在这里插入图片描述

如何取出12~15位的值,然后用于判断文件的类型:
使用c语言中的 & 操作即可实现

我们使用屏蔽字0170000(1111000000000000)&st_mode,将013清零(屏蔽),留下的1215就是我们要的文件类型。

关于C语言位操作,读者可以在C语言专栏进行阅读。
系统给这个屏蔽字定义了一个宏名,即#define S_IFMT 0170000

比如:我们前面中的st_mode为:
33204转化位二进制为

‭1000 000 110110100
&
1111 000 000 000 000
结果为:
1000 000 000 000 000

经过比对,我们给出的new.txt是属于普通文件。

判断文件类型

为了方便我们操作,系统在stat.h中定义了相应的带参宏,可以让我们快速的判断文件的类型。
#define S_ISLNK(st_mode) (((st_mode) & S_IFMT) == S_IFLNK)
#define S_ISREG(st_mode) (((st_mode) & S_IFMT) == S_IFREG)
#define S_ISDIR(st_mode) (((st_mode) & S_IFMT) == S_IFDIR)
#define S_ISCHR(st_mode) (((st_mode) & S_IFMT) == S_IFCHR)
#define S_ISBLK(st_mode) (((st_mode) & S_IFMT) == S_IFBLK)
#define S_ISFIFO(st_mode) (((st_mode) & S_IFMT) == S_IFIFO)
#define S_ISSOCK(st_mode) (((st_mode) & S_IFMT) == S_IFSOCK)

每一个带参宏,用于判断一种文件类型,判断时会把st_mode&S_IFMT,然后与对应的类型比对,如果比对结果为真,就表示是这种类型的文件,否则就不是。

代码演示:

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

void print_error(char *str)
{
         perror(str);
         exit(-1);
}
int main(int argc,char **argv)
{
        int ret = 0;
        struct stat sta = {0};
        //int stat(const char *pathname, struct stat *statbuf);
        //获取文件属性
        if(argc != 2)
        {
                printf("my_ls fileName\n\n");
                exit(-1);
        }
        printf("argv[0] = %s,argc[1] = %s\n",argv[0],argv[1]);
        ret = stat(argv[1],&sta);
        if(-1 == ret)   print_error("stat fail");
        ////打印文件类型
        char file_type = '0';
        if(S_ISLNK(sta.st_mode))        file_type = 'l';
        else if( S_ISREG(sta.st_mode))  file_type = '-';
        else if( S_ISDIR(sta.st_mode))  file_type = 'd';
        else if( S_ISCHR(sta.st_mode))  file_type = 'c';
        else if( S_ISBLK(sta.st_mode))  file_type = 'b';
        else if( S_ISFIFO(sta.st_mode)) file_type = 'p';
        else if( S_ISSOCK(sta.st_mode)) file_type = 's';
        printf("%c ",file_type);
        //打印文件属性
        printf("%d %lu %d %d %ld %ld %s\n",sta.st_mode,sta.st_nlink,sta.st_uid,sta.st_gid,sta.st_size,sta.st_atime,argv[1]);
        return 0;
}   

执行结果为:

在这里插入图片描述

我们再创建一个目录文件进行验证:
在这里插入图片描述
我们就可以看到文件类型。

文件权限

0~8bit表示文件权限
在这里插入图片描述

对于普通文件,即使是给了可执行权限,能够被CPU执行也必须是机器指令才能被执行,如果是文字编码给可执行权限是没有意义的。

从st_mode中提取文件权限

提取用户对应的权限
在stat.h中,定义了对应的屏蔽字。定义了三个宏定义:
#define S_IRUSR 00400:对应的是0000 000 100 000 000,提取用户读权限
#define S_IWUSR 00200:对应的是0000 000 010 000 000,提取用户写权限
#define S_IXUSR 00100:对应的是0000 000 001 000 000,提取用户可执行权限

我们下里面举出来提取用户读权限的例子,写权限和可执行权限方法类似。
我们前面中的st_mode为:
33204转化位二进制为
1000 000 110 110 100
&
0000 000 100 000 000
结果为1
0000 000 100 000 000
表示用户可读 结果为0表示用户不可读。

提取组对应的权限
#define S_IRGRP 00040 (0000 000 000 100 000)组读权限
#define S_IWGRP 00020 (0000 000 000 010 000)组写权限
#define S_IXGRP 00010 (0000 000 000 001 000)组可执行权限

提取其他用户对应的权限
#define S_IROTH 00004 (0000 000 000 000 100)其他用户读权限
#define S_IWOTH 00002 (0000 000 000 000 010)其他用户写权限
#define S_IXOTH 00001 (0000 000 000 000 001)其他用户可执行权限

代码演示:
将数字表示的读写权限,表示为rwx所表示的权限。

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

void print_error(char *str)
{
         perror(str);
         exit(-1);
}
int main(int argc,char **argv)
{
        int ret = 0;
        struct stat sta = {0};
        //int stat(const char *pathname, struct stat *statbuf);
        //获取文件属性
        if(argc != 2)
        {
                printf("my_ls fileName\n\n");
                exit(-1);
        }
      printf("argv[0] = %s,argc[1] = %s\n",argv[0],argv[1]);
        ret = stat(argv[1],&sta);
        if(-1 == ret)   print_error("stat fail");
        ////打印文件类型
        char file_type = '0';
        if(S_ISLNK(sta.st_mode))        file_type = 'l';
        else if( S_ISREG(sta.st_mode))  file_type = '-';
        else if( S_ISDIR(sta.st_mode))  file_type = 'd';
        else if( S_ISCHR(sta.st_mode))  file_type = 'c';
        else if( S_ISBLK(sta.st_mode))  file_type = 'b';
        else if( S_ISFIFO(sta.st_mode)) file_type = 'p';
        else if( S_ISSOCK(sta.st_mode)) file_type = 's';
        printf("%c ",file_type);
        //打印文件权限
        char buf[10] = {0};
        char tmp_buf[] = "rwxrwxrwx";
        int i;
        for(i = 0;i<9;i++)
        {
                if(sta.st_mode&(1<<(8-i))) buf [i] = tmp_buf[i];
                else buf[i] = '-';
        }
        printf("%s",buf);
        //打印文件属性
        printf("%d %lu %d %d %ld %ld %s\n",sta.st_mode,sta.st_nlink,sta.st_uid,sta.st_gid,sta.st_size,sta.st_atime,argv[1]);
        return 0;
}

执行结果为:
在这里插入图片描述

那么我们已经实现了 st_mode 我们就可以把33204删除掉。
删除之后执行结果为:

在这里插入图片描述

我们可以看到文件权限的部分和ls实现的是一样,说明我们上面的实现没有问题。

使用chmod命令修改文件权限(rwx)

直接使用数字

①chmod 0777 file.txt
这个0777,在命令行时,代表八进制的0可以省略。

第一个7:user对应的权限,111
第二个7:group对应的权限,111
第三个7:other对应的权限,111

修改后,文件的权限变为了:rwxrwxrwx。

②:chmod 0664 file.txt

0664的二进制为
110 110 100
修改后,文件的权限变为了:rw-rw-r–。

我们前面提到的对于存放文字编码的普通文件来说,不需要任何的执行权限。

open创建文件时所指定的原始权限
fd = open("./new_file.txt", O_RDWR|O_CREAT, 0664);
Open函数里面0不能省略
使用open系统API创建新文件时,需要制定一个原始的权限,比如指定的是0664的话,就表示,创建出的文件的原始权限为rw-rw-r–。

直接使用rwx来设置

修改所有权限
chmod a=rw- file.txt
表示所有的权限全部指定为rw-

只修改某一组的权限
chmod u=rw- file.txt
只将文件所属用户对应的权限设置为rw-

chmod g=r-- file.txt
只将文件所属组对应的权限设置为r–

chmod o=r-- file.txt
只将其它用户对应的权限设置为r–

chmod u=rwx,g=rw-,o=r-- file.txt
一次性的对三个权限都做设置。

只修改组里面某一位的权限
chmod u+x file.txt 给所属用户加上可执行权限
chmod u-x file.txt 给所属用户去掉可执行权限
chmod u+x,u+r file.txt 给所属用户加上可执行权限和读权限
chmod g+w file.txt 给组加上写权限
chmod o+r file.txt 给其他用户加上读权限
chmod u+r,g+w,o+x file.txt 给所属用户机上读权限,给组加上写权限,给其他用户加上可执行权限。

设置位用的很少,因此这里就不再说明,我们只需要知道在st_mode里面有三位设置位即可。

发布了84 篇原创文章 · 获赞 71 · 访问量 9096

猜你喜欢

转载自blog.csdn.net/qq_43648751/article/details/104222145
今日推荐