如何欺騙程序認為文件不存在?
我有一個程序將其設置儲存在
~/.config/myprogram
我以互動方式和批處理排隊系統使用。當以互動方式執行時,我希望這個程序使用我的配置文件(它確實如此)。但是在批處理模式下執行時,不需要配置文件,因為我指定了覆蓋所有相關設置的命令行選項。此外,通過網路訪問配置文件會使程序的啟動時間增加幾秒鐘;如果文件不存在,程序啟動速度會更快(因為每個作業只需要大約一分鐘,這對批處理作業的吞吐量有很大影響)。但是因為我也以互動方式使用該程序,所以我不想一直移動/刪除我的配置文件。根據我的批處理作業在集群上安排的時間(基於其他使用者的使用情況),(順便說一句:網路文件性能這麼慢可能是一個錯誤,但我只是集群的使用者,所以我只能解決它,而不是修復它。)
我可以建構一個不讀取配置文件(或具有不讀取配置文件的命令行選項)的程序版本以供批量使用,但該程序的建構環境設計不佳且難以設置。我更喜歡使用通過我係統的包管理器安裝的二進製文件。
如何欺騙該程序的特定實例假裝我的配置文件不存在(不修改程序)?我希望有一個表格的包裝
pretendfiledoesntexist ~/.config/myprogram -- myprogram --various-options...
,但我對其他解決方案持開放態度。
該程序可能會從
$HOME/.config/myprogram
. 所以你可以告訴它你的主目錄在其他地方,比如:HOME=/nowhere your-program
現在,也許你的程序需要你的主目錄中的一些其他資源。如果您知道它們是什麼,您可以為您的程序準備一個虛假首頁,其中包含指向它所需資源的連結。
mkdir -p ~/myprogram-home/.config ln -s ~/.Xauthority ~/myprogram-home/ ... HOME=~/myprogram-home myprogram
如果所有其他方法都失敗了,請編寫一個您將使用注入的包裝庫,
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
部分工作。看看它如何處理像and
fakeroot
之類的呼叫。getuid(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; } }