【Linux C编程】简单版本的自定义du命令

自定义du命令-------mydu

最近在学Linux C编程,跟着教程简单的编写了一个类似于Linux系统中du命令的程序,用于显示指定的目录或文件所占用的磁盘空间,简单的记录一下与分享,写的不好还请不吝赐教

程序中用到库的部分函数原型:

lstat

NAME
       stat, fstat, lstat - get file status

SYNOPSIS
       #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);

strchr

NAME
       strchr, strrchr, strchrnul - locate character in string

SYNOPSIS
       #include <string.h>

   char *strchr(const char *s, int c);

   char *strrchr(const char *s, int c);

   #define _GNU_SOURCE         /* See feature_test_macros(7) */
   #include <string.h>

   char *strchrnul(const char *s, int c);

DESCRIPTION
       The strchr() function returns a pointer to the first occurrence of the character c in the string s.

	   The strrchr() function returns a pointer to the last occurrence of the character c in the string s.
mydu.c
#include<stdio.h>
#include<stdlib.h>
#include<glob.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>

#define PATHSIZE 1024

//path_noloop函数用于判断子文件是否为“.”或者“..”,避免陷入无限递归中
static int path_noloop(char *path)
{
    
    
	char *pos;
    //获得目标路径中最后一个“/”右边的字符串
	pos = strrchr(path,'/');
	//return NULL,if not found '/'
	if(pos == NULL)
		exit(1);
	if (strcmp(pos+1,".") == 0 || strcmp(pos+1,"..") == 0)
		return 0;
	return 1;
}  

static int64_t mydu(const char *path)
{
    
    
	struct stat statres;
	char nextpath[PATHSIZE];
	glob_t globres;
	int i;
	int64_t sum;
	if (lstat(path,&statres) < 0)
	{
    
    
		perror("lstat()");
		exit(1);	
	}
    //判断是不是目录,如果不是目录,则直接跳出函数,返回文件的blocks大小,否则继续往下执行
	if(!S_ISDIR(statres.st_mode))
		//indicates the number of blocks allocated to  the  file,  512-byte  units
		return statres.st_blocks;
	
    //匹配目标路径下的非隐藏文件
	strncpy(nextpath,path,PATHSIZE);
	strncat(nextpath,"/*",PATHSIZE);
	glob(nextpath,0,NULL,&globres);
	
    //匹配目标路径下的隐藏文件,并把文件信息追加到glores结构体中
	strncpy(nextpath,path,PATHSIZE);
	strncat(nextpath,"/.*",PATHSIZE);
	glob(nextpath,GLOB_APPEND,NULL,&globres);		
	
	//printf("globres:%d\n",globres.gl_pathc);
	//include the first dir itself
    //通过递归来计算目标路径下的子目录下的文件的大小
	sum = statres.st_blocks;
	for (i =0;i<globres.gl_pathc;i++)
	{
    
    
        //path_noloop函数用于判断子文件是否为“.”或者“..”,避免陷入无限递归中
		if (path_noloop(globres.gl_pathv[i]))
			sum += mydu(globres.gl_pathv[i]);
			//printf("test");	
	}
    //释放globres中申请的内存
	globfree(&globres);	
	return sum;
}

int main(int argc, char *argv[])
{
    
    
	
    if (argc < 2)
	{
    
    
		fprintf(stderr,"Need a pathname as arg\n");
		exit(1);
	}
	
	//使用long long类型也是因为防止输出结果太大,超出整型的表示范围而导致出错
    //输出的大小单位是KB,而一个blocks的大小是512B,所以每两个blocks代表1KB,所有最终大小除以2
	printf("%lld\n",(mydu(argv[1])/2));
	exit(0);	                                   
   
}  

运行结果:

[root@rio mydu]# ./mydu /root/sys_pro/fs/mydu
20
[root@rio mydu]# du /root/sys_pro/fs/mydu
20	/root/sys_pro/fs/mydu

可以看到mydu得到的结果和du得到的目标文件的大小都是20KB

猜你喜欢

转载自blog.csdn.net/weixin_44517500/article/details/126959122
今日推荐