其他分享
首页 > 其他分享> > 系统中执行过 cd - 是否存在痕迹

系统中执行过 cd - 是否存在痕迹

作者:互联网

系统中执行过 cd - 是否存在痕迹

核心任务 找出执行过程中是否将当前PWD存入了某一个持久化数据结构中,就可以通过访问该数据结构从而得到执行前的PWD和OLDPWD

本文观点: 未找到该持久化数据结构的存在


在LINUX系统中,CD 指令执行后是否存在痕迹? 如果有留在了哪?

如果有,那么有两种可能性

  1. 留在操作系统中的数据结构里
  2. 留在本shell的数据结构里

查看文档知道,存在一个dirstack 能保存目录栈,但是在代码阅读过程中发现 dirs 的操作是直接依靠swap 执行的,cd 中并没有显性的使用 dirstack (见文末代码描述)。

下面是对cd - 执行的研究

cd - 和 PWD OLDPWD 的执行流程检测

具体过程(仅仅在OLDPWD存在且合法情况下,不合法时有其他处理)

cd - 的执行是获取OLDPWD的值到temp(如果存在),然后检测temp的合法性,最后将temp 赋给PWD

在执行后可观察到的是PWD和OLDPWD进行了交换。

交换的痕迹在,那么cd 的执行后不会产生多余的东西只能通过 执行前的 PWD OLDPWD 和执行后的PWDOLDPWD是刚好互为相反的来判断

  1. cd - 的执行会向标准输出流出执行后的PWD
  2. 执行后的PWD是执行前的OLDPWD

那么找出执行过程中是否将当前PWD存入了某一个持久化数据结构中,就可以通过访问该数据结构从而得到执行前的PWD和OLDPWD

从源代码阅读cd 相关内容

POSIX对cd 和 PWD的功能规定

  1. When the 'cd' builtin is invoked in LOGICAL mode, and the pathname
constructed from '$PWD' and the directory name supplied as an
argument does not refer to an existing directory, 'cd' will fail
instead of falling back to PHYSICAL mode.
  1. When the 'cd' builtin cannot change a directory because the length
of the pathname constructed from '$PWD' and the directory name
supplied as an argument exceeds PATH_MAX when all symbolic links
are expanded, 'cd' will fail instead of attempting to use only the
supplied directory name.
  1. The 'pwd' builtin verifies that the value it prints is the same as
the current directory, even if it is not asked to check the file
system with the '-P' option.

bash 的builtin cd.def 中相关内容

执行过程中 : 第一部分

遇到 cd - 换为 cd $OLDPWD

 else if (list->word->word[0] == '-' && list->word->word[1] == '\0')
    {
      /* This is `cd -', equivalent to `cd $OLDPWD' */
      dirname = get_string_value ("OLDPWD");

      if (dirname == 0)
	{
	  builtin_error (_("OLDPWD not set"));
	  return (EXECUTION_FAILURE);
	}

then find the dirs in CDPATH 这一点是CDPATH变量,而本指令执行 - = OLDPWD 是绝对路径,并不会使用到CDPATH

 else if (absolute_pathname (list->word->word))
    dirname = list->word->word;
  else if (privileged_mode == 0 && (cdpath = get_string_value ("CDPATH")))
    {
      dirname = list->word->word;

      /* Find directory in $CDPATH. */
      path_index = 0;
      while (path = extract_colon_unit (cdpath, &path_index))
	{

之后将更改目录(change_to_directory)

      while (path = extract_colon_unit (cdpath, &path_index))
	{
	  /* OPT is 1 if the path element is non-empty */
	  opt = path[0] != '\0';
	  temp = sh_makepath (path, dirname, MP_DOTILDE);
	  free (path);

	  if (change_to_directory (temp, no_symlinks, xattrflag))
	    {
	      /* POSIX.2 says that if a nonempty directory from CDPATH
		 is used to find the directory to change to, the new
		 directory name is echoed to stdout, whether or not
		 the shell is interactive. */
	      if (opt && (path = no_symlinks ? temp : the_current_working_directory))
		printf ("%s\n", path);

	      free (temp);
#if 0
	      /* Posix.2 says that after using CDPATH, the resultant
		 value of $PWD will not contain `.' or `..'. */
	      return (bindpwd (posixly_correct || no_symlinks));
#else
	      return (bindpwd (no_symlinks));
#endif

change_to_directory 中的内容

重复一遍问题为在执行cd 后留下了什么能被检测的痕迹

那么我们应当关注的是,change _to _directory 中如何更新PWD 是否有保存于某持久化数据结构中?

函数定义如下变量

static int
change_to_directory (newdir, nolinks, xattr)
     char *newdir;
     int nolinks, xattr;
{
  char *t, *tdir, *ndir;
  int err, canon_failed, r, ndlen;

其中在执行完将更新PWD在如下几种方式

/* If the chdir succeeds, update the_current_working_directory. */
  if (r == 0)
    {
      /* If canonicalization failed, but the chdir succeeded, reset the
	 shell's idea of the_current_working_directory. */
      if (canon_failed)
	{
	  t = resetpwd ("cd");
	  if (t == 0)
	    set_working_directory (tdir);
	  else
	    free (t);
	}
      else
	set_working_directory (tdir);

      free (tdir);
      return (1);
    }

而set和reset的定义如下

void
set_working_directory (name)
     char *name;
{
  FREE (the_current_working_directory);
  the_current_working_directory = savestring (name);
}

其中savestring 是个宏

#define savestring(x) (char *)strcpy (xmalloc (1 + strlen (x)), (x))general.h -- defines that everybody likes to use. ,目的是将该string 存入堆中,而之前之后等信息未能显示。

/* Call get_working_directory to reset the value of
   the_current_working_directory () */
static char *
resetpwd (caller)
     char *caller;
{
  char *tdir;
      
  FREE (the_current_working_directory);
  the_current_working_directory = (char *)NULL;
  tdir = get_working_directory (caller);
  return (tdir);
}

因此 cd 中未发现有将数据保存在持久化的数据结构中。

dirs 命令相关断定

首先,查阅资料得知,shell 提供了dirs 命令,该命令用于存储使用过的工作目录栈DIRSTACK array.

那么会留在 dirs的目录栈中吗? 实验后发现,并不会留下可被验证的痕迹,dirs的目录切换是通过swap 栈中元素顺序实现的

'DIRSTACK'
An array variable containing the current contents of the directory
stack. Directories appear in the stack in the order they are
displayed by the 'dirs' builtin. Assigning to members of this
array variable may be used to modify directories already in the
stack, but the 'pushd' and 'popd' builtins must be used to add and
remove directories. Assignment to this variable will not change
the current directory. If 'DIRSTACK' is unset, it loses its
special properties, even if it is subsequently reset.

//pushd.def 的pushd_builtin 的代码
// 这里是通过交换直接实现的,没有保存旧的到另一个地方。
      j = directory_list_offset - 1;
      temp = pushd_directory_list[j];
      pushd_directory_list[j] = current_directory;
      j = change_to_temp (temp);
      free (temp);
      return j;
    }

结论

综上,在cd - 的执行过程中,后果为swap PWD和OLDPWD。没有写入其他的可持久化的数据结构中。

标签:痕迹,working,OLDPWD,cd,current,PWD,directory,执行
来源: https://www.cnblogs.com/rfq7/p/16387037.html