#include<types.h>
int stat(const char*pathname, struct stat *buf);
int fstat(int filedes, struct stat *buf);
int lstat(const char *pathname, struct stat *buf);
参数说明:
pathname 带路径的文件名
buf 第二个参数是个指针,它指向一个我们应提供的结构
给 予一个pathname,stat函数返回一个与此命名文件有关的信息结构,fstat函数获得已在描述符filedes上打开的文件的有关信息。 lstat函数类似于stat,但是当命名的文件是一个符号连接时,lstat返回该符号连接的有关信息,而不是由该符号连接引用的文件的信息。 lstat函数不属于POSIX10031-1990标准,但很可能加到10031a中。SVR4和4.3+BSD支持lstat。
第二个参数是个指针,它指向一个我们应提供的结构。这些函数填写由buf指向的结构。该结构的实际定义可能所实施而有所不同,但其基本形式是:
mode st_mode; /*文件类型和方式(许可数)*/
ino st_ino; /* i-节点号(序列号)*/
dev st_dev; /*设备号(文件系统)*/
dev st_rdev; /*特殊文件的设备号*/
nlink st_nlink; /*连接数*/
uid st_uid; /*属主的用户ID*/
gid st_gid; /*属主的组ID*/
off st_size; /*普通文件的字节长度*/
time st_atime; /*最后存取时间*/
time st_mtime; /*最后修改存取时间*/
time st_ctime; /*最后文件状态更改时间*/
long st_blksize; /*最佳I/O块长*/
long st_blocks; /*分配的512字节块块数
};
POSIX.1未定义stdevstksige和stblocks字 段。SVR4和4.3+BSD则定义了这些字段。注意,除最后两个以外,其它各成员都为基本系统数据类型。我们将说明此结构的每个成员以了解文件属性。 stat函数的最大用户很可能是ls-l命令,用其可以获得有关一个文件的所有信息。
文件类型
至今我们已介绍了两种不同的文件类型--普通文件和目录。Unix系统的大多数文件是普通文件或目录,但是也有另外一些文件类型:
1.普通文件(Regular file)。[S_IFREG] 这是最常见的文件类型,这种文件包含了某种形式的数据。至于这种数据是文本还是二进制数据对于系统核而言并无区别。对普通文件内容的解释由处理该文件的应用程序进行。
2.目录文件(Directory file)。[S_IFDIR]这种文件包含了其它文件的名字以及指向与这些文件有关信息的指针。对一个目录文件具有读许可数的任一进程都可以读该目录的内容,但只有系统核可以写目录文件。
3.字符特殊文件(Charocter special file)。[S_IFCHR]这种文件用于系统中的某些类型的设备。
4.块特殊文件(Block special file)。[S_IFBLK]这种文件典型地用于磁盘设备。系统中的所有设备或者是字符特殊文件,或者是块特殊文件。
5.FIFO。[S_IFFIFO]这种文件用于进程间的通信,有时也将其称为命名管道。
6.套接口(socket)。[S_IFSOCK]这 种文件用于进程间的网络通信。套接口也可用于在一台宿主机上的进程之间的非网络通信。在第十五章,我们将用套接口进行进程间的通信。只有4.3+BSD才 返回套接口文件类型,虽然 SVR4支持用套接口进行进程间通信,但现在是经由套接口函数库实现的,而不是通过系统核内的套接口文件类型,将来的SVR4版本可能会支持套接口文件类 型。
7.符号连接(Symboliclink)。[S_IFLNK]这种文件指向另一个文件。
文件类型信息,包含在stat结构的stode成员中。我们可以用宏确定文件类型。这些宏的参数都是stat结构中的stode成员。
相关的宏判断如下:
S_ISBLK(buf.st_mode)
S_ISCHR(buf.st_mode)
S_ISDIR(buf.st_mode)
S_ISFIFO(buf.st_mode)
S_ISLNK(buf.st_mode)
S_ISSOCK(buf.st_mode)
以下实例为模拟ls –l命令的功能
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
////测试文件类型,并转化为UNIX标识方式
int GetFileType(mode_t st_mode, char *resp)
{
if (resp == NULL) return 0;
if (S_ISDIR(st_mode)) resp[0] = 'd'; /* 测试是否为目录文件 */
else if (S_ISCHR(st_mode)) resp[0]='c'; /* 测试是否为字符文件 */
else if (S_ISBLK(st_mode)) resp[0]='b'; /* 测试是否为块文件 */
else if (S_ISREG(st_mode)) resp[0]='-'; /* 测试是否为普通文件 */
else if (S_ISFIFO(st_mode)) resp[0]='p'; /* 测试是否为管道文件 */
else if (S_ISLNK(st_mode)) resp[0]='l'; /* 测试是否为符合链接 */
else resp[0] = ' ';
return 1;
}
////测试文件权限,并转化为UNIX标识方式
int GetFileMode(mode_t st_mode, char *resp)
{
if (resp == NULL) return 0;
memset(resp, '-', 9);
if (st_mode & S_IRUSR) resp[0] = 'r';
if (st_mode & S_IWUSR) resp[1] = 'w';
if (st_mode & S_IXUSR) resp[2] = 'x';
if (st_mode & S_IRGRP) resp[3] = 'r';
if (st_mode & S_IWGRP) resp[4] = 'w';
if (st_mode & S_IXGRP) resp[5] = 'x';
if (st_mode & S_IROTH) resp[6] = 'r';
if (st_mode & S_IWOTH) resp[7] = 'w';
if (st_mode & S_IXOTH) resp[8] = 'x';
return 9;
}
//////测试文件其它属性式
int GetFileOtherAttr(struct stat info, char *resp)
{
struct tm * mtime;
if (resp == NULL) return 0;
mtime = localtime(&info.st_mtime);
return (sprintf(resp, " %3d %6d %6d %11d %04d%02d%02d",
info.st_nlink, info.st_uid, info.st_gid, info.st_size,
mtime->tm_year+1900, mtime->tm_mon+1, mtime->tm_mday));
}
//////////////////主函数///////////
void main(int argc, char **argv)
{
struct stat info;
char buf[100], *p = buf;
if (argc != 2)
{
fprintf(stderr, "ls1 filename\n");
return ;
}
memset(buf, 0, sizeof(buf));
if (lstat(argv[1], &info) == 0)
{
p += GetFileType(info.st_mode, p);
p += GetFileMode(info.st_mode, p);
p += GetFileOtherAttr(info, p);
printf("%s %s\n", buf, argv[1]);
}
else fprintf(stderr, "open file failed.\n");
}