【date】Linux date命令修改时间的问题

Linux date命令修改时间的问题

问题

Android10;高通平台
使用下面date命令修改时间日期,时分秒生效,年月日不生效
=> date -D YYYY-MM-DD hh:mm:ss

路径

\android\external\toybox\toys\posix\date.c
\android\external\toybox\lib\args.c

找原因

首先在命令行键入
=> adb shell date -D 2020-10-01 22:59:00

去代码看一下参数传的有没有什么问题
\android\external\toybox\main.c

// argc:参数的数量   argv: 参数
int main(int argc, char *argv[])
{
  if (!*argv) return 127;

  if (CFG_TOYBOX) {
    // Call the multiplexer, adjusting this argv[] to be its' argv[1].
    // (It will adjust it back before calling toy_exec().)
    toys.argv = argv-1;
    toybox_main();
  }
  ...
}

argc = 4,
argv[0] = date, argv[1] = -D, argv[2] = 2020-10-01, argv[3] = 22:59:00
在这里插入图片描述
很明显这里并没有什么问题,我们接着往下看调用toybox_main()

// Multiplexer command, first argument is command to run, rest are args to that.
// If first argument starts with - output list of command install paths.
void toybox_main(void)
{
  static char *toy_paths[]={"usr/","bin/","sbin/",0};
  int i, len = 0;

  if (toys.argv[1]) {
    toy_exec(toys.argv+1);
    if (0<readlink(toys.argv[1], libbuf, sizeof(libbuf)))
      toy_exec_which(toy_find(basename(libbuf)), toys.argv);
  }
  ...
}

  参数传给toys.argv,我们看一下toys.argv里面是怎么存放数据的:
  其中toys.argv[0]为空,toys.argv[1] = date, toys.argv[2] = -D, toys.argv[3] = 2020-10-08, toys.argv[4] = 22:59:00
  还是没有问题,我们接着往下看

// Lookup internal toybox command to run via argv[0]
void toy_exec(char *argv[])
{
  toy_exec_which(toy_find(basename(*argv)), argv);
}

// Run an internal toybox command.
void toy_exec_which(struct toy_list *which, char *argv[])
{
  ...
  // Run command
  toy_init(which, argv);
  if (toys.which) toys.which->toy_main();
  xexit();
}
void toy_init(struct toy_list *which, char *argv[])
{
  void *oldwhich = toys.which;
  ...
  // Continue to portion of init needed by standalone commands
  toy_singleinit(which, argv);
}

static void toy_singleinit(struct toy_list *which, char *argv[])
{
  toys.which = which;
  toys.argv = argv;
  ...

  if (NEED_OPTIONS && which->options) get_optflags();
  else {
    toys.optargs = argv+1;
    for (toys.optc = 0; toys.optargs[toys.optc]; toys.optc++);
  }
  toys.old_umask = umask(0);
  if (!(which->flags & TOYFLAG_UMASK)) umask(toys.old_umask);
  toys.signalfd--;
  toys.toycount = ARRAY_LEN(toy_list);
}

这里走的分支是get_optflags()
  get_optflags()是对参数的解析,通过log可以发现get_optflags的for循环只循环了gof.argc=1(-D),gof.argc=3(22:59:00),漏掉了gof.argc=2就是年月日
先看gof.argc=1的循环:
  gof.arg是字符型指针,指向toys.argv[1] = -D 的”-”,++后就指向了”D”, 所以传给gotflag()的参数是”D”

// Fill out toys.optflags, toys.optargs, and this[] from toys.argv
void get_optflags(void)
{
  struct getoptflagstate gof;
  struct opts *catch;
  unsigned long long saveflags;
  char *letters[]={"s",""};

  // Iterate through command line arguments, skipping argv[0]
  for (gof.argc=1; toys.argv[gof.argc]; gof.argc++) {
    gof.arg = toys.argv[gof.argc];
    catch = NULL;

    // Parse this argument
    if (gof.stopearly>1) goto notflag;

    gof.nodash_now = 0;

    // Various things with dashes
    if (*gof.arg == '-') {

      // Handle -
      if (!gof.arg[1]) goto notflag;
      gof.arg++;
      if (*gof.arg=='-') {
        struct longopts *lo;

        gof.arg++;
        // Handle --
        if (!*gof.arg) {
          gof.stopearly += 2;
          continue;
        }

        // do we match a known --longopt?
        for (lo = gof.longopts; lo; lo = lo->next) {
          if (!strncmp(gof.arg, lo->str, lo->len)) {
            if (!gof.arg[lo->len]) gof.arg = 0;
            else if (gof.arg[lo->len] == '=' && lo->opt->type)
              gof.arg += lo->len;
            else continue;
            // It's a match.
            catch = lo->opt;
            break;
          }
        }

        // Should we handle this --longopt as a non-option argument?
        if (!lo && gof.noerror) {
          gof.arg -= 2;
          goto notflag;
        }

        // Long option parsed, handle option.
        gotflag(&gof, catch);
        continue;
      }

    // Handle things that don't start with a dash.
    } else {
      if (gof.nodash && (gof.nodash>1 || gof.argc == 1)) gof.nodash_now = 1;
      else goto notflag;
    }

    // At this point, we have the args part of -args.  Loop through
    // each entry (could be -abc meaning -a -b -c)
    saveflags = toys.optflags;
    while (*gof.arg) {

      // Identify next option char.
      for (catch = gof.opts; catch; catch = catch->next)
        if (*gof.arg == catch->c)
          if (!((catch->flags&4) && gof.arg[1])) break;

      // Handle option char (advancing past what was used)
      if (gotflag(&gof, catch) ) {
        toys.optflags = saveflags;
        gof.arg = toys.argv[gof.argc];
        goto notflag;
      }
    }
    continue;

    // Not a flag, save value in toys.optargs[]
notflag:
    if (gof.stopearly) gof.stopearly++;
    toys.optargs[toys.optc++] = toys.argv[gof.argc];
  }
  ...
}

  看下为什么会把年月日跳过,gotflag()中选项(-option)解析, gotflag(&gof, catch);
传入的gof->arg 指向 ”D”, gof->arg有参数++指向” ”

// Use getoptflagstate to parse one command line option from argv
static int gotflag(struct getoptflagstate *gof, struct opts *opt)
{
  int type;

  // Set flags
  toys.optflags |= opt->dex[1];
  gof->excludes |= opt->dex[2];
  if (opt->flags&2) gof->stopearly=2;

  ...
  // Does this option take an argument?
  if (!gof->arg) {
    if (opt->flags & 8) return 0;
    gof->arg = "";
  } else gof->arg++; // 指向" "
  type = opt->type; // type = ":"

  ...
  return 0;
}

char*arg = ” ”
gof->nodash_now = 0, !arg[0] = 1, opt->flags = 0
进行判断,++argc,argc由1变为2,也是导致年月日被跳过的原因
这时arg指向“2020-10-08”, opt->arg指向“2020-10-08”

解决方法

  由于args.c是解析命令行参数的共用文件,没把握最好不要修改,很容易影响到其他命令的解析。我们可以让被跳过的参数2为任意字符,如("+"可为任意字符)
=> date -D + YYYY-MM-DDhh:mm:ss
另外也可以使用
=> date MMDDhhmmYYYY.ss set
来设置时间

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值