引言:
在Linux中使用ls -l filename命令查看filename的属性时,会列出文件的9种属性,例如:ls -l /etc/fstab
-rw-r--r-- 1 root root 1102 2013-10-12 02:33 /etc/fstab
以上这些文件属性的信息,都存放在一个stat的结构体中。下面就来分析一下这个结构体。
要想查看一个文件的stat结构体,可以通过stat类函数获得!
       #include <sys/types.h>
       #include <sys/stat.h>
       #include <unistd.h>
       int stat(const char *path, struct stat *buf); //stat函数就返回此path所指命令文件有关的信息。
       int fstat(int fd, struct stat *buf); 
//fstat函数获取已在文件描述符fd上打开的有关信息。
       int lstat(const char *path, struct stat *buf);//lstat函数类似于stat,当命名文件是一个符号链接时,lstat返回该符号链接的有关信息,而不是由该符号链接引用文件的信息。
以上三个函数,若成功则返回0, 若出错则返回-1。以上三个函数填写有buf指向的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 */
           };
(一)
文件类型,对应stat结构中的st_mode成员,包括普通文件、目录文件、块特殊文件、字符特殊文件、FIFO(命名管道)、套接字、符号链接7种文件。文件类型信息包含在stat结构的st_mode成员中。一般用下表中的宏确定文件类型,这些宏的参数都是stat结构中的st_mode成员。
| 宏 | 文件类型 | 
| S_ISREG() | 普通文件 | 
| S_ISDIR() | 目录文件 | 
| S_ISCHR() | 字符特殊文件 | 
| S_ISBLK() | 块特殊文件 | 
| S_ISFIFO() | 管道或FIFO | 
| S_ISLNK() | 符号链接 | 
| S_ISSOCK() | 套接字 | 
以宏S_ISREG()为例,说明上述各宏在<sys/stat.h>中是如何定义的
# define S_IFMT __S_IFMT #define S_ISREG(mode) __S_ISTYPE((mode), __S_IFREG) #define __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask))示例程序:
/*
 *File Name : typedemo.c
 *Author    : libing
 *Mail      : libing1209@126.com
 *Function  : test the file type you input 
 */
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
	int 		  i;
	struct stat buf;
	char 	   *ptr;
	for(i = 1; i < argc; i++){
		printf("%s:", argv[i]);
		if(lstat(argv[i], &buf) < 0){//获得stat结构体
			printf("lstat error.\n");	
			continue;
		}
		//利用宏测试各种文件类型
		if(S_ISREG(buf.st_mode))
			printf("regular");
		if(S_ISDIR(buf.st_mode))
			printf("directory");
		if(S_ISCHR(buf.st_mode))
			printf("character special");
		if(S_ISBLK(buf.st_mode))
			printf("block special");
		if(S_ISFIFO(buf.st_mode))
			printf("fifo");
		if(S_ISLNK(buf.st_mode))
			printf("symbolic link");
		if(S_ISSOCK(buf.st_mode))
			printf("sock");
		putchar(‘\n‘);
	}
	exit(0);
}程序测试结果:
编译程序: gcc typedemo.c 执行程序: ./a.out /etc/fstab 结果显示: /etc/fstab regular
设置用户ID和设置组ID:与一个进程相关的ID有6个,列表如下:
| 实际用户ID 我们实际是谁 实际组ID | 
| 有效用户ID 用于文件访问 有效组ID 权限检查 附加组ID | 
| 保存的设置用户ID 由exec函数 保存的设置组ID 保存 | 
文件访问权限,不只是普通文件,所有文件类型都有访问权限。每个文件有9个访问权限,如下表1:
| st_mode屏蔽 | 意义 | 
| S_IRUSR S_IWUSR S_IXUSR | 用户-读 用户-写 用户-执行 | 
| S_IRGRP S_IWGRP S_IXGRP | 组-读 组-写 组-执行 | 
| S_IROTH S_IWOTH S_IXOTH | 其他-读 其他-写 其他-执行 | 
/*
 * File Name : permdemo.c
 * Author    : libing
 * Mail      : libing1209@126.com
 * Function  : test the file permation you input
 */
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
int 
main(int argc, char *argv[])
{
	if(argc != 2){
		printf("usage : %s filename.\n", argv[0]);	
		exit(0);
	}	
	printf("FileName : %s.\n", argv[1]);
	struct stat buf;
	if(lstat(argv[1], &buf) == -1){
		printf("stat error.\n");	
		exit(0);
	}
	char perm[9] = {0};
	strcpy(perm, "---------");
	mode_t mode = buf.st_mode;
	if(mode & S_IRUSR) perm[0] = ‘r‘;
	if(mode & S_IWUSR) perm[1] = ‘w‘;
	if(mode & S_IXUSR) perm[2] = ‘x‘;
	if(mode & S_IRGRP) perm[3] = ‘r‘;
	if(mode & S_IWGRP) perm[4] = ‘w‘;
	if(mode & S_IXGRP) perm[5] = ‘x‘;
	if(mode & S_IROTH) perm[6] = ‘r‘;
	if(mode & S_IWOTH) perm[7] = ‘w‘;
	if(mode & S_IXOTH) perm[8] = ‘x‘;
	printf("File permission bits = %s.\n", perm);
	
}编译程序测试:
编译程序: gcc permdemo.c 执行程序: ./a.out /etc/fstab 显示结果: FileName : /etc/fstab. File permission bits = rw-r--r--.
(四)
新文件和目录的所有权:新文件的用户ID设置为进程的有效用户ID。新文件的组ID可以是进程的有效组ID,也可以是它所在目录的组ID。
(五)
access函数时按实际用户ID和实际组ID进行访问权限测试的。注意与(三)中的有效用户ID访问权限测试做比较。
       #include <unistd.h>
       int access(const char *pathname, int mode);   // 若成功则返回0, 若出错则返回-1。
参数mode定义在<unistd.h>文件中,如下表2:
| mode | 说明 | 
| R_OK W_OK X_OK F_OK | 测试读权限 测试写权限 测试执行权限 测试文件是否存在 | 
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
	if(argc != 2)
			printf("usage: a.out pathname");
	if(access(argv[1], R_OK) < 0)
			printf("access error for %s", argv[1]);
	else
			printf("read ok.\n");
	if(open(argv[1], O_RDONLY) < 0)
			printf("open error for %s", argv[1]);
	else
			printf("open for reading OK\n");
	exit(0);
}程序测试:
编译程序: gcc access.c 执行程序: ./a.out /etc/fstab 显示结果: read ok. open for reading OK(六)
umask函数为进程设置文件模式创建屏蔽字,并返回以前的值。
       #include <sys/types.h>
       #include <sys/stat.h>
       mode_t umask(mode_t mask);   // 返回以前的文件模式创建屏蔽字
参数cmask是由上面的表1列出的9个常量中的若干个按位“或”构成的。对于任何在文件模式创建屏蔽字中为1的位,在文件mode中的相应位一定被关闭。
示例程序:
/*
 *File Name : umaskdemo.c
 *Author    : libing
 *Mail      : libing1209@126.com
 *Function  : just the umask function
 */
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#define RWRWRW (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
int
main(void)
{
	umask(0);   //设置文件模式创建屏蔽字
	if(creat("foo", RWRWRW) < 0)
		printf("create foo  error.\n");
	umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);  //设置文件模式创建屏蔽字
	if(creat("far", RWRWRW) < 0)
		printf("create far error.\n");
	exit(0);
}程序测试显示 :
编译程序: gcc umask.c 执行程序: ./a.out 测试显示: ls -l far foo -rw------- 1 book book 0 2014-05-12 20:40 far -rw-rw-rw- 1 book book 0 2014-05-12 20:40 foo
chmod函数与fchmod函数可以更改现有文件的访问权限。chmod 函数在指定的文件上进行操作,而fchmod函数则对已打开的文件进行操作。
       #include <sys/stat.h>
       int chmod(const char *path, mode_t mode);
       int fchmod(int fd, mode_t mode);
另外:stat结构体中的st_size成员表示以字节为单位的文件长度。
Linux环境编程之文件I/O(六):文件属性,布布扣,bubuko.com
原文:http://blog.csdn.net/to_be_it_1/article/details/25552557