#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h> //需包含头文件
有如下三个函数的函数原型:
int stat(const char *path, struct stat *buf);
第一个形参:指出文件(文件路径); 第二个形参:出参数(函数对该参数操作,然后传出)。
int fstat(int fd, struct stat *buf);
fstat函数与stat函数的功能一样,只是第一个形参是文件描述符。
int lstat(const char *path, struct stat *buf);
lstat函数的形参跟stat函数的形参一样。其功能也跟stat函数功能一样,仅有一点不同:stat函数是穿透(追踪)函数,即对软链接文件进行操作时,操作的是链接到的那一个文件,不是软链接文件本身;而lstat函数是不穿透(不追踪)函数,对软链接文件进行操作时,操作的是软链接文件本身。
以上三个函数:成功返回0,失败返回-1,并且将详细错误信息赋值给errno全局变量。
其它Linux系统函数类似,带l表示不追踪,不带l表示追踪(穿透)。如:ls –l命令查看的文件属性,是不追踪(不穿透)的;rm删除文件时,是不追踪的;Vi和Vim是穿透的;对于穿透的命令,是无法判断文件是不是软链接文件,比如ls –l命令,其是不穿透的,因此可以判断是否是软链接文件;如果是用stat函数实现的ls –l命令,则是穿透的,对于查看原文件和链接文件的属性是一样的,无法区别两者,因此可以考虑用lstat函数来实现ls –l命令的功能。
注意:创建软链接最好用绝对路径 ln –s 原文件 软链接文件(采用绝对路径)
stat、lstat和fstat函数中 struct stat类型的说明:
struct stat {
dev_t st_dev; /* 文件的设备编号 */
ino_t st_ino; /* 索引结点编号 */
mode_t st_mode; /* 文件类型和权限*/
nlink_t st_nlink; /*硬链接数 */
uid_t st_uid; /*用户ID*/
gid_t st_gid; /* 组ID*/
dev_t st_rdev; /* 设备类型(若此文件为设备文件,则为设备编号*/
off_t st_size; /* 文件大小*/
blksize_t st_blksize; /*文件系统的I/O缓冲区大小*/
blkcnt_t st_blocks; /* 块数 */
time_t st_atime; /* 访问时间 */
time_t st_mtime; /* 修改时间 */
time_t st_ctime; /* 更改时间 */
}; //标红为重点内容
struct stat结构体位于inode(索引结点)中,但是其内部不包含文件名。文件名位于位于文件的目录项dentry中(即简化的FCB),其包含文件名和inode编号。通过denty的inode编号可以找到inode,进一步找到文件本身。硬链接就是denty(目录项)。
上述结构体中,对st_mode成员做一个详细的介绍:
mode_t st_mode; /* 文件类型和权限*/
st_mode变量(mode_t类型):该变量占 2byte共16位,为16位的整型值。用于储存文件类型和权限。 如下图所示:
每一位均为二进制数。r代表4,即100;w代表2,即010;x代表1,即001。由于总共16位二进制数,因此需要6位8进制数来进行表示,其中8进制数以0开头,共7位。
其他人权限(0~2位)。读权限:0000004,在所给函数头文件中进行了宏定义为:S_IROTH;写:0000002,S_IWOTH;执行:0000001,S_IXOTH。 掩码为:0000007,S_IRWXO 掩码的作用:st_mode & 掩码 就可以过滤st_mode中除其他人权限以外的信息,所得结果直接是其他人的权限信息,下面原理相同。
所属组权限(3~5位)。读权限:0000040, S_IRGRP;写:0000020,S_IWGRP;执行:0000010,S_IXGRP。 掩码为:0000070,S_IRWXG。
所属主权限(6~8位)。读权限:0000400, S_IRUSR;写:0000200,S_IWUSR;执行:0000100,S_IXUSR。 掩码为:0000700,S_IRWXU。
特殊权限位(9~11位)。SUID:0004000, S_ISUID;SGID:0002000,S_ISGID;SBIT:0001000,S_ISVTX。 //特殊权限位很少用
文件类型(12~15位,共7种类型文件)。套接字(socket)文件s:0140000,S_IFSOCK;链接文件(软链接)l:0120000,S_IFLNK;普通文件-:0100000,S_IFREG;块设备文件b:0060000,S_IFBLK;目录文件d:0040000,S_IFDIR;字符设备文件c:0020000,S_IFCHR;管道文件p:0010000,S_IFIFO。 掩码:0170000 作用一样,st_mode & 掩码 的结果与七种类型的宏相比较,就可以判断是哪一种文件。
强调一下特殊权限位SBIT(粘滞位)的功能:1.对目录设置粘滞位,则该目录内的文件只能被文件所有者、超级用户和目录所有者这三类用户删除,其他用户都没有删除的权限;2.对文件设置了粘滞位,那么在内存资源十分紧张的情况下,也不会把该文件放回到磁盘上。如磁盘的对换区SWAP,当内存紧张,优先级别低的进程会被暂时放回到对换区中,但是一旦设置了粘滞位,则不会放回磁盘,依然处于内存。
下面是说明stat函数的使用的代码:
//运用stat函数实现查看文件大小属性的功能
[root@localhost work]# vim statuse.c
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main( int argc,char *argv[ ] ) //命令行参数
{
if( argc < 2 )
printf("./statuse filename1 filename2 ...\n");
struct stat zsx;
int ret;
int i=1;
for( i=1;i<argc;i++ )
{
ret = stat( argv[i],&zsx); //stat函数获取文件的属性,穿透的
if( ret == -1 )
{
perror("stat filename");
exit(1);
}
int size = (int)zsx.st_size; //注意,必须强制转换,后者变量是off_t类型
printf("%s %d\n",argv[i],size);
}
return 0;
}
[root@localhost work]# gcc -pipe -ggdb3 -pedantic -Wall statuse.c -o statuse
[root@localhost work]# ls
english.txt ls-l.c stat.c statuse statuse.c
[root@localhost work]# ./statuse english.txt ls-l.c stat.c statuse statuse.c
english.txt 109055
ls-l.c 2204
stat.c 416
statuse 57468
statuse.c 535
[root@localhost work]# ll english.txt
-rwxrwxrwx. 1 root root 109055 Mar 19 10:30 english.txt
//运用stat函数实现ls –l 命令的功能
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>
int main(int argc, char* argv[])
{
if(argc < 2)
int main(int argc, char* argv[])
{
if(argc < 2)
{
printf("./a.out filename\n");
exit(1);
}
struct stat st;
int ret = stat(argv[1], &st);
if(ret == -1)
{
perror("stat");
exit(1);
}
// 存储文件类型和访问权限
char perms[11] = {0};
// 判断文件类型
switch(st.st_mode & S_IFMT)
{
case S_IFLNK:
perms[0] = 'l';
break;
case S_IFDIR:
perms[0] = 'd';
break;
case S_IFREG:
perms[0] = '-';
break;
case S_IFBLK:
perms[0] = 'b';
break;
case S_IFCHR:
perms[0] = 'c';
break;
case S_IFSOCK:
perms[0] = 's';
break;
case S_IFIFO:
perms[0] = 'p';
break;
default:
perms[0] = '?';
break;
}
// 判断文件的访问权限
// 文件所有者
perms[1] = (st.st_mode & S_IRUSR) ? 'r' : '-';
perms[2] = (st.st_mode & S_IWUSR) ? 'w' : '-';
perms[3] = (st.st_mode & S_IXUSR) ? 'x' : '-';
// 文件所属组
perms[4] = (st.st_mode & S_IRGRP) ? 'r' : '-';
perms[5] = (st.st_mode & S_IWGRP) ? 'w' : '-';
perms[6] = (st.st_mode & S_IXGRP) ? 'x' : '-';
// 其他人
perms[7] = (st.st_mode & S_IROTH) ? 'r' : '-';
perms[8] = (st.st_mode & S_IWOTH) ? 'w' : '-';
perms[9] = (st.st_mode & S_IXOTH) ? 'x' : '-';
// 硬链接计数
int linkNum = st.st_nlink;
// 文件所有者
char* fileUser = getpwuid(st.st_uid)->pw_name;
// 文件所属组
char* fileGrp = getgrgid(st.st_gid)->gr_name;
// 文件大小
int fileSize = (int)st.st_size;
// 修改时间
char* time = ctime(&st.st_mtime);
char mtime[512] = {0};
strncpy(mtime, time, strlen(time)-1);
char buf[1024];
sprintf(buf, "%s %d %s %s %d %s %s", perms, linkNum, fileUser, fileGrp, fileSize, mtime, argv[1]);
printf("%s\n", buf);
return 0;
}
————————————————
版权声明:本文为CSDN博主「luciusvorenus」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_33883085/article/details/88695946