文件或目录的基本属性(stat函数)

        我们在打开一个文件之后,对其进行了读、写操作,那么接下来需要了解一个文件的基本属性,在这里就需要调用stat函数来查看了。


目录

一、获取文件元信息

二、对应stat结构体部分成员的操作函数

        1、getpwuid函数

        2、getgrgid函数

        3、localtime函数

        4、strftime函数

        5、time函数

三、对目录的操作函数

        1. 打开目录

        2. 读目录

        3. 关闭目录流

        4. 解析目录

        5. 解析命令行选项

        6.从终端读入一个口令

四、具体的函数使用实例


一、获取文件元信息

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int stat(const char *pathname, struct stat *statbuf);
int fstat(int fd, struct stat *statbuf);
int lstat(const char *pathname, struct stat *statbuf);

       我们主要研究stat函数
        path:文件地址                buf:存储文件元信息的结构体
        函数成功执行后,所得的元信息都存储在buf中
        成功0.失败-1

        buf结构体的数据:

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
};

具体的中文翻译可以参考stat函数与stat结构体 和 Linux中stat函数和stat命令使用详解

这里着重说明一下st_mode,它是一个16bit的整形数,各个bit所对应的关系如下

0-2比特位其他用户权限
3-5比特位组用户权限
6-8比特位本用户权限
9-11比特位特殊权限
12-15比特位文件类型

所以想要使用文件权限和类型的时候,要先用st_mode与一系列的宏做&运算之后才能得出,具体的操作一样可以参考上一个链接。

以及st_blocks,指的是文件所占的块数,1块-->512Byte


二、对应stat结构体部分成员的操作函数

        1、getpwuid函数

#include <sys/types.h>
#include <pwd.h>

struct passwd *getpwuid(uid_t uid);

uid_t uid:指的是stat结构体里边的uid。
功能:返回/etc/passwd文件里指定uid的行,把这一行的信息放入结构体passwd中。
 关于/etc/passwd,请参考  Linux /etc/passwd
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函数

#include <sys/types.h>
#include <grp.h>

struct group *getgrgid(gid_t gid);

gid_t gid:指的是stat结构体里边的gid。
功能:返回/etc/group文件里指定gid的行,把这一行的信息放入结构体group中。
group结构如下:

struct group {
    char   *gr_name;        /* group name */
    char   *gr_passwd;      /* group password */
    gid_t   gr_gid;         /* group ID */
    char  **gr_mem;         /* NULL-terminated array of pointers
                               to names of group members */
};

        3、localtime函数

#include <time.h>

struct tm *localtime(const time_t *timep);

const time_t *timep指的是stat结构体中包含的三个时间结构体中的某一个成员,最下边三行有现成的宏定义可以使用
(宏定义里的时间是当前时间到1970.1.1 00:00:00的秒数)
功能:将秒数转化为一个tm类型的结构体
tm结构体如下:

struct tm {
    int tm_sec;    /* Seconds (0-60) */
    int tm_min;    /* Minutes (0-59) */
    int tm_hour;   /* Hours (0-23) */
    int tm_mday;   /* Day of the month (1-31) */
    int tm_mon;    /* Month (0-11) */
    int tm_year;   /* Year - 1900 */
    int tm_wday;   /* Day of the week (0-6, Sunday = 0) */
    int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */
    int tm_isdst;  /* Daylight saving time */
};

我们可以直接调用tm结构体中的数据进行操作,也可以调用strftime()函数拼接成字符串使用。

        4、strftime函数

#include <time.h>

size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);

功能:将 tm 结构体中的数据,按照 format 所指定的字符串格式,保存到字符串 s 中,最多保存max字节。(具体的使用在最下方的例子中)
format中使用到的特殊格式说明符可以参照 百度百科strftime()函数

        5、time函数

        如果需要获取单独的时间戳,可以调用time函数,可以获取当前时间到1970.1.1 00:00:00的秒数。

#include <time.h>

time_t time(time_t *tloc);

time_t *tloc是存放时间的结构体,函数的返回值是结构体的地址


三、具体的函数使用实例

        其中的目录解析函数请参考        关于目录的基本函数

        mian.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include "myls.h"
#include <glob.h>
#include <string.h>

#define BUFSIZE 128

int main(int argc, char *argv[]){

	int c = 0;
	struct stat st;
	char *p = "./*";
	char *path = NULL;
	glob_t res;
	char buf[BUFSIZE] = {};

		c = getopt(argc ,argv, "-l");

		switch (c){
			case 1 :
				strcat(strcpy(buf,argv[optind-1]),"/*");
				glob(buf, 0, NULL, &res);
				for (int i = 0; i < res.gl_pathc; i++)
					printf("%s\t",(res.gl_pathv)[i]);
				printf("\n");
				globfree(&res);
				break;

			case 'l':
					glob(p, 0, NULL, &res);
					for (int i = 0; i < res.gl_pathc; i++){
						path = (char *)res.gl_pathv[i];
						stat(path, &st);
						printf("%c%s %d %s %s %d %s %s\n", filetype(st),filemode(st),\
								filenlink(st),fileowner(st), filegroupname(st), \
								filesize(st), filetime(st), res.gl_pathv[i]);
					}
				globfree(&res);
				break;
		}
		
		if (argc < 2){
				glob(p, 0, NULL, &res);
				for (int i = 0; i < res.gl_pathc; i++)
					printf("%s\t",(res.gl_pathv)[i]);
				printf("\n");
				globfree(&res);
		}

	return 0;	
}


myls.h

#ifndef __MYLS_H
#define __MYLS_H

const char *filemode(struct stat st);

char filetype(struct stat st);

int filenlink(struct stat st);

const char *fileowner(struct stat st);

const char *filegroupname(struct stat st);

int filesize(struct stat st);

const char *filetime(struct stat st);

#endif

myls.c

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>

#define BUFSIZE 32

const char *filemode(struct stat st){ // 文件权限
	int m[] = {S_IRUSR,S_IWUSR,S_IXUSR,S_IRGRP,S_IWGRP,S_IXGRP,S_IROTH,S_IWOTH,S_IXOTH};	
	static char s[] = "rwxrwxrwx";
	
	for (int i = 0; s[i]; i++){
		if (!(st.st_mode & m[i]))
			s[i] = '-';
	}
	return s;
}

char filetype(struct stat st){	//文件类型
	char ret;

	switch (st.st_mode & S_IFMT){
		case S_IFSOCK: ret = 's'; break;
		case S_IFLNK : ret = 'l'; break;
		case S_IFREG : ret = '-'; break;
		case S_IFBLK : ret = 'b'; break;
		case S_IFDIR : ret = 'd'; break;
		case S_IFCHR : ret = 'c'; break;
		case S_IFIFO : ret = 'p'; break;
	}
	return ret;
}
	
int filenlink(struct stat st){		//文件链接数
	return st.st_nlink;
}

const char *fileowner(struct stat st){		//文件拥有者名
	struct passwd *pwd = getpwuid(st.st_uid);
	return pwd->pw_name;
}

const char *filegroupname(struct stat st){	//文件所属组
	struct group *grp = getgrgid(st.st_gid);
	return grp->gr_name;
}

int filesize(struct stat st){		//文件大小
	return st.st_size;	
}

const char *filetime(struct stat st){	//文件最后一次修改时间
	static char buf[BUFSIZE] = {};
	struct tm *tmp = localtime(&st.st_mtime);

	strftime(buf, BUFSIZE, "%m月 %d %H:%M",tmp);
	return buf;
}



  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值