您的位置:首页 > 其它

文件I/O实践(2) --文件stat

2015-10-12 22:18 423 查看
功能:获取文件元数据

[cpp] view
plaincopy





#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结构体

[cpp] view
plaincopy





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 */

};

[cpp] view
plaincopy





//示例 - 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

[cpp] view
plaincopy





struct passwd *getpwuid(uid_t uid);

[cpp] view
plaincopy





//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

[cpp] view
plaincopy





struct group *getgrgid(gid_t gid);

[cpp] view
plaincopy





//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

[cpp] view
plaincopy





ssize_t readlink(const char *path, char *buf, size_t bufsiz);

4. localtime

[cpp] view
plaincopy





struct tm *localtime(const time_t *timep);

[cpp] view
plaincopy





//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 */

};

[cpp] view
plaincopy





//示例: 实现简单的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);

}

[cpp] view
plaincopy





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;

}

[cpp] view
plaincopy





bool isLink(const struct stat &fileStat)

{

if ((fileStat.st_mode & S_IFMT) == S_IFLNK)

return true;

return false;

}

[cpp] view
plaincopy





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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: