linux下的rm命令是个删除文件命令那么它的源代码是怎样的呢?下面由秋天网 Qiutian.ZqNF.Com小编为大家整理了linux下rm命令源码的相关知识,希望对大家有帮助!

linux的rm命令源码分析

1.原因

想要在删除文件前,先覆盖文件内容,防止他人恢复文件,从而得到文件原内容;并且需要支持rm命令原本的参数选项:

name rm - remove files or directoriessynopsis rm [option]... file...remove (unlink) the file(s). -f, --force ignore nonexistent files, never prompt -i prompt before every removal -i prompt once before removing more than three files, or when removing recursively. less intru- sive than -i, while still giving protection against most mistakes ......

想来还是直接修改rm源文件比较方便,因而查看rm命令的源码文件,在调用删除系统调用前加入覆盖文件内容的操作,从而安全删除文件,并且支持rm命令的参数选项。

2.获取linux命令源码

可以通过三条命令获得命令的源代码网址

which rm //得到文件的绝对路径

rpm -qf 路径 //获取该命令所属的软件包名

rpm -qi 包名 //获取包信息,包含网址url信息

如下:

[[email protected] ~]$ which rm/bin/rm[[email protected] ~]$ rpm -qf /bin/rmcoreutils-8.4-19.el6.x86_64[[email protected] ~]$ rpm -qi coreutilsname : coreutils relocations: (not relocatable)version : 8.4 vendor: red hat, inc.release : 19.el6 build date: tue 17 apr 2012 06:14:13 am pdtinstall date: sun 04 aug 2013 11:48:59 am pdt build host: hs20-bc2-3.build.redhat.comgroup : system environment/base source rpm: coreutils-8.4-19.el6.src.rpmsize : 12847030 license: gplv3+signature : rsa/8, thu 19 apr 2012 10:59:38 pm pdt, key id 199e2f91fd431d51packager : red hat, inc. url : http://www.gnu.org/software/coreutils/summary : a set of basic gnu tools commonly used in shell sdeion :these are the gnu core utilities. this package is the combination ofthe old gnu fileutils, sh-utils, and textutils packages.

linux的rm命令源码

rm.c主函数main

rm命令函数调用流程:

man() -> rm() -> rm_fts() -> excise() -> unlinkat()

int main (int argc, char **argv){ bool preserve_root = true; struct rm_options x; bool prompt_once = false; int c; initialize_main (&argc, &argv); //初始化输入参数 set_program_name (argv[0]); //设置程序名 setlocale (lc_all, ""); bindtextdomain (package, localedir); textdomain (package); /* 程序正常结束前调用的close_stdin函数,关闭标准输入; * 一个程序最多可以用atexit()注册32个处理函数,这些处理函数的 * 调用顺序与其注册顺序相反。即就是先注册的最后调用,最后调用的最先调用*/ atexit (close_stdin); rm_option_init (&x); //初始化rm选项,即就是rm命令的参数 /* try to disable the ability to unlink a directory. */ priv_set_remove_linkdir (); /*试图去禁用删除目录的功能,try to remove priv from the effective set*/ while ((c = getopt_long (argc, argv, "dfirvir", long_opts, null)) != -1) { switch (c) //switch语句主要是根据输入参数选项设置删除选项 { case 'f': x.interactive = rmi_never; x.ignore_missing_files = true; prompt_once = false; break; case 'i': x.interactive = rmi_always; x.ignore_missing_files = false; prompt_once = false; break;

case 'r': case 'r': x.recursive = true; break; ...... case_getopt_help_char; case_getopt_version_char (program_name, authors); default: diagnose_leading_hyphen (argc, argv); usage (exit_failure); } } if (argc <= optind) /*参数小于等于optind,即就是没有输入要删除的filename*/ { if (x.ignore_missing_files) /*指定了-f选项时,直接退出,否则输出信息提示用户为指定操作对象*/ exit (exit_success); else { error (0, 0, _("missing operand")); usage (exit_failure); } } if (x.recursive && preserve_root) { static struct dev_ino dev_ino_buf; x.root_dev_ino = get_root_dev_ino (&dev_ino_buf); if (x.root_dev_ino == null) error (exit_failure, errno, _("failed to get attributes of %s"), quote ("/")); } size_t n_files = argc - optind; /*n_files存储命令行指定操作对象个数,即就是要删除文件个数(目录视为一个)*/ char **file = argv + optind; /*file存储操作对象的索引*/ if (prompt_once && (x.recursive || 3 < n_files)) { fprintf (stderr, (x.recursive ? _("%s: remove all arguments recursively? ") : _("%s: remove all arguments? ")), program_name); if (!yesno ()) exit (exit_success); } enum rm_status status = rm (file, &x); /*删除文件,返回删除状态*/ assert (valid_status (status)); exit (status == rm_error ? exit_failure : exit_success);}

rm()函数

/* remove files, honoring options specified via x. return rm_ok if successful. */enum rm_statusrm (char *const *file, struct rm_options const *x){ enum rm_status rm_status = rm_ok; if (*file) { int bit_flags = (fts_cwdfd | fts_nostat | fts_physical); if (x->one_file_system) bit_flags |= fts_xdev; fts *fts = xfts_open (file, bit_flags, null); //创建并填充fts结构体部分成员信息,会调用fts_open函数,失败返回失败的诊断信息 while (1) { ftsent *ent; ent = fts_read (fts); //填充ftsent结构体成员信息 if (ent == null) { if (errno != 0) { error (0, errno, _("fts_read failed")); rm_status = rm_error; } break; } enum rm_status s = rm_fts (fts, ent, x); assert (valid_status (s)); update_status (rm_status, s); } if (fts_close (fts) != 0) { error (0, errno, _("fts_close failed")); rm_status = rm_error; } } return rm_status;}

rn_fts()函数根据ftsent结构体成员信息,做一些处理,然后调用excise()函数执行删除操作;

excise函数调用unlinkat系统函数

/* remove the file system object specified by ent. is_dir specifies whether it is expected to be a directory or non-directory. return rm_ok upon success, else rm_error. */static enum rm_statusexcise (fts *fts, ftsent *ent, struct rm_options const *x, bool is_dir){ int flag = is_dir ? at_removedir : 0; if (unlinkat (fts->fts_cwd_fd, ent->fts_accpath, flag) == 0) { /* 使用了-v选项时,输出详细删除信息,是目录输出目录名,是文件输出文件名, 输出的是当前目录到删除文件的完全路径(" `/tmp/aa' "或者"`test/bb'") */ if (x->verbose) { printf ((is_dir ? _("removed directory: %s\n") : _("removed %s\n")), quote (ent->fts_path)); /*quote是将输出用(`')反引号单引号括起来*/ } return rm_ok; } //下边为unlinkat函数执行失败,做的一些处理 /* the unlinkat from kernels like linux-2.6.32 reports erofs even for nonexistent files. when the file is indeed missing, map that to enoent, so that rm -f ignores it, as required. even without -f, this is useful because it makes rm print the more precise diagnostic. */ if (errno == erofs) { struct stat st; if ( ! (lstatat (fts->fts_cwd_fd, ent->fts_accpath, &st) && errno == enoent)) errno = erofs; } if (ignorable_missing (x, errno)) return rm_ok; /* when failing to rmdir an unreadable directory, the typical errno value is eisdir, but that is not as useful to the user as the errno value from the failed open (probably eperm). use the earlier, more deive errno value. */ if (ent->fts_info == fts_dnr) errno = ent->fts_errno; error (0, errno, _("cannot remove %s"), quote (ent->fts_path)); mark_ancestor_dirs (ent); return rm_error;}

添加的覆盖文件内容的操作就是添加在unlinkat函数前边,因为上几步已经做好了rm命令选项的操作,使用不同参数的不同操作,unlinkat函数是最终执行删除操作的:

int flag = is_dir ? at_removedir : 0;if(flag == 0) //根据flag标志判断是文件还是目录,如果是文件才执行覆盖操作,否则不做任何操作{ //覆盖操作}if (unlinkat (fts->fts_cwd_fd, ent->fts_accpath, flag) == 0)

linux源码rm函数,linux的rm命令源码相关推荐

  1. linux内核的延时函数,linux中内核延时函数 (转)

    第一类延时函数原型是:(忙等) void ndelay(unsigned long nsecs); void udelay(unsigned long usecs); void mdelay(unsi ...

  2. linux协议栈skb操作函数,linux协议栈skb操作函数

    1,struct sk_buff数据结构 struct sk_buff{ //这两个结构必须放在最前面 struct sk_buff *next; struct sk_buff *prev; stru ...

  3. linux 内核 fget,fgets函数 linux中fgets函数怎么用

    一个函数该如何使用?我们最先要了解的就是这个函数的语法以及具体的含义是什么,所以今天我们就来看一看fgets函数在实际的运用过程当中是如何使用的,希望能给大家带来一定的帮助. fgets函数--lin ...

  4. linux中脚本退出函数,Linux 命令 shell 脚本之09(函数)

    1.使用函数 [oracle@XAG143 myshell]$ cat test_fun1.sh #!/bin/bash # using a function in a script function ...

  5. linux字符串编码转换函数,Linux C++ 字符串 编码识别、编码转换

    最近在做一个类似垂直下载的爬虫系统.下载之后有个解析模块,解析之后要求编码一致的向后传入索引,便遇到了编码转换问题. 1. 编码的识别 推荐使用 libchardet, 可以在这个页面下载,使用说明就 ...

  6. linux内核的外部接口函数,linux内核中GPIO的使用(二)--标准接口函数

    在linux内核中,有一些基本模块可以使用标准的接口函数来操作,比如GPIO.interrupt.clock,所谓的标准接口函数是指一些与硬件平台无关的.linux下做驱动通用的函数, 常用的有: g ...

  7. linux c 文件拷贝函数,Linux C函数库参考手册

    来自一本绝版的书,虽然没有函数 描述,但是最起码可以知道分类,就可以去 man 了 Linux C函数库参考手册 第1章字符测试 函数 isalnum(测试字符是否为英文字母或数字) isalpha( ...

  8. linux动态库注册函数,Linux动态库函数的详解

    linux动态库函数的详解 加载动态库 void *dlopen(const char *filename, int flag); flag的可能值: rtld_lazy rtld_now rtld_ ...

  9. Linux环境高级编程函数,Linux环境高级编程--出错处理(CLStatus)

    很多程序库对外提供若干类,每个方法出错时如何告知调用者是否出错,以及出错码(在Linux上在error.h中的全局errno就是保存我们Linux程序执行的出错码的)?方法很多,为了简化起见,函数将返 ...

  10. linux编程取消wait函数,Linux编程基础之进程等待(wait()函数).pdf

    Linux编程基础之进程等待(wait()函数) 编程过程中,有时需要让一个进程等待另一个进程 ,最常见的是父进程等待自己的子进程 ,或者父进程回收自己 的子进程资源包括僵尸进程.这里简单介绍一下系统 ...

最新文章

  1. 中级程序员教程-Cache映像技术
  2. 阻止计算机访问注册表,电脑怎么样防止注册表被强行的篡改,保护电脑安全
  3. 如何用ChemFinder制作子表单
  4. HTML与CSS基础之伪类选择器(三)
  5. C语言试题三十三之比较两个字符串的长度,(不得调用c语言提供的求字符串长度的函数),函数返回较长的字符串。若两个字符串长度相同,则返回第一个字符串。
  6. exposed beyond app through Intent.getData(),或FileUriExposedException
  7. Gartner发布2020年十大战略科技发展趋势
  8. PAT 1060 Are They Equal (25 分)
  9. 国际认可不断增加,国产数据库发展与应用前景如何?
  10. ios入门之消息推送详解
  11. 微信小程序云开发教程-微信小程序的JS基础-视图层数据更新
  12. DVWA网盘下载和安装教程 详解
  13. Ti芯片 bq76940锂电池管理系统BMS资料,源程序+PDF原理图,主控stm32f030。
  14. Kylin中cube优化
  15. win7如何设置通电自动开机_老司机处理win7系统电脑自动开机设置的详细步骤【图文】...
  16. Windows 最全CMD命令,带死机修复系统命令
  17. 500Illegal PORT command 错误 无法取得目录列表 8uftp
  18. Kotlin Suppress 的非常规用法
  19. form表单的onsubmit() return问题
  20. linux xmapp的安装

热门文章

  1. linux平台MSG_OOB选项测试
  2. vue项目获取浏览器地址栏参数方法 ?aaa=111bbb=222(非路由传参)
  3. 程序员需要学数学吗?
  4. 公司注销代理合同模板
  5. 没想到你们是这样的女生……
  6. C语言中文网学习进度
  7. 小学期 BlueSky学长与友人帐
  8. Android bluetooth介绍(三): 蓝牙扫描(scan)设备分析
  9. WINRAR5.0破解
  10. 线性分式变换(linear fractional transformation)