#include <sys/stat.h>
#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指向的結構。該結構的實際定義可能所實施而有所不同,但其基本形式是:
struct stat{
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_ISREG(buf.st_mode)
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 <stdio.h>
#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");
}