如何欺骗进程认为文件不存在?

如何欺骗进程认为文件不存在?

我有一个程序存储其设置,~/.config/myprogram我可以交互式地使用该程序并与批处理排队系统一起使用。当交互运行时,我希望这个程序使用我的配置文件(它确实如此)。但在批处理模式下运行时,不需要配置文件,因为我指定了覆盖所有相关设置的命令行选项。此外,通过网络访问配置文件会使程序的启动时间增加几秒钟;如果文件不存在,程序启动速度会更快(因为每个作业只需要大约一分钟,这对批处理作业吞吐量有重大影响)。但因为我也以交互方式使用该程序,所以我不想一直移动/删除我的配置文件。根据我的批处理作业在集群上安排的时间(基于其他用户的使用情况),我可能希望以交互方式使用该程序,同时作为批处理作业的一部分。

(旁白:网络文件性能如此缓慢可能是一个错误,但我只是集群的用户,所以我只能解决它,而不能修复它。)

我可以构建一个不读取配置文件(或具有不读取配置文件的命令行选项)的程序版本以供批量使用,但该程序的构建环境设计不佳且难以设置。我更喜欢使用通过系统的包管理器安装的二进制文件。

如何欺骗该程序的特定实例假装我的配置文件不存在(无需修改程序)?我希望有一个 form 的包装器 pretendfiledoesntexist ~/.config/myprogram -- myprogram --various-options...,但我对其他解决方案持开放态度。

答案1

该程序可能会解析从 到该文件的路径$HOME/.config/myprogram。所以你可以告诉它你的主目录在其他地方,例如:

HOME=/nowhere your-program

现在,也许您的程序需要主目录中的一些其他资源。如果您知道它们是什么,您可以为您的程序准备一个假主页,其中包含指向该程序所需资源的链接。

mkdir -p ~/myprogram-home/.config
ln -s ~/.Xauthority ~/myprogram-home/
...
HOME=~/myprogram-home myprogram

答案2

如果所有其他方法都失败,请编写一个您将注入的包装器库,LD_PRELOAD以便拦截调用open("/home/you/my-program/config.interactive"),但任何其他调用都会通过。这适用于任何类型的程序,甚至是 shell 脚本,因为它会过滤系统调用。

extern int errno;

int open(const char *pathname, int flags)
{
  char *config_path = get_config_file_path();
  if (!strstr(pathname, config_path))
  {
    return get_real_open(pathname, flags);
  }
  else
  {
    errno = ENOENT;
    return -1;
  }
}

注意:我尚未测试此代码,并且我不能 100% 确定该errno部分是否有效。

看看怎么样fakerootgetuid(2)对于和等调用执行此操作stat(2)

基本上,链接器会将该应用程序链接到您的库,从而覆盖该open符号。由于您不能使用您自己的库中命名的两个不同的函数open,因此您必须将其分隔在第二部分(例如get_real_open)中,该部分将依次链接到原始open调用。

原来的:./Application

Application -----> libc.so
            open()

拦截:LD_PRELOAD=yourlib_wrap.so ./Application

Application -----> yourlib_wrap.so --------------> yourlib_impl.so -----> libc.so
            open()                 get_real_open()                 open()

编辑:显然您可以启用一个ld标志 ( --wrap <symbol>),它允许您编写包装器而不必求助于双重链接:

/* yourlib.c */
#include <stdio.h>

int __real_open(const char *pathname, int flags)

int __wrap_open(const char *pathname, int flags)
{
  char *config_path = get_config_file_path();
  if (!strstr(pathname, config_path))
  {
    /* the undefined reference here will resolve to "open" at linking time */
    return __real_open(pathname, flags);
  }
  else
  {
    errno = ENOENT;
    return -1; 
  }
}

答案3

将配置文件移开,并为交互式用例编写一个 shell 脚本包装器,将文件复制到其正常目标,运行程序,并在退出时将其删除。

答案4

将配置文件重命名为例如config.interactive.创建另一个名为 例如 的空文件config.script

config现在,创建一个名为(或应用程序期望作为配置文件的任何内容)的软链接到您需要的任何实际配置并运行您的应用程序。

ln -s config.interactive config

请记住事后整理您的链接。

相关内容