[Linux C Programming] Simple version of custom du command

Custom du command --------mydu

Recently, I am learning Linux C programming. Following the tutorial, I simply wrote a program similar to the du command in the Linux system, which is used to display the disk space occupied by the specified directory or file. Simply record and share it. If the writing is not good, please don't hesitate to enlighten me

Some function prototypes of the library used in the program:

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

operation result:

[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

It can be seen that the size of the result obtained by mydu and the target file obtained by du are both 20KB

Supongo que te gusta

Origin blog.csdn.net/weixin_44517500/article/details/126959122
Recomendado
Clasificación