int stat(const char *pathname, struct stat *statbuf);
将会得到一个struct stat类型的变量statbuf。
struct stat是一个结构体类型
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* Inode number */
mode_t st_mode; /* File type and mode */
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; /* Block size for filesystem I/O */
blkcnt_t st_blocks; /* Number of 512B blocks allocated */
/* Since Linux 2.6, the kernel supports nanosecond
precision for the following timestamp fields.
For the details before Linux 2.6, see NOTES. */
struct timespec st_atim; /* Time of last access */
struct timespec st_mtim; /* Time of last modification */
struct timespec st_ctim; /* Time of last status change */
#define st_atime st_atim.tv_sec /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
其中文件的类型由st_mode与S_IFMT做&运算得到具体的类型。
S_IFMT 0170000 bit mask for the file type bit field
S_IFSOCK 0140000 socket
S_IFLNK 0120000 symbolic link
S_IFREG 0100000 regular file
S_IFBLK 0060000 block device
S_IFDIR 0040000 directory
S_IFCHR 0020000 character device
S_IFIFO 0010000 FIFO
文件的权限由st_mode与每个组对应的变量做&运算,一共9位,看是否有权限
S_IRUSR 00400 owner has read permission
S_IWUSR 00200 owner has write permission
S_IXUSR 00100 owner has execute permission
S_IRGRP 00040 group has read permission
S_IWGRP 00020 group has write permission
S_IXGRP 00010 group has execute permission
S_IROTH 00004 others have read permission
S_IWOTH 00020 others have write permission
S_IXOTH 00001 others have execute permission
实现stat的算法
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#define BUFSIZE 128
dev_t file_dev(struct stat res);
ino_t file_inode(struct stat res);
nlink_t file_link(struct stat res);
off_t file_size(struct stat res);
blkcnt_t file_blocks(struct stat res);
blksize_t file_io_block(struct stat res);
char file_type(struct stat res);
int file_mode(struct stat res, char **mode);
int get_file_uid_name(struct stat res, uid_t *uid, char **uname);
int get_file_gid_name(struct stat res, gid_t *gid, char **gname);
int get_file_mtime(struct stat res, char *buf, int size);
int get_file_atime(struct stat res, char *buf, int size);
int get_file_ctime(struct stat res, char *buf, int size);
int main(int argc, char *argv[])
{
struct stat statbuf;
char *s = NULL;
uid_t myid;
gid_t grid;
char *myname = NULL;
char *grname = NULL;
char buf[BUFSIZE];
if(argc < 2)
return 1;
if(-1 == stat(argv[1], &statbuf))
{
perror("stat()");
return 1;
}
file_mode(statbuf, &s);
get_file_uid_name(statbuf, &myid, &myname);
get_file_gid_name(statbuf, &grid, &grname);
printf(" 文件:%s\n", argv[1]);
printf(" 大小:%ld\t\t块:%ld\t\tIO块:%ld\t\t类型:%c\n", \
file_size(statbuf), file_blocks(statbuf), \
file_io_block(statbuf), file_type(statbuf));
printf("设备:%ld\t\tInode:%ld\t\t硬连接:%ld\n", \
file_dev(statbuf), file_inode(statbuf), \
file_link(statbuf));
printf("权限:(%s)\tUid:( %d/\t%s)\tGid:( %d/\t%s)\n",\
s, myid, myname, grid, grname);
get_file_mtime(statbuf, buf, BUFSIZE);
printf("最近访问:%s\n", buf);
get_file_atime(statbuf, buf, BUFSIZE);
printf("最近更改:%s\n", buf);
get_file_ctime(statbuf, buf, BUFSIZE);
printf("最近改动:%s\n", buf);
free(s);
s = NULL;
free(myname);
myname = NULL;
free(grname);
grname = NULL;
return 0;
}
dev_t file_dev(struct stat res)
{
return res.st_dev;
}
ino_t file_inode(struct stat res)
{
return res.st_ino;
}
nlink_t file_link(struct stat res)
{
return res.st_nlink;
}
off_t file_size(struct stat res)
{
return res.st_size;
}
blkcnt_t file_blocks(struct stat res)
{
return res.st_blocks;
}
blksize_t file_io_block(struct stat res)
{
return res.st_blksize;
}
char file_type(struct stat res)
{
char c;
switch(res.st_mode & S_IFMT)
{
case S_IFSOCK:
c = 's';
break;
case S_IFLNK:
c = 'l';
break;
case S_IFREG:
c = '-';
break;
case S_IFBLK:
c = 'b';
break;
case S_IFDIR:
c = 'd';
break;
case S_IFCHR:
c = 'c';
break;
case S_IFIFO:
c = 'p';
break;
default:
c = '?';
break;
}
return c;
}
int file_mode(struct stat res, char **mode)
{
int all_mode[] = {S_IRUSR, S_IWUSR, S_IXUSR, \
S_IRGRP, S_IWGRP, S_IXGRP, \
S_IROTH, S_IWOTH, S_IXOTH\
};
int i;
*mode = calloc(10, sizeof(char));
if(*mode == NULL)
return -1;
strncpy(*mode, "rwxrwxrwx", 10);
for(i = 0; i < 9; i++)
{
if(!(res.st_mode & all_mode[i]))
(*mode)[i] = '-';
}
return 0;
}
int get_file_uid_name(struct stat res, uid_t *uid, char **uname)
{
struct passwd *pwd = NULL;
*uid = res.st_uid;
pwd = getpwuid(*uid);
if(NULL == pwd)
return -1;
*uname = malloc(strlen(pwd->pw_name) + 1);
strcpy(*uname, pwd->pw_name);
return 0;
}
int get_file_gid_name(struct stat res, gid_t *gid, char **gname)
{
struct group *gop = NULL;
*gid = res.st_gid;
gop = getgrgid(*gid);
*gname = malloc(strlen(gop->gr_name) + 1);
if(NULL == *gname)
return -1;
strcpy(*gname, gop->gr_name);
return 0;
}
static int __time_change(struct timespec tim, char *buf, int size)
{
struct tm *tmp = NULL;
tmp = localtime(&tim.tv_sec);
if(NULL == tmp)
return -1;
strftime(buf, size, "%Y-%y-%d %H:%M:%S", tmp);
return 0;
}
int get_file_mtime(struct stat res, char *buf, int size)
{
__time_change(res.st_mtim, buf, size);
}
int get_file_atime(struct stat res, char *buf, int size)
{
__time_change(res.st_atim, buf, size);
}
int get_file_ctime(struct stat res, char *buf, int size)
{
__time_change(res.st_ctim, buf, size);
}