Unix编程之文件类型检测
来源:互联网 发布:电子线路画图软件 编辑:程序博客网 时间:2024/05/29 21:30
坚持 成长 每日一篇
stat结构体介绍
在unix系统中我们可以通过了解stat 结构体的成员了解文件的所有属性。结构体的定义可能随实现有所不同,但其基本形式是:下面是mac下的stat格式
struct stat { dev_t st_dev; /* 拥有该文件的设备ID[XSI] ID of device containing file */ ino_t st_ino; /* 文件结点号[XSI] File serial number */ mode_t st_mode; /* 文件的类型 Mode of file (see below) */ nlink_t st_nlink; /* 硬连接数 Number of hard links */ uid_t st_uid; /* 文件用户标识 User ID of the file */ gid_t st_gid; /* 文件用户组标识 Group ID of the file */ dev_t st_rdev; /* 文件所表示的特殊设备文件的设备标识 Device ID for sepecial files */#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) struct timespec st_atimespec; /* time of last access */ struct timespec st_mtimespec; /* time of last data modification */ struct timespec st_ctimespec; /* time of last status change */#else time_t st_atime; /* 最后的访问时间 Time of last access */ long st_atimensec; /* nsec of last access */ time_t st_mtime; /* 最后修改时间 Last data modification time */ long st_mtimensec; /* last data modification nsec */ time_t st_ctime; /* 最后状态改变时间 Time of last status change */ long st_ctimensec; /* nsec of last status change */#endif off_t st_size; /* 总大小,字节为单位 file size, in bytes */ blkcnt_t st_blocks; /* 允许分配给文件的块的数量,512字节为单元 blocks allocated for file */ blksize_t st_blksize; /* 文件系统的块大小 optimal blocksize for I/O */ __uint32_t st_flags; /* 用户自定义文件描述符给该文件 user defined flags for file */ __uint32_t st_gen; /* file generation number */ __int32_t st_lspare; /* RESERVED: DO NOT USE! */ __int64_t st_qspare[2]; /* RESERVED: DO NOT USE! */}
文件类型
Unix中大多数的文件类型是普通文件或目录。下面是Unix文件类型的介绍
- 普通文件:包含了某种形式的数据。对于Unix内核而言,不管是文本还是二进制数据都没有区别。对于普通文件内容的解释是由处理该文件的应用程序进行的。
- 目录文件:包含其他文件的名字以及执行这些文件有关信息的指针。对目录文件有读权限的任一进程都可以读该目录内容,但只有内核可以直接写目录。进程需要通过一些函数才能修改目录。
- 特殊文件:提供对设备(如磁盘)带缓冲的访问,每次访问以固定长度为单位进行。
- 字符特殊文件:提供对设备不带缓冲的访问,每次访问长度可变。(FreeBSD所有设备都是通过字符特殊文件访问,没有特殊文件)
- FIFO:用于进程间通信,也叫管道。
- 套接字:用于进程间的网络通信。
- 符号连接:该文件会指向另一个文件
上面的7种文件类型包含在stat结构体的st_mode成员中。通过使用下面宏的参数可以确定文件类型。
例如判断文件是否是目录文件类型:
#define S_ISDIR(mode) (((mode)&S_IFMT)== S_IFDIR);
各种类型文件对应的宏如下
S_ISREG() 普通文件
S_ISDIR() 目录文件
S_ISCHR() 字符特殊文件
S_ISBLK() 块特殊文件
S_ISFIFO() 管道活着FIFO
S_ISLNK() 符号连接
S_ISSOCK() 套接字
POSIX.1允许实现将进程通信对象当作文件,但是坚持宏参数不是stat的st_mode而是stat的指针
S_TYPEISMQ(buf):消息队列S_TYPEISSEM(buf):信号量S_TYPEISSHM(buf):共享存储对象
函数stat,fstat,fstatat,lstat获取文件的结构体stat
我们可以通过下面的四个函数获取文件的stat。下面是从mac上截取的四个函数定义
#include <sys/stat.h>int fstat(int fd, struct stat *buf) __DARWIN_INODE64(fstat);int lstat(const char *pathname, struct stat *buf) __DARWIN_INODE64(lstat);int stat(const char *pathname, struct stat *buf) __DARWIN_INODE64(stat);int fstatat(int fd, const char *pathname, struct stat *buf, int flag);
fstat 根据打开的文件描述符fd上的文件返回stat;
lstat 返回符号连接的有关信息,而不是符号连接引用的文件信息。
stat 返回此命名文件有关的信息,如果是符号连接返回连接引用的文件信息。
fstatat 如果flag设置为:AT_SYMLINK_NOFOLLOW,则类似lstat。否则默认类似于stat
fd参数为AT_FDCWD 表示pathname支持相对路径。如果pathname是绝对路径fd传什么都无所谓
测试源码
#include <stdio.h>#include <sys/stat.h>#include <time.h>//时间转换,参数word修饰这是什么时间void printfTime(long time,char word[]){ static char str_time[100]; struct tm *local_time = NULL; time_t utc_time; utc_time = time; local_time = localtime(&utc_time); strftime(str_time, sizeof(str_time), "%Y-%m-%d,%H:%M:%S", local_time); printf("%s:%s\n",word,str_time);}int main(int argc, const 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) { printf("error:"); perror("lstat error"); continue; } //通过检查stat结构体buf的st_mode来检查文件类型 if (S_ISREG(buf.st_mode)) { ptr = "regular";//普通文件 }else if(S_ISDIR(buf.st_mode)){ ptr = "S_ISDIR";//目录文件 }else if(S_ISCHR(buf.st_mode)){ ptr = "S_ISCHR";//字符特殊文件 }else if(S_ISBLK(buf.st_mode)){ ptr = "S_ISBLK";//块特殊文件 }else if(S_ISFIFO(buf.st_mode)){ ptr = "S_ISFIFO";//管道或FIFO }else if(S_ISLNK(buf.st_mode)){ ptr = "S_ISLNK";//符号链接 }else if(S_ISSOCK(buf.st_mode)){ ptr = "S_ISSOCK";//套接字 }else{ ptr = "** _unknow mode **"; } printf(" %s\n",ptr); printf("time = %ld\n",buf.st_atime); printfTime(buf.st_atime,"访问时间"); printfTime(buf.st_ctime,"修改时间"); printfTime(buf.st_birthtime,"创建时间"); printf("DeviceID = %d\n",buf.st_dev); printf("UserID = %d\n",buf.st_uid); printf("文件大小:%lld字节\n",buf.st_size); //**可以判断该Stat是不是信号量 if(S_TYPEISMQ(buf)){printf("是一个消息队列\n");}else printf("NO Queue\n"); if(S_TYPEISSEM(buf)){printf("是一个信号量\n");}else printf("NO SEM\n"); if(S_TYPEISSHM(buf)){printf("是一个共享存储对象\n");}else printf("NO SHM\n"); } return 0;}
0 0
- Unix编程之文件类型检测
- <<探讨linux/unix>>之文件类型
- unix环境高级编程-4.3-文件类型
- 《UNIX环境高级编程》笔记--文件类型
- 《UNIX环境高级编程》笔记6--文件类型
- UNIX环境编程学习笔记(6)——文件I/O之判断文件类型
- unix文件类型
- Unix文件类型
- Unix文件类型
- UNIX文件I/O之判断文件类型
- 文件类型检测
- 7.shell编程(7) --- 文件类型以及UNIX编程原则
- UNIX中的文件类型
- UNIX系统的文件类型
- Unix编程之环境变量
- Linux命令之file - 检测并显示文件类型
- 《Unix环境高级编程》:死锁检测实例
- Vim的文件类型检测
- 求职之路(拿到百度、美团、趋势科技、华为offer)
- FIRST
- Base64编码与解码
- 数据结构实践——循环双链表应用
- 对象数组排序
- Unix编程之文件类型检测
- 推荐!手把手教你使用Git
- xml里面数据的读取
- Template模式-在于模板框架以及和Strategy模式区别
- 数据科学的三个重要经验
- thinkPHP3.2.3使用过程中遇到的问题收集
- 欢迎使用CSDN-markdown编辑器
- android:windowSoftInputMode属性使用
- Python 爬虫 raise self._value IndexError: list index out of range