水煮coreutils之 rm
来源:互联网 发布:淘宝新店如何经营视频 编辑:程序博客网 时间:2024/04/30 16:59
前言:
这是水煮coreutils 系列的第一篇,写下在读linux coreutils 代码的心得体会,随着难度的渐渐加大,不知道能把这个系列坚持到什么
时候,也许这是第一篇也就是最后一篇.
coreutils 是linux系统中最接近我们日常使用的部分,rm cp ls cat 等命令皆发于此,最常用意味着最稳定,最高效,偶自认为
目前不是看内核代码的那块料,那就从最基本的地方看起.
rm [ -f ] [ -r ] [ -R ] [ -i ] [ -e ] File
其中 i 是问不问要删除,r和R 表达一个意思要递归删除,e是显示删除的内容,f 不是我们想像的强制删除只是有错误信息不做提示
罢了.
通过 getopt_long 获取参数,参数放在struct rm_options中,不包括文件名.
那文件名是怎么获取的呢? 一个小技巧,以后在很多的应用程序中都会用到.
size_t n_files = argc - optind;
char const *const *file = (char const *const *) argv + optind;
获取到文件名以后,要做的事情就是删除了
enum RM_status status = rm (n_files, file, &x);
现在我们来看rm函数的实现:
在分析函数之前我们思考一下如果我们来实现这个函数,应当怎么做?
删除文件用remove 或者 unlink 函数,删除目录用rmdir函数,那么我们要做的事情就是遇到文件删除文件,遇到目录进入目录删除
文件,文件删除光光再出来删除目录,遇到删除不掉的就跳到上一级目录连着文件一起不删除.
rm的实现其实也很简单,拿
注意一下这一句:setjmp (ds->current_arg_jumpbuf)
在以后的过程中会有意想不到的效果.
自顶向下 抽丝剥茧 偶们来到了 rm_1函数:
它做的事情很简单 跳过 . .. 文件,remove_entry 删除文件,如果返回值为非空目录,那就删除目录remove_dir.
判断文件是个有用的宏,记录一下
#define DOT_OR_DOTDOT(Basename) /
(Basename[0] == '.' && (Basename[1] == '/0' /
|| (Basename[1] == '.' && Basename[2] == '/0')))
现在来看remove_entry:
调用prompt,这个函数做多个事情,
第一 迎合-i选项问你是否要删除
第二 判断是否为目录,
第三 目录是否为空
返回值表达,如果为文件,链接,空目录等标志为可删除,如果为非空目录标志为非空目录,如果其它情况作为err返回.
接下来对于可删除的的东西就开始删除了.
来看remove_dir函数.
这个函数采取的方法是用几个堆栈保持目录,文件状态,然后调用remove_cwd_entries 删除本目录的内容.
那么来看remove_cwd_entries 函数
从函数名来说就是把当前目录下的所有文件删除,很多人会认为这个是递归实现的,其实这个才是rm这个程序的精华部分,
通过两个循环化解递归:
这个是伪代码表示,表示个流程,还有复杂的堆栈操作,递归是函数的压栈,这里是把目录名压栈,一定程度上保留了系统资源.
细看代码我们可以学到很多有用的东西,很多很精巧的宏和函数,比如判断一个数是否2的n次方
这种用法也很好
这是水煮coreutils 系列的第一篇,写下在读linux coreutils 代码的心得体会,随着难度的渐渐加大,不知道能把这个系列坚持到什么
时候,也许这是第一篇也就是最后一篇.
coreutils 是linux系统中最接近我们日常使用的部分,rm cp ls cat 等命令皆发于此,最常用意味着最稳定,最高效,偶自认为
目前不是看内核代码的那块料,那就从最基本的地方看起.
rm [ -f ] [ -r ] [ -R ] [ -i ] [ -e ] File
其中 i 是问不问要删除,r和R 表达一个意思要递归删除,e是显示删除的内容,f 不是我们想像的强制删除只是有错误信息不做提示
罢了.
通过 getopt_long 获取参数,参数放在struct rm_options中,不包括文件名.
那文件名是怎么获取的呢? 一个小技巧,以后在很多的应用程序中都会用到.
size_t n_files = argc - optind;
char const *const *file = (char const *const *) argv + optind;
获取到文件名以后,要做的事情就是删除了
enum RM_status status = rm (n_files, file, &x);
现在我们来看rm函数的实现:
在分析函数之前我们思考一下如果我们来实现这个函数,应当怎么做?
删除文件用remove 或者 unlink 函数,删除目录用rmdir函数,那么我们要做的事情就是遇到文件删除文件,遇到目录进入目录删除
文件,文件删除光光再出来删除目录,遇到删除不掉的就跳到上一级目录连着文件一起不删除.
rm的实现其实也很简单,拿
for (i = 0; i < n_files; i++)
...{
enum RM_status s;
cycle_check_init (&ds->cycle_check_state);
/**//* In the event that rm_1->remove_dir->remove_cwd_entries detects
a directory cycle, arrange to fail, give up on this FILE, but
continue on with any other arguments. */
if (setjmp (ds->current_arg_jumpbuf))
s = RM_ERROR;
else
s = rm_1 (ds, file[i], x, &cwd_state);
assert (VALID_STATUS (s));
UPDATE_STATUS (status, s);
}
...{
enum RM_status s;
cycle_check_init (&ds->cycle_check_state);
/**//* In the event that rm_1->remove_dir->remove_cwd_entries detects
a directory cycle, arrange to fail, give up on this FILE, but
continue on with any other arguments. */
if (setjmp (ds->current_arg_jumpbuf))
s = RM_ERROR;
else
s = rm_1 (ds, file[i], x, &cwd_state);
assert (VALID_STATUS (s));
UPDATE_STATUS (status, s);
}
注意一下这一句:setjmp (ds->current_arg_jumpbuf)
在以后的过程中会有意想不到的效果.
自顶向下 抽丝剥茧 偶们来到了 rm_1函数:
它做的事情很简单 跳过 . .. 文件,remove_entry 删除文件,如果返回值为非空目录,那就删除目录remove_dir.
判断文件是个有用的宏,记录一下
#define DOT_OR_DOTDOT(Basename) /
(Basename[0] == '.' && (Basename[1] == '/0' /
|| (Basename[1] == '.' && Basename[2] == '/0')))
现在来看remove_entry:
调用prompt,这个函数做多个事情,
第一 迎合-i选项问你是否要删除
第二 判断是否为目录,
第三 目录是否为空
返回值表达,如果为文件,链接,空目录等标志为可删除,如果为非空目录标志为非空目录,如果其它情况作为err返回.
接下来对于可删除的的东西就开始删除了.
来看remove_dir函数.
这个函数采取的方法是用几个堆栈保持目录,文件状态,然后调用remove_cwd_entries 删除本目录的内容.
那么来看remove_cwd_entries 函数
从函数名来说就是把当前目录下的所有文件删除,很多人会认为这个是递归实现的,其实这个才是rm这个程序的精华部分,
通过两个循环化解递归:
这个是伪代码表示,表示个流程,还有复杂的堆栈操作,递归是函数的压栈,这里是把目录名压栈,一定程度上保留了系统资源.
removedir()
...{
while(1)
...{
remove_cwd_entries(dir);
}
}
remove_cwd_entries()
...{
while(1)
...{
if(isfile)
rm(file) ;
if(isdir)
...{
chdir(dir)
break ;
}
}
}
...{
while(1)
...{
remove_cwd_entries(dir);
}
}
remove_cwd_entries()
...{
while(1)
...{
if(isfile)
rm(file) ;
if(isdir)
...{
chdir(dir)
break ;
}
}
}
细看代码我们可以学到很多有用的东西,很多很精巧的宏和函数,比如判断一个数是否2的n次方
static inline bool
is_power_of_two (unsigned int i)
...{
return (i & (i - 1)) == 0;
}
is_power_of_two (unsigned int i)
...{
return (i & (i - 1)) == 0;
}
这种用法也很好
memcpy(mempcpy(str,buf1,strlen(buf1)),buf2,strlen(buf2)+1) ;
- 水煮coreutils之 rm
- 水煮coreutils 之二 hash
- 水煮coreutils 之三 完美hash
- coreutils
- 水煮旅途之概述
- 水煮旅途之“天山夜话”
- 水煮操作系统之虚拟化
- 每天一个linux命令之coreutils包: [命令
- 每天一个linux命令之coreutils包: base64命令
- coreutils源码学习之——mkdir.c
- RM文件解析之RM文件格式
- Linux命令之:rm
- Linux命令之rm
- Linux命令之"rm"
- Linux命令之rm
- linux命令之rm
- shell命令之rm
- Linux命令之rm
- 从WORD和EXCEL提取FLASH
- XSL简明教程
- avi视频 及其压缩 2
- 更改ROR的WEBrick的IP以及PORT设置
- DOM文档对象模型-HTML
- 水煮coreutils之 rm
- Installing SunSPOT SDK under Vista - Step-by-Step
- cube map texture & volume texture
- HGE下汉字显示的两种解决方案
- 通关小游戏,看你能过几关
- 字符编码转换
- vs.net 2005 sp1 安装经验收集
- 找到的相关连接ACCESS 2007 的相关资料
- 用.NET框架实现序列化