Та ошибка была произведена ядром. Вы могли попытаться обновить ядро, чтобы видеть, была ли проблема решена.
Эта программа, вероятно, разрешает путь к этому файлу из $HOME/.config/myprogram
. Таким образом, вы можете сказать, что ваш домашний каталог находится в другом месте, например:
HOME=/nowhere your-program
Теперь, возможно, вашей программе нужен какой-нибудь другой ресурс в вашем домашнем каталоге. Если вы знаете, какие они, вы можете подготовить фальшивый дом для вашей программы со ссылками на ресурс, который ей там нужен.
mkdir -p ~/myprogram-home/.config
ln -s ~/.Xauthority ~/myprogram-home/
...
HOME=~/myprogram-home myprogram
Это должно быть возможно с профсоюзами / aufs. Вы создаете chroot
окружение для процесса. Вы используете реальный каталог в качестве слоя только для чтения и ставите поверх него пустой каталог. Затем вы монтируете том unionfs в соответствующий каталог в среде chroot
и удаляете файл там. Процесс не увидит его, но все остальные увидят.
Если все остальное не удастся, напишите библиотеку оберток, которую вы вставите с помощью LD_PRELOAD
, чтобы вызов open("/home/you/my-program/config.interactive")
был перехвачен, но прошел через любую другую библиотеку. Это работает для любого типа программ, даже скриптов оболочки, так как будет фильтровать системные вызовы.
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
работает.
Посмотрите, как 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()
Edit: Видимо есть флаг ld
, который можно включить (-обертка <символ>
), что позволяет писать обертки, не прибегая к двойной линковке:
/* 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;
}
}
Уберите свой файл конфигурации и запишите обертку сценария командной строки для интерактивного сценария использования, которая копирует файл в его обычное место назначения, запускает программу и удаляет его при выходе.
Переименуйте файл конфигурации, например, в config.interactive
. Создайте другой пустой файл, например config.script
.
Теперь создайте мягкую ссылку под названием config
(или что бы приложение ни ожидало в качестве конфигурационного файла) на нужную вам реальную конфигурацию и запустите ваше приложение.
ln -s config.interactive config
После этого не забудьте привести свою ссылку в порядок.
Если вы точно охарактеризовали , как ваша программа использует конфигурационный файл,
Я пропустил это.
Многие программы (такие как bash
и vi
) будут проверять на наличие конфигурационного файла
сразу же после запуска; если файл существует, прочитайте его и закройте.
Эти программы больше никогда не обращаются к этим инициализационным файлам.
Если ваша программа такая, читайте дальше.
Я знаю, что вы отвергли ответы, которые делают конфигурационный файл по-настоящему несуществующим. (переименовывая его), но у меня есть морщина, которую я не видел ни у кого другого. Делайте это, когда вызываете программу в пакетном режиме:
DELAY_TIME=1
REALPATH="~/.config/myprogram"
HOLDPATH="${REALPATH}.hold"
mv "$REALPATH" "$HOLDPATH"
(sleep "$DELAY_TIME"; mv "$HOLDPATH" "$REALPATH")&
myprogram
Это сдвигает с места конфигурационный файл,
но затем переносит его на одну секунду позже, даже если мипрограмма
все еще работает.
Это создает очень короткое окно времени, в течение которого файл недоступен -
какова вероятность интерактивного запуска программы во время этого окна?
(Даже если вы это сделаете, вы можете просто выйти и перезапустить программу,
и конфигурационный файл, вероятно, вернётся на место.)
Это действительно создаёт условия гонки; если программе потребуется слишком много времени для открытия файла, он может получить настоящий файл. Если такое случается достаточно часто, чтобы это стало проблемой, просто увеличьте значение DELAY_TIME.
Мне нравится ответ Стефана, но это трюк любая программа полагает, что какой-либо файл пустой - (потому что его папка временно указывает на фактически пустой файл) :
cat <./test.txt
###OUTPUT###
notempty
mount --bind /dev/null ./test.txt
cat <./test.txt
###NO OUTPUT###
umount ./test.txt
cat <./test.txt
###OUTPUT###
notempty
Вы также можете:
mount --bind ./someotherconfig.conf ./unwanted.conf
Если хотите.