你在你的代碼,它是固定在下面的示例中的一些問題(我還添加相關的報頭,並提供了main
給一個完整的程序):
#include <stdio.h>
#include <dlfcn.h>
FILE* (*my_fopen)(const char *filename, const char* mode);
void* libc_handle;
void __attribute__ ((constructor)) init(void){
libc_handle = dlopen("libc.so.6", RTLD_LAZY);
my_fopen = dlsym(libc_handle,"fopen");
}
FILE* fopen(const char* filename, const char* mode){
printf("Hello, Pax\n");
return my_fopen(filename, mode);
}
int main (void) {
FILE *fout = fopen ("xyzzy.txt","w");
fclose (fout);
return 0;
}
從什麼變化你提供如下:
my_fopen
函數指針應該就是一個指針。我懷疑你可能認爲FILE*
是這樣做的,但這實際上並不正確。要指定返回指針的功能指針,您需要FILE * (*fn)(blah, blah)
。
換句話說,該函數的第一個參數必須是const char *
,指針。你只需要const char
。
您實際上並不需要用於設置my_fopen
指針(轉換,取消地址,取消引用)的複雜表達式。你可以使用更簡單的my_fopen = ...
。事實上,我認爲在這種情況下,演員可能實際上是在阻止gcc
報告錯誤,因爲它假設,如果你投了,你知道你在做什麼。
您可能還應該檢查返回值dlopen
。在這段代碼中,我沒有這樣做,但是,如果您因爲某種原因未找到(或無法加載)庫,那麼後面的行可能會導致您的悲傷。
當我編譯和Red Hat Enterprise Linux Workstation release 6.4 (Santiago)
運行這個程序,我得到的Hello, Pax
和文件xyzzy.txt
創建輸出。
而且,只是作爲一個之外,還有可能被用來訪問文件系統等功能,像open
,opendir
,freopen
,creat
,mkfifo
(我認爲)。
根據您的需要,您可能需要做一些額外的工作。
一個你可能要考慮的事情是,ls
可能連使用fopen
。它實際上可以用opendir/readdir
和stat
來構建。
所以,我們使用一個程序,我們知道調用fopen
。輸入以下程序qqtest.c
:
#include <stdio.h>
int main (void) {
FILE *fh = fopen ("xyzzy.txt", "w");
fclose (fh);
return 0;
}
與gcc -o qqtest qqtest.c
編譯它,然後運行它。您應該看不到輸出,但應該創建文件xyzzy.txt
。一旦您已確認,刪除xyzzy.txt
文件,然後輸入以下程序qq.c
:
#include <stdio.h>
#include <dlfcn.h>
FILE* (*my_fopen)(const char *filename, const char* mode);
void* libc_handle;
void __attribute__ ((constructor)) init(void){
libc_handle = dlopen("libc.so.6", RTLD_LAZY);
my_fopen = dlsym(libc_handle,"fopen");
}
FILE* fopen(const char* filename, const char* mode){
printf("Hello, Pax\n");
return my_fopen(filename, mode);
}
與gcc -shared -o qq.so qq.c -ldl
這編譯並運行您的程序qqtest
(改變共享對象的路徑到自己的課程目錄):
LD_PRELOAD=/home/pax/qq.so ./qqtest
這個時候,你應該看到Hello, Pax
串輸出創建xyzzy.txt
文件之前,證明了它的呼喚你的包裝函數,這反過來又調用原始fopen
。現在
,這一切都非常好,但是,即使一旦你得到這個位的工作,你必須攔截相當多的不同的調用,以確保您捕獲所有的變化。
這需要一段時間才能完成,正如Chris Stratton在評論中指出的那樣,Linux內核已具有能夠向您報告文件系統更改。
如果你的目標是隻跟蹤文件系統的變化,而不是教育自己如何可以做到,看看inotify來看看如何做到這一點,而不必重新發明輪子。
我會掛鉤'而不是'fopen'。 –
你有沒有考慮inotify? –
@MatteoItalia,我打開了鉤子,但沒有用來打開文件。我認爲fopen()等使用私有方法\ __ open(),我不認爲我可以掛鉤到 – user1734905