常用的cp, mv, mkdir等Linux命令在Android中的实现

常用的cp, mv, mkdir等Linux命令,在Android下是如何实现的呢

今天查验了一番,以cp为例,看下命令所在路径:

kona:/system/bin # which cp

显示如下

/sytem/bin/cp

我再次使用下面命令ls查看

kona:/system/bin # ls -al /system/bin/cp

显示如下:

lrwxr-xr-x 1 root shell 6 2009-01-01 00:00 /system/bin/cp -> toybox

同样的,查看mv和mkdir命令,显示如下:

kona:/system/bin # ls -al /system/bin/mv
lrwxr-xr-x 1 root shell 6 2009-01-01 00:00 /system/bin/mv -> toybox

kona:/system/bin # ls -al /system/bin/mkdir
lrwxr-xr-x 1 root shell 6 2009-01-01 00:00 /system/bin/mkdir -> toybox

发现命令都是个软连接文件,并且都指向了toybox,toybox是什么鬼?

kona:/ # ls -al /system/bin/toybox
-rwxr-xr-x 1 root shell 487072 2022-01-27 03:37 /system/bin/toybox

toybox不是软连接文件了,那么它是如何区分这些命令呢?
大胆猜测,这些命令软连接文件执行后,会读取当前可执行文件的名字,根据此名字的不同执行不同的操作
实际情况,也是这样,C/C++可执行文件的main方法的参数argv[0],就可以表示当前执行的文件名

int  main(int argc, char *argv[])

写程序test_symlink.c验证:

#include<stdio.h>
int main(int argc, char* argv[]){
    printf("%s\n", argv[0]);
    return 0;
}

编译生成test_symlink可执行文件后,创建两个连接文件cp和mkdir都指向这个test_symlink

# ln -s test_symlink cp
# ln -s test_symlink mkdir

然后执行./cp和./mkdir
输出:

# ./cp
./cp
# ./mkdir
./mkdir

toybox的实现,使用argv来做不同命令的区分

int main(int argc, char *argv[])
{
  // don't segfault if our environment is crazy
  if (!*argv) return 127;

  // Snapshot stack location so we can detect recursion depth later.
  // Nommu has special reentry path, !stacktop = "vfork/exec self happened"
  if (!CFG_TOYBOX_FORK && (0x80 & **argv)) **argv &= 0x7f;
  else {
    int stack_start;  // here so probe var won't permanently eat stack

    toys.stacktop = &stack_start;
  }

  // Android before O had non-default SIGPIPE, 7 years = remove in Sep 2024.
  if (CFG_TOYBOX_ON_ANDROID) signal(SIGPIPE, SIG_DFL);

  if (CFG_TOYBOX) {
    // Call the multiplexer with argv[] as its arguments so it can toy_find()
    toys.argv = argv-1;
    toybox_main();
  } else {
    // single command built standalone with no multiplexer is first list entry
    toy_singleinit(toy_list, argv);
    toy_list->toy_main();
  }
  xexit();
}

toybox_main

void toybox_main(void)
{
  char *toy_paths[] = {"usr/", "bin/", "sbin/", 0}, *s = toys.argv[1];
  int i, len = 0;
  unsigned width = 80;

  // fast path: try to exec immediately.
  // (Leave toys.which null to disable suid return logic.)
  // Try dereferencing one layer of symlink
  while (s) {
    struct toy_list *tl = toy_find(basename(s));

    if (tl==toy_list && s!=toys.argv[1]) unknown(basename(s));
    toy_exec_which(toy_find(basename(s)), toys.argv+1);
    s = (0<readlink(s, libbuf, sizeof(libbuf))) ? libbuf : 0;
  }
  ....
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值