最近兩天學習了有關檔案屬性的擷取和操作,下面是在學習過程中的一個例程。
Linux中有關檔案屬性的資訊存儲在struct 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 file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
我們可以通過系統API stat()擷取檔案的該結構體。例程中,我主要解析了st_mode這一結構體元素,該元素存儲了有關檔案類型和權限的資訊。
類型和權限都是通過位标志進行存儲和識别的:
S_IFMT 0170000 bit mask for the file type bit fields
S_IFSOCK 0140000 socket
S_IFLNK 0120000 symbolic link
S_IFREG 0100000 regular file
S_IFBLK 0060000 block device
S_IFDIR 0040000 directory
S_IFCHR 0020000 character device
S_IFIFO 0010000 FIFO
S_ISUID 0004000 set UID bit
S_ISGID 0002000 set-group-ID bit (see below)
S_ISVTX 0001000 sticky bit (see below)
S_IRWXU 00700 mask for file owner permissions
S_IRUSR 00400 owner has read permission
S_IWUSR 00200 owner has write permission
S_IXUSR 00100 owner has execute permission
S_IRWXG 00070 mask for group permissions
S_IRGRP 00040 group has read permission
S_IWGRP 00020 group has write permission
S_IXGRP 00010 group has execute permission
S_IRWXO 00007 mask for permissions for others (not in group)
S_IROTH 00004 others have read permission
S_IWOTH 00002 others have write permission
S_IXOTH 00001 others have execute permission
可以看到,檔案類型和權限由不同的掩碼進行控制,特定的類型和權限都對應不同的位,可以通過比對位辨別識别某一檔案的類型或是權限。
另外,檔案類型除了用上述的方法進行識别外,linux中還提供了專門的帶參宏定義,通過這些宏定義可以更加友善的識别檔案類型:
S_ISREG(m) is it a regular file?
S_ISDIR(m) directory?
S_ISCHR(m) character device?
S_ISBLK(m) block device?
S_ISFIFO(m) FIFO (named pipe)?
S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.)
S_ISSOCK(m) socket? (Not in POSIX.1-1996.)
m就是st_mode元素。這種方法在例程中也有使用。
例程如下:
#include<stdio.h>
#include<string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc,char *argv[])
{
int ret = -1;
struct stat buf;
memset(&buf,0,sizeof(struct stat));
ret = stat(argv[1],&buf);//擷取結構體struct stat的資訊
if(ret < 0)
{
perror("open");
exit(-1);
}
printf("ino_t:%d\n",buf.st_ino);//列印inode
if(1 == S_ISREG(buf.st_mode))//identify file types using macros,用帶參宏定義判斷檔案類型
{
printf("%s is a regular file\n",argv[1]);
}
printf("S_ISLNK(buf.st_mode) is:%d\n",S_ISLNK(buf.st_mode));
if(1 == S_ISLNK(buf.st_mode))//can't pass the test,判斷符号連結檔案,但在測試的時候沒有判斷出來
{
printf("%s is a symbolic link\n",argv[1]);
}
printf("S_IFREG:%d,buf.st_mode:%d\n",S_IFREG,buf.st_mode);//列印st_mode資訊
switch(S_IFMT & buf.st_mode)//用掩碼和位标志判斷檔案類型
{
case S_IFREG:printf("%s is a regular file\n",argv[1]);break;
case S_IFDIR:printf("%s is a directory\n",argv[1]);break;
case S_IFSOCK:printf("%s is a socket file\n",argv[1]);break;
case S_IFLNK:printf("%s is a link file\n",argv[1]);break;
case S_IFBLK:printf("%s is a block device file\n",argv[1]);break;
case S_IFCHR:printf("%s is a character device file\n",argv[1]);break;
case S_IFIFO:printf("%s is a FIFO/pipe file\n",argv[1]);break;
default:printf("can't identify\n");
}
switch(S_IRWXU & buf.st_mode)//用位标志判斷檔案權限
{
case S_IRUSR|S_IWUSR|S_IXUSR:printf("owner of %s has rwx permission \n",argv[1]);break;
case S_IWUSR:printf("owner of %s has w permission\n",argv[1]);break;
case S_IXUSR:printf("owner of %s has x permission\n",argv[1]);break;
case S_IRUSR:printf("owner of %s has r permission \n",argv[1]);break;
case S_IWUSR|S_IXUSR:printf("owner of %s has wx permission \n",argv[1]);break;
case S_IRUSR|S_IXUSR:printf("owner of %s has rx permission \n",argv[1]);break;
case S_IRUSR|S_IWUSR:printf("owner of %s has rw permission \n",argv[1]);break;
default:printf("owner of %s has no permission\n");
}
return 0;
}
權限識别隻是識别了檔案屬主對檔案的操作權限,其它的組權限和其他權限如法炮制。由于權限是w r x的組合,而檔案類型的位辨別是單獨的,是以兩者在判斷的時候略有不同。
測試時候的一個發現:有關符号連結檔案(軟連接配接檔案)本身都是rwx屬性,而且用chmod指令修改權限也是無效的。但其st_mode代表的則是所連結的檔案的權限。換句話說符号連接配接檔案本身都是可讀可寫可執行的,但其st_mode則和源檔案保持一緻。
測試發現的一個問題:符号連結檔案被當作了普通檔案,帶參宏定義和位标志都無法正确識别符号連接配接檔案。