プロセスが同じファイル名を持つ別のファイルを読み取るようにします。

プロセスが同じファイル名を持つ別のファイルを読み取るようにします。

ファイルを読み取るアプリケーションがあります。そう呼ぶプロセス名とファイル~/.構成。いつプロセス名実行すると常に読みます。~/.構成そして別の方法で構成することはできません。以前とそれ以降に「~/.configuration」に依存する他のアプリケーションがありますが、それ以降はそうではありません。プロセス名ランニング。

パッケージプロセス名コンテンツを置き換えるスクリプトで~/.構成オプションですが、最近停電(内容が置き換えられたとき)が発生し、ファイルの以前の内容が失われたため、お勧めできません。

LD_DEBUG=files processname特定のファイルを読み取ろうとするときにプロセスが他のものを読むように欺く方法(おそらく関連性の高いものを使用するかもしれません)はありますか?実行可能ファイル内でファイル名を検索して変更することは、やや侵害的ですが、うまくいくでしょう。

呼び出しを引き継ぐためにカーネルモジュールを書くことが可能であることを知っていますopen()https://news.ycombinator.com/item?id=2972958)、しかし、より簡単でクリーンな方法はありますか?

編集:検索するとき~/.構成内部にプロセス名実行可能ファイルを読み取る前に別のファイル名を読み取ろうとしました。~/.構成。問題が解決しました。

答え1

最新バージョンのLinuxでは、次のことができます。共有をキャンセルこれマウントネームスペース。つまり、仮想ファイルシステムを別々に表示するプロセス(別々にマウントされたファイルシステム)を起動できます。

これはを通じて行うことができますが、chrootあなたunshareの場合にはより適しています。

同様に、名前空間をマウントするにはスーパーユーザー権限がchroot必要です。unshare

~/.configurationだから、あなたがファイルを持っているとしましょう~/.configuration-for-that-cmd

実際にバインドマウントプロセスを開始して実行でき~/.configurationます~/.configuration-for-that-cmdthat-cmd

良い:

sudo unshare -m sh -c "
   mount --bind '$HOME/.configuration-for-that-cmd' \
                '$HOME/.configuration' &&
     exec that-cmd"

that-cmdすべてのサブプロセスは互いに異なって表示されます~/.configuration

that-cmd上記は次のように実行されますrootsudo -u another-user that-cmd必要に応じて、次のように実行されます。他のユーザー

答え2

ソフトリンク。

2つの構成ファイルを作成し、ほとんどの場合ソフトリンクを使用して1つを指しますが、特別なアプリケーションが実行されている場合は他のファイルを指すようにソフトリンクを変更します。

(これはひどいハッキングであることを知っていますが、ファイルの内容を変更するよりもやや安定しています。)

または$ HOMEを操作してください。

面倒なプロセスを開始するスクリプトで$ HOMEを通常の$ HOMEディレクトリの下のエントリに設定すると、アプリケーションはその場所にある設定ファイルを使用する必要があります(デフォルトのシェルコマンドで動作するようにテストされ、〜は$ HOMEに展開されます)。

プロセスが実行する他の操作によって$ HOMEを変更すると、意図しない結果が生じる可能性があります(つまり、出力ファイルが間違った場所にある可能性があります)。

答え3

以下を使用してこれを実行できます。LD_PRELOAD技術。これは、特定のプレフィックスで始まるパスを別の場所にマッピングする実装です。コードはgithubにもあります。

たとえば、/etc/ルートにならずにファイルの存在を偽造できます。これは/etc/ownCloud/sync-exclude.list、ファイルが存在しない場合に動作を拒否するowncloudクライアントに必要です。

これは、あるディレクトリを別のディレクトリにマッピングする機能をオーバーライドすることopen()で機能します(例:。open64()open()/etc/ownCloud/.../home/user1/.etc/ownCloud/...

を調整し、path_mapプリロードされたlibを使用してプログラムをコンパイルして実行します。

gcc -std=c99 -Wall -shared -fPIC path-mapping.c -o path-mapping.so -ldl

LD_PRELOAD=/path/to/my/path-mapping.so someprogram

ソースコードpath-mapping.c:

#define _GNU_SOURCE

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <dlfcn.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdarg.h>
#include <malloc.h>

// List of path pairs. Paths beginning with the first item will be
// translated by replacing the matching part with the second item.
static const char *path_map[][2] = {
    { "/etc/ownCloud/", "/home/user1/.etc/ownCloud/" },
};

__thread char *buffer = NULL;
__thread int buffer_size = -1;

typedef FILE* (*orig_fopen_func_type)(const char *path, const char *mode);
typedef int (*orig_open_func_type)(const char *pathname, int flags, ...);

static int starts_with(const char *str, const char *prefix) {
    return (strncmp(prefix, str, strlen(prefix)) == 0);
}

static char *get_buffer(int min_size) {
    int step = 63;
    if (min_size < 1) {
        min_size = 1;
    }
    if (min_size > buffer_size) {
        if (buffer != NULL) {
            free(buffer);
            buffer = NULL;
            buffer_size = -1;
        }
        buffer = malloc(min_size + step);
        if (buffer != NULL) {
            buffer_size = min_size + step;
        }
    }
    return buffer;
}

static const char *fix_path(const char *path)
{
    int count = (sizeof path_map) / (sizeof *path_map); // Array length
    for (int i = 0; i < count; i++) {
        const char *prefix = path_map[i][0];
        const char *replace = path_map[i][1];
        if (starts_with(path, prefix)) {
            const char *rest = path + strlen(prefix);
            char *new_path = get_buffer(strlen(path) + strlen(replace) - strlen(prefix));
            strcpy(new_path, replace);
            strcat(new_path, rest);
            printf("Mapped Path: %s  ==>  %s\n", path, new_path);
            return new_path;
        }
    }
    return path;
}


int open(const char *pathname, int flags, ...)
{
    const char *new_path = fix_path(pathname);

    orig_open_func_type orig_func;
    orig_func = (orig_open_func_type)dlsym(RTLD_NEXT, "open");

    // If O_CREAT is used to create a file, the file access mode must be given.
    if (flags & O_CREAT) {
        va_list args;
        va_start(args, flags);
        int mode = va_arg(args, int);
        va_end(args);
        return orig_func(new_path, flags, mode);
    } else {
        return orig_func(new_path, flags);
    }
}

int open64(const char *pathname, int flags, ...)
{
    const char *new_path = fix_path(pathname);

    orig_open_func_type orig_func;
    orig_func = (orig_open_func_type)dlsym(RTLD_NEXT, "open64");

    // If O_CREAT is used to create a file, the file access mode must be given.
    if (flags & O_CREAT) {
        va_list args;
        va_start(args, flags);
        int mode = va_arg(args, int);
        va_end(args);
        return orig_func(new_path, flags, mode);
    } else {
        return orig_func(new_path, flags);
    }
}

関連情報