功能:获取文件元数据
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- int stat(const char *path, struct stat *buf);
- int fstat(int fd, struct stat *buf);
- int lstat(const char *path, struct stat *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 filesystem 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 */
- };
- //示例 - err_exit函数如前
- // 其实可以通过Linux 系统调用major, minor来替换(如下)
- #define MAJOR(a) (int)((unsigned short)a >> 8) //主设备号: 获取高8位
- #define MINOR(a) (int)((unsigned short)a & 0xFF)//次设备号: 获取低8位
- bool fileType(const struct stat &fileStat);
- void filePerm(const struct stat &fileStat, char *perm);
- int main(int argc, char *argv[])
- {
- if (argc != 2)
- {
- cerr << "Usage: " << argv[0] << " <file-name>" << endl;
- exit(EXIT_FAILURE);
- }
- struct stat fileStat;
- if (lstat(argv[1], &fileStat) == -1)
- err_exit("stat error");
- cout << "file-name: " << argv[1] << endl;
- cout << "st_ino = " << fileStat.st_ino << endl;
- cout << "device major: " << major(fileStat.st_dev)
- << ", minor: " << minor(fileStat.st_dev) << endl;
- if (fileType(fileStat))
- {
- cout << "----------------------------" << endl;
- cout << "major: " << MAJOR(fileStat.st_dev)
- << ", minor: " << MINOR(fileStat.st_rdev) << endl;
- // cout << "major: " << major(fileStat.st_dev)
- // << ", minor: " << minor(fileStat.st_rdev) << endl;
- }
- //获取文件的权限: 但要注意需要&上07777
- fprintf(stdout, "file permission: %o", fileStat.st_mode&07777);
- char perm[11];
- filePerm(fileStat, perm);
- cout << ", msg: " << perm << endl;
- cout << "st_nlink = " << fileStat.st_nlink << endl;
- cout << "st_uid = " << fileStat.st_uid << endl;
- cout << "st_gid = " << fileStat.st_gid << endl;
- cout << "st_size = " << fileStat.st_size << endl;
- cout << "st_blksize = " << fileStat.st_blksize << endl;
- cout << "st_blocks = " << fileStat.st_blocks << endl;
- cout << "st_atime = " << fileStat.st_atime << endl;
- cout << "st_ctime = " << fileStat.st_ctime << endl;
- cout << "st_mtime = " << fileStat.st_mtime << endl;
- }
- bool fileType(const struct stat &fileStat)
- {
- cout << "file-type: ";
- switch(fileStat.st_mode & S_IFMT)
- {
- case S_IFSOCK:
- cout << "socket";
- break;
- case S_IFLNK:
- cout << "symbolic link";
- break;
- case S_IFREG:
- cout << "regular file";
- break;
- case S_IFBLK:
- cout << "block device" << endl;
- return true;
- break;
- case S_IFDIR:
- cout << "directory";
- break;
- case S_IFCHR:
- cout << "character device" << endl;
- return true;
- break;
- case S_IFIFO:
- cout << "FIFO" << endl;
- break;
- default:
- cout << "unknown?";
- break;
- }
- cout << endl;
- return false;
- }
- void filePerm(const struct stat &fileStat, char *perm)
- {
- strcpy(perm, "----------");
- switch(fileStat.st_mode & S_IFMT)
- {
- case S_IFSOCK:
- perm[0] = 's';
- break;
- case S_IFLNK:
- perm[0] = 'l';
- break;
- case S_IFREG:
- perm[0] = '-';
- break;
- case S_IFBLK:
- perm[0] = 'b';
- break;
- case S_IFDIR:
- perm[0] = 'd';
- break;
- case S_IFCHR:
- perm[0] = 'c';
- break;
- case S_IFIFO:
- perm[0] = 'p';
- break;
- default:
- perm[0] = '?';
- break;
- }
- if (fileStat.st_mode & S_IRUSR)
- perm[1] = 'r';
- if (fileStat.st_mode & S_IWUSR)
- perm[2] = 'w';
- if (fileStat.st_mode & S_IXUSR)
- perm[3] = 'x';
- if (fileStat.st_mode & S_IRGRP)
- perm[4] = 'r';
- if (fileStat.st_mode & S_IWGRP)
- perm[5] = 'w';
- if (fileStat.st_mode & S_IXGRP)
- perm[6] = 'x';
- if (fileStat.st_mode & S_IROTH)
- perm[7] = 'r';
- if (fileStat.st_mode & S_IWOTH)
- perm[8] = 'w';
- if (fileStat.st_mode & S_IXOTH)
- perm[9] = 'x';
- }
[拓展]
1.getpwuid
- struct passwd *getpwuid(uid_t uid);
- //passwd结构体
- struct passwd
- {
- char *pw_name; /* username */
- char *pw_passwd; /* user password */
- uid_t pw_uid; /* user ID */
- gid_t pw_gid; /* group ID */
- char *pw_gecos; /* user information */
- char *pw_dir; /* home directory */
- char *pw_shell; /* shell program */
- };
2.getgrgid
- struct group *getgrgid(gid_t gid);
- //group结构体
- struct group
- {
- char *gr_name; /* group name */
- char *gr_passwd; /* group password */
- gid_t gr_gid; /* group ID */
- char **gr_mem; /* group members */
- };
3. readlink
- ssize_t readlink(const char *path, char *buf, size_t bufsiz);
4. localtime
- struct tm *localtime(const time_t *timep);
- //tm结构体
- struct tm
- {
- int tm_sec; /* seconds */
- int tm_min; /* minutes */
- int tm_hour; /* hours */
- int tm_mday; /* day of the month */
- int tm_mon; /* month */
- int tm_year; /* year */
- int tm_wday; /* day of the week */
- int tm_yday; /* day in the year */
- int tm_isdst; /* daylight saving time */
- };
- //示例: 实现简单的ls -l功能
- #include <iostream>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <grp.h>
- #include <pwd.h>
- #include <time.h>
- using namespace std;
- inline void err_exit(std::string message);
- bool isDevice(const struct stat &fileStat);
- bool isLink(const struct stat &fileStat);
- void filePerm(const struct stat &fileStat, char *perm);
- int main(int argc, char *argv[])
- {
- if (argc != 2)
- {
- cerr << "Usage: " << argv[0] << " <file-name>" << endl;
- exit(EXIT_FAILURE);
- }
- struct stat fileStat;
- if (lstat(argv[1], &fileStat) == -1)
- err_exit("lstat error");
- //获取权限
- char perm[11];
- filePerm(fileStat, perm);
- cout << perm << ' ';
- //获取文件链接数
- cout << fileStat.st_nlink << ' ';
- //获取文件所有者
- struct passwd *ps = getpwuid(fileStat.st_uid);
- cout << ps->pw_name << ' ';
- //获取文件所属组
- struct group *gp = getgrgid(fileStat.st_gid);
- cout << gp->gr_name << ' ';
- if (isDevice(fileStat))
- cout << major(fileStat.st_dev) << ", "
- << minor(fileStat.st_rdev) << ' ';
- else
- cout << fileStat.st_size << ' ';
- // 打印最后一次修改时间
- time_t mtime = fileStat.st_mtime;
- struct tm *pTime = localtime(&mtime);
- cout << pTime->tm_mon+1 << "月 " << pTime->tm_mday << ' '
- << pTime->tm_hour << ':' << pTime->tm_min << ' ';
- // 打印文件名
- cout << argv[1];
- if (isLink(fileStat))
- {
- cout << " -> ";
- char name[1024] = {0};
- if (readlink(argv[1], name, sizeof(name)) == -1)
- err_exit("readlink error");
- cout << name;
- }
- cout << endl;
- }
- inline void err_exit(std::string message)
- {
- perror(message.c_str());
- exit(EXIT_FAILURE);
- }
- bool isDevice(const struct stat &fileStat)
- {
- switch(fileStat.st_mode & S_IFMT)
- {
- case S_IFBLK:
- case S_IFCHR:
- return true;
- break;
- default:
- return false;
- break;
- }
- return false;
- }
- bool isLink(const struct stat &fileStat)
- {
- if ((fileStat.st_mode & S_IFMT) == S_IFLNK)
- return true;
- return false;
- }
- void filePerm(const struct stat &fileStat, char *perm)
- {
- strcpy(perm, "----------");
- switch(fileStat.st_mode & S_IFMT)
- {
- case S_IFSOCK:
- perm[0] = 's';
- break;
- case S_IFLNK:
- perm[0] = 'l';
- break;
- case S_IFREG:
- perm[0] = '-';
- break;
- case S_IFBLK:
- perm[0] = 'b';
- break;
- case S_IFDIR:
- perm[0] = 'd';
- break;
- case S_IFCHR:
- perm[0] = 'c';
- break;
- case S_IFIFO:
- perm[0] = 'p';
- break;
- default:
- perm[0] = '?';
- break;
- }
- if (fileStat.st_mode & S_IRUSR)
- perm[1] = 'r';
- if (fileStat.st_mode & S_IWUSR)
- perm[2] = 'w';
- if (fileStat.st_mode & S_IXUSR)
- perm[3] = 'x';
- if (fileStat.st_mode & S_IRGRP)
- perm[4] = 'r';
- if (fileStat.st_mode & S_IWGRP)
- perm[5] = 'w';
- if (fileStat.st_mode & S_IXGRP)
- perm[6] = 'x';
- if (fileStat.st_mode & S_IROTH)
- perm[7] = 'r';
- if (fileStat.st_mode & S_IWOTH)
- perm[8] = 'w';
- if (fileStat.st_mode & S_IXOTH)
- perm[9] = 'x';
- }
#include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include<stdio.h> #include<stdlib.h> #include<errno.h> #define ERR_EXIT(m) \ do{\ perror("m");\ exit(EXIT_FAILURE);\ }while(0) //struct stat 中st_dev成员高八位为主设备号 低八位为此设备号 #define MAJOR(a) (int)((unsigned short)a >> 8) #define MIMOR(a) (int)((unsigned short)a & 0xff) int main(int argc ,char *argv[]) { if(argc != 2) { fprintf(stderr,"Usage %s file\n",argv[0]); exit(EXIT_FAILURE); } struct stat mystat; if(stat(argv[1],&mystat) == -1) { ERR_EXIT("stat err!"); } printf("File number:major: %d,mimor %d\n",MAJOR(mystat.st_dev),MIMOR(mystat.st_dev)); printf("filename:%s\n",argv[1]); return 0; } //在linux命令行中输入 ./01stat Makefile 可以看到 主设备号(决定了用什么驱动程序)为 8 次设备号为 10 //可以使用 df 命令查看文件所在的磁盘分区 df Makefile 显示为:/dev/sda10 //ls -l 查看 /dev/sad10 的主设备号为 8 此设备号为 10