Как обмануть процесс, заставив его думать, что файл не существует?

Как обмануть процесс, заставив его думать, что файл не существует?

У меня есть программа, которая хранит свои настройки, и ~/.config/myprogramя использую ее как в интерактивном режиме, так и с пакетной системой очередей. При интерактивном запуске я хочу, чтобы эта программа использовала мои файлы конфигурации (и она это делает). Но при запуске в пакетном режиме файлы конфигурации не нужны, потому что я указываю параметры командной строки, которые перезаписывают все соответствующие настройки. Кроме того, доступ к файлам конфигурации по сети увеличивает время запуска программы на несколько секунд; если файлы отсутствуют, программа запускается намного быстрее (поскольку каждое задание занимает всего около минуты, это существенно влияет на пропускную способность пакетного задания). Но поскольку я также использую программу в интерактивном режиме, я не хочу постоянно перемещать/удалять свои файлы конфигурации. В зависимости от того, когда мои пакетные задания планируются в кластере (на основе использования другими пользователями), я могу захотеть использовать программу в интерактивном режиме и как часть пакетного задания одновременно.

(Кстати: низкая производительность сетевых файлов, вероятно, является ошибкой, но я всего лишь пользователь кластера, поэтому могу только обойти ее, но не исправить.)

Я мог бы создать версию программы, которая не читает файлы конфигурации (или имеет опцию командной строки, чтобы не читать) для пакетного использования, но среда сборки этой программы плохо спроектирована и сложна в настройке. Я бы предпочел использовать двоичные файлы, установленные через менеджер пакетов моей системы.

Как мне обмануть отдельные экземпляры этой программы, чтобы они делали вид, что мои файлы конфигурации не существуют (без изменения программы)? Я надеюсь на оболочку в форме pretendfiledoesntexist ~/.config/myprogram -- myprogram --various-options..., но я открыт для других решений.

решение1

Эта программа, вероятно, определяет путь к этому файлу из $HOME/.config/myprogram. Таким образом, вы можете указать ей, что ваш домашний каталог находится в другом месте, например:

HOME=/nowhere your-program

Теперь, возможно, your-program нуждается в каком-то другом ресурсе в вашем домашнем каталоге. Если вы знаете, что это за ресурс, вы можете подготовить фальшивый дом для 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")был перехвачен, но любой другой прошел. Это работает для любого типа программы, даже для скриптов оболочки, поскольку она будет фильтровать системные вызовы.

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()

Редактировать:ВидимоСуществует 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

Уберите свой конфигурационный файл и напишите оболочку сценария оболочки для интерактивного использования, которая копирует файл в его обычное место назначения, запускает программу и удаляет ее при выходе.

решение4

Переименуйте файл конфигурации в eg config.interactive. Создайте еще один пустой файл с именем eg config.script.

Теперь создайте мягкую ссылку под названием config(или как приложение ожидает ее в качестве файла конфигурации) на любую реальную конфигурацию, которая вам нужна, и запустите свое приложение.

ln -s config.interactive config

Не забудьте потом привести ссылку в порядок.

Связанный контент