UNIX环境高级编程-第4章-4.1~4.3
2016-06-06 23:14
435 查看
4.1 引言
从stat开始,逐个说明stat结构的每一个成员以了解文件的所有属性=> 说明修改文件属性的各个函数=> 说明UNIX文件系统的结构以及符号链接=> 介绍对目录操作的各个函数。
4.2 函数stat,fstat,lstat,fstatat
#include<sys/types.h> #include<sys/stat.h> #include<unistd.h> int stat(const char*pathname,struct stat*buf); int fstat(int fd,struct stat*buf); int lstat(const char*pathname,struct stat*buf); #include<fcntl.h> #include<sys/stat.h> int fstatat(int dirfd,const char*pathname,struct stat*buf,int flags);
这些函数返回一个文件的文件信息并写入到buf中。使用以上函数测试文件的属性的时候并不要求进程对该文件的权限,只要求进程对包含该文件的各级目录具有执行权限,即能够在该目录下面搜索该文件。
stat和fstatat检索pathname指定的文件的文件属性,他们的不同点在于:
lstat 和stat一样,除了lstat不会跟踪符号链接而是返回符号链接本身的信息。
fstat和stat是一样的,也会跟踪符号链接,只不过fstat是检索fd指定的文件的文件属性。
所有的这些函数都使用到了一个struct stat结构,其定义如下: struct stat{ dev_t st_dev;//包含该文件的设备 ino_t st_ino;//该文件的inode节点编号 mode_t st_mode;//文件权限 nlink_t st_nlink;//硬链接数量 uid_t st_uid;//属主ID gid_t st_gid;//属组ID dev_t st_rdev;//特殊文件的设备ID编号 off_t st_size;//占用字节数 blksize_t st_blksize;//占用文件系统块数目 blkcnt_t st_blocks;//分配的512B大小块的数量 //从Linux2.6开始,内核对以下时间戳字典支持纳秒级别的精度 struct timespec st_atim;//最后访问时间 struct timespec st_mtim;//最后修改时间 struct timespec st_ctim;//属性最后改变时间 //后向兼容 #define st_atime st_atim.tv_sec #define st_mtime st_mtim.tv_sec #define st_ctime st_ctim.tv_sec };
st_atime 会因为文件访问而被改变,比如execve,mknod,pipe,utime,read等的操作,其他的操作如nmap,既有可能会,也可能不改变st_atime字段。
st_mtime 会因为文件修改而被改变,比如mknod,truncate,utime,和write。此外,目录的st_mtime会因为对目录里面文件的创建和删除而改变。如果是文件属主,属组,硬链接数量,mode权限的改变并不会影响该文件的st_mtime。
st_ctime 会因为被write或者inode节点被改变和改变。
下列掩码的值是为st_mode而设置的: S_IFMT 0170000 文件类型位掩码,可以使用st_mode与其进行&运算并和下列宏进行比较 S_IFSOCK 0140000 socket类型 S_IFLNK 0120000 符号链接 S_IFREG 0100000 普通文件 S_IFBLK 0060000 块设备 S_IFDIR 0040000 目录 S_IFCHR 0020000 字符设备 S_IFIFO 0010000 FIFO 因为对文件类型的测试是普遍存在的,因此POSIX标准提供了针对st_mode字段的测试的宏定义: S_ISREG(m) 测试是否是普通文件 S_ISDIR(m) 测试是否是目录 S_ISCHR(m) 是否是字符设备 S_ISBLK(m) 是否是块设备 S_ISFIFO(m) 是否时FIFO队列 S_ISLINK(m) 是否是符号链接 S_ISSOCK(m) 是否是套接字 以下掩码值是为st_mode定义的,st_mode是这些所有值的位或|: S_ISUID 0004000 设置用户ID位 S_ISGID 0002000 设置组ID位 S_ISVTX 0001000 粘连位 S_IRWXU 00700 文件属主字段掩码 S_IRUSR 00400 属主具有读权限 S_IWUSR 00200 属主具有写权限 S_IXUSR 00100 属主具有执行权限 S_IRWXG 00070 属组权限掩码 S_IRGRP 00040 属组具有读权限 S_IWGRP 00020 属组具有写权限 S_IXGRP 00010 属组具有执行权限 S_IRWXO 00007 非属组用户权限掩码 S_IROTH 00004 其他用户具有读权限 S_IWOTH 00002 其他用户具有写权限 S_IXOTH 00001 其他用户具有执行权限 S_ISGID位有几个特殊的用处,对于一个目录,这意味着一个BSD语义被用在了该目录上:在该目录中创建的的属组ID继承了目录的属组ID,而不是来自于创建该文件的有效组ID,并且在该目录中创建的目录也会具有S_ISGID位被设置为1,对于一个没有设置属组执行权限的文件,那么S_ISGID位表示mandatory file/record locking。 粘连位S_ISVTX表示目录中的文件只能被文件属主,目录属主或具有权限的进程重命名和删除。 fstatat和stat的区别在于: 如果pathname是相对路径,那么它是相对于dirfd表示的目录而言的。 如果dirfd=AT_FDCWD,那么pathname相对路径是相对于当前工作目录而言的。 如果pathname是绝对路径,那么dirfd将会被忽略。 flags要么是0,要么被设置成为以下值: AT_EMPTY_PATH: 如果pathname为空,fstatat将会操作dirfd指定的文件,如果dirfd=AT_FDCWD,将会处理当前工作目录,在这种情况下,dirfd将可以指向任何文件,并不仅仅是一个目录,该标志是linux特有的,如果定义了_GNU_SOURCE讲可以获取该定义。 AT_NO_AMOUNT: 该标志是Linux特有。 AT_SYMLINK_NOFOLLOW: 如果pathname是一个符号链接,不跟随该符号链接而是项lstat一样返回符号链接本身的属性。 如果成功调用返回0,否则返回-1,全局变量errno将会被设置。
//编写一个程序,对于每一个文件输出其i节点编号,硬链接数量,属主id,属组gid,字节数,占用文件系统磁盘块数量,占用512块数量和文件权限和文件类型
#include<sys/types.h> #include<sys/stat.h> #include<unistd.h> #include<stdio.h> #include<stdlib.h> #include<string.h> int main(int argc,char**argv){ if(argc<2){ printf("用法: a.out 文件或者目录路径名称\n"); exit(0); } struct stat st; int i=1; for(i=1;i<argc;i++){ if(stat(argv[i],&st)<0){ perror(strcat(strcat("获取文件",argv[i]),"的属性失败\n")); exit(0); } printf("文件%s的信息如下:\n--------------------\n",argv[i]); printf("i节点编号:%ld\n",st.st_ino); printf("硬链接数量:%ld\n",st.st_nlink); printf("属主id:%ld\n",st.st_uid); printf("属组id:%ld\n",st.st_gid); printf("文件占用字节数量:%ld\n",st.st_size); printf("文件占用磁盘数量:%ld\n",st.st_blksize); printf("文件占用512字节块数量:%ld\n",st.st_blocks); if(S_ISREG(st.st_mode)){ printf("该文件是一个普通文件\n"); }else if(S_ISDIR(st.st_mode)){ printf("该文件是一个目录\n"); }else if(S_ISCHR(st.st_mode)){ printf("该文件是一个字符设备\n"); }else if(S_ISBLK(st.st_mode)){ printf("该文件是一个块设备\n"); }else if(S_ISFIFO(st.st_mode)){ printf("该文件是一个FIFO队列\n"); }else if(S_ISLNK(st.st_mode)){ printf("该文件是一个符号链接\n"); }else if(S_ISSOCK(st.st_mode)){ printf("该文件是一个套接字\n"); }else{ printf("该文件类型未知\n"); } if(st.st_mode&S_ISUID){ printf("该文件的用户ID位被设置\n"); } if(st.st_mode&S_ISGID){ printf("该文件的组IID位被设置\n"); } if(st.st_mode&S_IRWXU&S_IRUSR){ printf("该文件属主可读\n"); } } return 0; }
//测试结果如下
xcl@xcl:~/桌面$ ./main / /etc /home /home/xcl /home/xcl/桌面\
/home/xcl/桌面/有用的文件1
文件/的信息如下:
i节点编号:2硬链接数量:24
属主id:0
属组id:0
文件占用字节数量:4096
文件占用磁盘数量:4096
文件占用512字节块数量:8
该文件是一个目录
该文件属主可读
文件/etc的信息如下:
i节点编号:11665409硬链接数量:160
属主id:0
属组id:0
文件占用字节数量:12288
文件占用磁盘数量:4096
文件占用512字节块数量:24
该文件是一个目录
该文件属主可读
文件/home的信息如下:
i节点编号:26476545硬链接数量:4
属主id:0
属组id:0
文件占用字节数量:4096
文件占用磁盘数量:4096
文件占用512字节块数量:8
该文件是一个目录
该文件属主可读
文件/home/xcl的信息如下:
i节点编号:26476552硬链接数量:67
属主id:1000
属组id:1000
文件占用字节数量:20480
文件占用磁盘数量:4096
文件占用512字节块数量:48
该文件是一个目录
该文件属主可读
文件/home/xcl/桌面的信息如下:
i节点编号:26476570硬链接数量:5
属主id:1000
属组id:1000
文件占用字节数量:16384
文件占用磁盘数量:4096
文件占用512字节块数量:32
该文件是一个目录
该文件属主可读
文件/home/xcl/桌面/有用的文件1的信息如下:
i节点编号:26491698硬链接数量:1
属主id:1000
属组id:1000
文件占用字节数量:19060
文件占用磁盘数量:4096
文件占用512字节块数量:56
该文件是一个普通文件
该文件属主可读
相关文章推荐
- Unix 即将迎来 50 岁
- Linux VS Unix:Linux欲一统天下 Unix不死
- 命令行小技巧:读取文件的不同方式
- IE:临时文件保存法
- 文件的读出 编辑 管理
- 文件遍历排序函数
- 在线用表单建立文件夹
- VB获取文件大小的方法
- 文件、目录,文本文件等多种操作类
- 处理驱动器和文件夹
- 用vbs删除某些类型文件和磁盘空间报告的脚本
- Windows7下获得System权限问题解决方法
- 可折叠展开的简单目录实现代码
- 路由器安全有关的目录
- Ruby实现批量对文件增加前缀代码分享
- 用一整天的时间安装postgreSQL NTFS权限
- C#获取文件夹及文件的大小与占用空间的方法
- delphi制作wav文件的方法
- PowerShell移动目录中指定文件的方法(非全部文件)