Linuxシステムプログラミング26ディレクトリとユーザーの操作-独自のduコマンドを実装する

ls隠しファイルを表示する

ls -a。:current
directoryで始まる、隠しファイルを含むすべてのファイルを表示します

mhr@ubuntu:~/work/linux/muluheyonghucaozuo/26$ ls
mydu.c
mhr@ubuntu:~/work/linux/muluheyonghucaozuo/26$ 
mhr@ubuntu:~/work/linux/muluheyonghucaozuo/26$ ls -a
.  ..  mydu.c
mhr@ubuntu:~/work/linux/muluheyonghucaozuo/26$ 

現在のディレクトリをグロブできません。親ディレクトリ...はスタックを壊します


実験:彼らの単純なduコマンドを実現する

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <glob.h>
#include <string.h>

#define PATHSIZE 1024


static int path_noloop(const char *path)
{
	char *pos;
	
	//定位最右边的'/'的位置
	pos = strrchr(path,'/');
	if(pos == NULL)
	exit(1);

	//判断 当前文件是 "." 和 ".." ,这两种情况不操作 直接越过,不然会导致栈破裂
	if(strcmp(pos+1,".")==0 || (strcmp(pos+1,"..")==0))
		return 0;

	return 1;
}

//防止大小溢出 long long int
static int64_t mydu(const char *path)
{
	struct stat statres;
	char nextpath[PATHSIZE];
	glob_t globres;
	int i;
	int64_t sum=0;
    //不使用 stat 遇到链接文件的时候 会返回 实际链接文件的属性信息,而我们此时需要返回链接文件本身属性信息
	if(lstat(path,&statres) < 0)
	{
		perror("lstat");
		exit(1);
	}
	//如果是非目录文件,直接返回文件大小 k: 块数/2
	 if(!S_ISDIR(statres.st_mode))
		return statres.st_blocks;

	// nextpath/*
	//strcpy(nextpath,path);
	strncpy(nextpath,path,PATHSIZE);
	strncat(nextpath,"/*",PATHSIZE);
	
	glob(nextpath,0, NULL, &globres);

	// nextpath/.*
	//strcpy(nextpath,path);
	strncpy(nextpath,path,PATHSIZE);
	strncat(nextpath,"/.*",PATHSIZE);
	glob(nextpath,GLOB_APPEND,NULL,&globres);


	sum += statres.st_blocks;

	for(i =0; i < globres.gl_pathc; i++)
	{
		//排除 . 和 ..文件
		if(path_noloop(globres.gl_pathv[i]))
		sum += mydu(globres.gl_pathv[i]);
	}
	
   globfree(&globres);
	return sum;
}

int main(int argc,char* argv[])
{
	if(argc < 2)
	{
		fprintf(stderr,"Usage:%s <src_file> <dest_file>\n",argv[0]);
		exit(1);
	}

	printf("%lld\n",mydu(argv[1])/2);


	exit(0);
}




mhr@ubuntu:~/work/linux/muluheyonghucaozuo/26$ gcc mydu.c 
mydu.c: In function ‘main’:
mydu.c:75:9: warning: format ‘%lld’ expects argument of type ‘long long int’, but argument 2 has type ‘int64_t {aka long int}’ [-Wformat=]
  printf("%lld\n",mydu(argv[1])/2);
         ^
mhr@ubuntu:~/work/linux/muluheyonghucaozuo/26$ ./a.out /etc/
13480
mhr@ubuntu:~/work/linux/muluheyonghucaozuo/26$ du /etc/
...
13480	/etc/

例外:
int glob()は0を正常に返します。コードをテストしたところ、glob()の結果を確認し、ターゲットファイルサイズを正常に計算できないことがわかった場合、テストでglob()関数が見つかりました。 3つの状況を返しました:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <glob.h>
#include <string.h>

#define PATHSIZE 1024


static int path_noloop(const char *path)
{
	char *pos;
	pos = strrchr(path,'/');
	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,err=0;
	int64_t sum=0;

	if(lstat(path,&statres) < 0)
	{
		perror("lstat");
		exit(1);
	}

	 if(!S_ISDIR(statres.st_mode))
		return statres.st_blocks;

	// nextpath/*
	//strcpy(nextpath,path);
	strncpy(nextpath,path,PATHSIZE);
	strncat(nextpath,"/*",PATHSIZE);
	
	glob(nextpath,0, NULL, &globres);

	// nextpath/.*
	//strcpy(nextpath,path);
	strncpy(nextpath,path,PATHSIZE);
	strncat(nextpath,"/.*",PATHSIZE);
	err = glob(nextpath,GLOB_APPEND,NULL,&globres);
	printf("err = %d\n",err);

	if(err)
	{
		fprintf(stderr,"glob():%s\n",strerror(err));
		exit(1);
	}


	sum += statres.st_blocks;

	for(i =0; i < globres.gl_pathc; i++)
	{
		if(path_noloop(globres.gl_pathv[i]))
		sum += mydu(globres.gl_pathv[i]);
	}

	return sum;
}

int main(int argc,char* argv[])
{
	if(argc < 2)
	{
		fprintf(stderr,"Usage:%s <src_file> <dest_file>\n",argv[0]);
		exit(1);
	}

	printf("%lld\n",mydu(argv[1])/2);


	exit(0);
}


...
err = 0
err = 0
err = 0
err = 0
err = 0
err = 3
glob():No such process
mhr@ubuntu:~/work/linux/muluheyonghucaozuo/26$ 

そのため、当面はglobの戻り値の判断はありません。

duコマンドは、後でディレクトリストリームを使用して実装されます。

おすすめ

転載: blog.csdn.net/LinuxArmbiggod/article/details/105981004