一、读取文件元数据
int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);
stat() stats the file pointed to by path and fills in buf.
lstat() is identical to stat(), except that if path is a symbolic link, then the link itself is stat-ed, not the file that it refers to.
fstat() is identical to stat(), except that the file to be stat-ed is specified by the file descriptor fd.
二、stat结构体
struct stat ;
示例程序:
/*************************************************************************
> File Name: file_stat.c
> Author: Simba
> Mail: dameng34@163.com
> Created Time: Sat 23 Feb 2013 02:34:02 PM CST
************************************************************************/
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#define ERR_EXIT(m)
do {
perror(m);
exit(EXIT_FAILURE);
} while(0)
#define MAJOR(a) (int)((unsigned short)a >> 8) // 高8位,主设备号
#define MINOR(a) (int)((unsigned short)a & 0xFF)
int filetype(struct stat *buf)
{
int flag = 0;
printf("Filetype:");
mode_t mode;
mode = buf->st_mode;
switch (mode & S_IFMT)
{
case S_IFSOCK:
printf("socket
");
break;
case S_IFLNK:
printf("symbolic link
");
break;
case S_IFREG:
printf("regular file
");
break;
case S_IFBLK:
printf("block device
");
flag = 1;
break;
case S_IFDIR:
printf("directory
");
break;
case S_IFCHR:
printf("character device
");
flag = 1;
break;
case S_IFIFO:
printf("FIFO
");
break;
default:
printf("unknown file type
");
break;
}
return flag;
}
void fileperm(struct stat *buf, char perm[])
{
strcpy(perm, "----------");
perm[0] = '?';
mode_t mode;
mode = buf->st_mode;
switch (mode & S_IFMT)
{
case S_IFSOCK:
perm[0] = 's';
break;
case S_IFLNK:
perm[0] = 'l';
break;
case S_IFREG:
perm[0] = '-';
break;
case S_IFBLK:
perm[0] = 'b';
break;
case S_IFDIR:
perm[0] = 'd';
break;
case S_IFCHR:
perm[0] = 'c';
break;
case S_IFIFO:
perm[0] = 'p';
break;
}
if (mode & S_IRUSR)
perm[1] = 'r';
if (mode & S_IWUSR)
perm[2] = 'w';
if (mode & S_IXUSR)
perm[3] = 'x';
if (mode & S_IRGRP)
perm[4] = 'r';
if (mode & S_IWGRP)
perm[5] = 'w';
if (mode & S_IXGRP)
perm[6] = 'x';
if (mode & S_IROTH)
perm[7] = 'r';
if (mode & S_IWOTH)
perm[8] = 'w';
if (mode & S_IXOTH)
perm[9] = 'x';
perm[10] = '0';
}
int main(int argc, char *argv[])
printf("Filename:%s
", argv[1]);
struct stat sbuf;
if (lstat(argv[1], &sbuf) == -1)
ERR_EXIT("stat error");
printf("file in Dev number:major %d, minor %d
",
MAJOR(sbuf.st_dev), MINOR(sbuf.st_dev));
printf("File inode:%d
", (int) sbuf.st_ino);
if (filetype(&sbuf))
{
printf("Device number:major %d, minor %d
",
MAJOR(sbuf.st_rdev), MINOR(sbuf.st_rdev));
}
char perm[11] = {0};
fileperm(&sbuf, perm);
printf("File permission bits=%o %s
", sbuf.st_mode & 0777, perm); // 0777 是八进制数
return 0;
}
测试如下:
simba@ubuntu:~/Documents/code/linux_programming/APUE/File_IO$ ./file_stat Makefile
Filename:Makefile
file in Dev number:major 8, minor 1
File inode:660022
Filetype:regular file
File permission bits=664 -rw-rw-r--
因为是普通文件,故从st_dev字段看设备号,而不是st_rdev. 主设备号表示设备驱动程序,而次设备号表示特定的子设备。比如在同一个磁盘上面不同的文件系统,设备驱动程序相当,但是次设备号不同。
st_rdev只有字符特殊文件和块特殊文件才有这个值,表示实际设备的设备编号。
$ ./a.out / /home/sar /dev/tty[01]
/: dev = 3/3
/home/sar: dev = 3/4
/dev/tty0: dev = 0/7 (character) rdev = 4/0
/dev/tty1: dev = 0/7 (character) rdev = 4/1
$ mount which directories are mounted on which devices?
/dev/hda3 on / type ext2 (rw,noatime)
/dev/hda4 on /home type ext2 (rw,noatime)
$ ls -lL /dev/tty[01] /dev/hda[34]
brw------- 1 root 3, 3 Dec 31 1969 /dev/hda3
brw------- 1 root 3, 4 Dec 31 1969 /dev/hda4
crw------- 1 root 4, 0 Dec 31 1969 /dev/tty0
crw------- 1 root 4, 1 Jan 18 15:36 /dev/tty1
Note that the filenames and i-nodes for the two terminal devices (st_dev) are on device 0/7 the devfs pseudo file system, which implements the /dev but that their actual device numbers are 4/0 and 4/1.