获取文件属性 stat() fstat() lstat()

1 概述

1)linux系统下,一切皆文件,共有7种类型:普通文件、目录文件、管道文件、可执行文件、压缩文件、设备文件(字符、管道和块)和其他文件。
2) linux下通过ls命令查询文件信息,可通过stat相关函数查询出来或stat + 文件名命令

2 函数声明

  1. int stat(const char *path, struct stat *buf);
    • 入参*path: 文件的路径
    • 出参*buf: 文件信息
    • 返回值: 0 - 成功,-1 - 失败
  2. int fstat(int fd, struct stat *buf);
    • 入参fd: 文件描述符
    • 出参*buf: 文件信息
    • 返回值: 0 - 成功,-1 - 失败
  3. int lstat(const char *path, struct stat *buf);
    • 入参*path: 文件的路径
    • 出参*buf: 文件信息
    • 返回值: 0 - 成功,-1 - 失败

说明

  • 执行失败时,error有如下定义:
    EBADF: 文件描述词无效
    EFAULT:地址空间不可访问
    ELOOP:遍历路径时遇到太多的符号连接
    ENAMETOOLONG:文件路径名太长
    ENOENT:路径名的部分组件不存在或路径名是空字符串
    ENOMEM:内存不足
    ENOTDIR:路径名的部分组件不是目录
  • stat和lstat通过文件路径和文件名访问文件, fstat是通过文件描述符获取文件属性
  • 文件本身没有权限限制,文件的上层目录必须有访问权限才能获取到文件属性
  • 文件是符号链接时,lstat返回的是该符号链接本身的信息,而stat返回的是该符号链接指向的文件的信息

3 stat结构体

执行man 2 stat查询结构体定义

struct stat {
               dev_t     st_dev;         /* ID of device containing file */
               ino_t     st_ino;         /* inode number */
               mode_t    st_mode;        /* protection 文件的类型和权限*/  
               nlink_t   st_nlink;       /* number of hard links */
               uid_t     st_uid;         /* user ID of owner */
               gid_t     st_gid;         /* group ID of owner */
               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 512B blocks allocated */

               /* Since Linux 2.6, the kernel supports nanosecond
                  precision for the following timestamp fields.
                  For the details before Linux 2.6, see NOTES. */

               struct timespec st_atim;  /* time of last access */
               struct timespec st_mtim;  /* time of last modification */
               struct timespec st_ctim;  /* time of last status change */

           #define st_atime st_atim.tv_sec      /* Backward compatibility */
           #define st_mtime st_mtim.tv_sec
           #define st_ctime st_ctim.tv_sec
           };

mode_t st_mode 为16位的short类型,对应的16位标志位
在这里插入图片描述通过与S_IFMT掩码,可获取文件类型

S_IFMT 0170000 //掩码,过滤st_mode中除文件类型以外的信息
S_IFSOCK 0140000 //套接字
S_IFLNK 0120000 //符号链接(软链接)
S_IFREG 0100000 //普通文件
S_IFBLK 0060000 //块设备
S_IFDIR 0040000 //目录文件
S_IFCHR 0020000 //字符设备
S_IFIFO 0010000 //管道
S_ISUID 0004000 //设置用户ID
S_ISGID 0002000 //设置组ID
S_ISVTX 0001000 //粘住位
S_IRWXU 00700 //掩码,过滤st_mode除文件所有者权限以外的信息
S_IRUSR 00400 //用户读权限
S_IWUSR 00200 //用户写权限
S_IXUSR 00100 //用户执行权限
S_IRWXG 00070 //掩码,过滤st_mode除所属组权限以外的信息
S_IRGRP 00040 //读权限
S_IWGRP 00020 //写权限
S_IXGRP 00010 //执行权限
S_IRWXO 00007 //掩码,过滤st_mode除其他人权限以外的信息
S_IROTH 00004 //读权限
S_IWOTH 00002 //写权限
S_IXOTH 00001 //执行权限

4 代码示例

示例1:

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

void test_stat()
{
	struct stat st;
	int ret = -1;

	ret = stat("test_basic.c", &st);
	if(-1 == ret)
	{
		perror("stat fail.\n");
		return;
	}

	printf("file size: %lld.\n", (long long)st.st_size);
	printf("file device: %ld.\n", (long)st.st_dev);
	printf("file blocks: %lld.\n", (long long)st.st_blocks);
	printf("file node: %ld.\n", (long)st.st_ino);
	printf("file hardlink: %ld.\n", (long)st.st_nlink);
	printf("file user id: %ld.\n", (long)st.st_uid);
	printf("file group id: %ld.\n", (long)st.st_gid);

	return;
}
int main(int argc, char *argv[])
{
	test_stat();
	
	return 0;
}

gcc test_basic.c -o test_basic 编译
运行结果:
在这里插入图片描述示例2:

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

void test_stat02(int argc, char *argv[])
{
	struct stat sb;

	if (argc != 2) {
		fprintf(stderr, "Usage: %s <pathname>\n", argv[0]);
		exit(EXIT_FAILURE);
	}

	if (stat(argv[1], &sb) == -1) {
		perror("stat");
		exit(EXIT_FAILURE);
	}

	printf("File type:		");

	switch (sb.st_mode & S_IFMT)
	{
		case S_IFBLK: 	
			printf("block device\n");
			break;
		case S_IFCHR: 	
			printf("character device\n");
			break;
		case S_IFDIR: 	
			printf("directory\n");
			break;
		case S_IFIFO: 	
			printf("FIFO/pipe\n");
			break;
		case S_IFLNK: 	
			printf("symlink\n");
			break;
		case S_IFREG: 	
			printf("regular file\n");
			break;
		case S_IFSOCK: 	
			printf("socket\n");
			break;
		default:		
			printf("unknown?\n");
			break;
	}

	printf("I-node number:	%ld\n", (long)sb.st_ino);
	printf("Mode:			%lo (octal)\n", (unsigned long)sb.st_mode);
	printf("Link count:		%ld\n", (long)sb.st_nlink);
	printf("Ownership:		UID=%ld  GID=%ld\n", (long)sb.st_uid, (long)sb.st_gid);
	printf("Preferred I/O block size: %ld bytes\n", (long)sb.st_blksize);
	printf("File size:		%lld bytes\n", (long long)sb.st_size);
	printf("Blocks allocated:	%lld\n", (long long) sb.st_blocks);
	printf("Last status change:			%s", ctime(&sb.st_ctime));
	printf("Last file access: 			%s", ctime(&sb.st_atime));
	printf("Last file modification:		%s", ctime(&sb.st_mtime));
	
	exit(EXIT_SUCCESS);
}

int main(int argc, char *argv[])
{
	//test_stat();
	test_stat02(argc, argv);
	
	return 0;
}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值