|
|
#!/bin/bash
# # This shell-script genereates the fl_wrapper.c source file.
cat << EOT /* ROCK Linux Wrapper for getting a list of created files * * --- ROCK-COPYRIGHT-NOTE-BEGIN --- * * This copyright note is auto-generated by ./scripts/Create-CopyPatch. * Please add additional copyright information _after_ the line containing * the ROCK-COPYRIGHT-NOTE-END tag. Otherwise it might get removed by * the ./scripts/Create-CopyPatch script. Do not edit this copyright text! * * ROCK Linux: rock-src/misc/tools-source/fl_wrapper.c.sh * ROCK Linux is Copyright (C) 1998 - 2005 Clifford Wolf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. A copy of the GNU General Public * License can be found at Documentation/COPYING. * * Many people helped and are helping developing ROCK Linux. Please * have a look at http://www.rocklinux.org/ and the Documentation/TEAM * file for details. * * --- ROCK-COPYRIGHT-NOTE-END --- * * gcc -Wall -O2 -ldl -shared -o fl_wrapper.so fl_wrapper.c * * !!! THIS FILE IS AUTO-GENERATED BY $0 !!! * * ELF Dynamic Loading Documentation: * - http://www.linuxdoc.org/HOWTO/GCC-HOWTO-7.html * - http://www.educ.umu.se/~bjorn/mhonarc-files/linux-gcc/msg00576.html * - /usr/include/dlfcn.h */
/* Headers and prototypes */
#define DEBUG 0 #define DLOPEN_LIBC 1
#define _GNU_SOURCE #define _REENTRANT
#define open xxx_open #define open64 xxx_open64 #define mknod xxx_mknod
# include <dlfcn.h> # include <errno.h> # include <fcntl.h> # include <stdio.h> # include <stdlib.h> # include <string.h> # include <sys/stat.h> # include <sys/types.h> # include <unistd.h> # include <utime.h> # include <stdarg.h>
#undef mknod #undef open #undef open64
static void * get_dl_symbol(char *);
struct status_t { ino_t inode; off_t size; time_t mtime; time_t ctime; };
static void handle_file_access_before(const char *, const char *, struct status_t *); static void handle_file_access_after(const char *, const char *, struct status_t *);
char *wlog = 0, *rlog = 0, *cmdname = "unkown";
/* Wrapper Functions */ EOT
# This has been made with cpp-macros before until they turned to be absolutely # unreadable ... # add_wrapper() { line="$( echo "$*" | sed 's/ *, */,/g' )" old_ifs="$IFS" ; IFS="," ; set $line ; IFS="$old_ifs"
ret_type=$1 ; shift ; function=$1 ; shift p1="" ; p2="" ; for x ; do p1="$p1$x, " ; done for x ; do x="${x%%\[\]}" ; p2="$p2${x##* }, " ; done p1="${p1%, }" ; p2="${p2%, }"
if [ "${function#exec}" = "${function}" ] then echo ; cat << EOT extern $ret_type $function($p1); $ret_type (*orig_$function)($p1) = 0;
$ret_type $function($p1) { struct status_t status; int old_errno=errno; $ret_type rc;
handle_file_access_before("$function", f, &status); if (!orig_$function) orig_$function = get_dl_symbol("$function"); errno=old_errno;
#if DEBUG == 1 fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original $function() at %p (wrapper is at %p).\n", getpid(), orig_$function, $function); #endif rc = orig_$function($p2);
old_errno=errno; handle_file_access_after("$function", f, &status); errno=old_errno;
return rc; } EOT else echo ; cat << EOT extern $ret_type $function($p1); $ret_type (*orig_$function)($p1) = 0;
$ret_type $function($p1) { int old_errno=errno;
handle_file_access_after("$function", f, 0); if (!orig_$function) orig_$function = get_dl_symbol("$function"); errno=old_errno;
return orig_$function($p2); } EOT fi }
add_wrapper 'FILE*, fopen, const char* f, const char* g' add_wrapper 'FILE*, fopen64, const char* f, const char* g'
add_wrapper 'int, creat, const char* f, mode_t m' add_wrapper 'int, creat64, const char* f, mode_t m'
add_wrapper 'int, mkdir, const char* f, mode_t m' add_wrapper 'int, mknod, const char* f, mode_t m, dev_t d'
add_wrapper 'int, link, const char* s, const char* f' add_wrapper 'int, symlink, const char* s, const char* f' add_wrapper 'int, rename, const char* s, const char* f'
add_wrapper 'int, utime, const char* f, const struct utimbuf* t' add_wrapper 'int, utimes, const char* f, struct timeval* t'
add_wrapper 'int, execv, const char* f, char* const a[]' add_wrapper 'int, execve, const char* f, char* const a[], char* const e[]'
echo cat fl_wrapper_execl.c cat fl_wrapper_open.c
echo ; cat << "EOT" /* Internal Functions */
static void * get_dl_symbol(char * symname) { void * rc; #if DLOPEN_LIBC static void * libc_handle = 0;
if (!libc_handle) libc_handle=dlopen("libc.so.6", RTLD_LAZY); if (!libc_handle) { printf("fl_wrapper.so: Can't dlopen libc: %s\n", dlerror()); abort(); }
rc = dlsym(libc_handle, symname); # if DEBUG == 1 fprintf(stderr, "fl_wrapper.so debug [%d]: Symbol '%s' in libc (%p) has been resolved to %p.\n", getpid(), symname, libc_handle, rc); # endif #else rc = dlsym(RTLD_NEXT, symname); # if DEBUG == 1 fprintf(stderr, "fl_wrapper.so debug [%d]: Symbol '%s' (RTLD_NEXT) has been resolved to %p.\n", getpid(), symname, rc); # endif #endif if (!rc) { printf("fl_wrapper.so: Can't resolve %s: %s\n", symname, dlerror()); abort(); }
return rc; }
static int pid2ppid(int pid) { char buffer[100]; int fd, rc, ppid = 0;
sprintf(buffer, "/proc/%d/stat", pid); if ( (fd = open(buffer, O_RDONLY, 0)) < 0 ) return 0; if ( (rc = read(fd, buffer, 99)) > 0) { buffer[rc] = 0; /* format: 27910 (bash) S 27315 ... */ sscanf(buffer, "%*[^ ] %*[^ ] %*[^ ] %d", &ppid); } close(fd);
return ppid; }
/* this is only called from fl_wrapper_init(). so it doesn't need to be * reentrant. */ static char *getpname(int pid) { static char p[512]; char buffer[100]=""; char *arg=0, *b; int i, fd, rc;
sprintf(buffer, "/proc/%d/cmdline", pid); if ( (fd = open(buffer, O_RDONLY, 0)) < 0 ) return "unkown"; if ( (rc = read(fd, buffer, 99)) > 0) { buffer[rc--] = 0; for (i=0; i<rc; i++) if (!buffer[i]) { arg = buffer+i+1; break; } } close(fd);
b = basename(buffer); snprintf(p, 512, "%s", b);
if ( !strcmp(b, "bash") || !strcmp(b, "sh") || !strcmp(b, "perl") ) if (arg && *arg && *arg != '-') snprintf(p, 512, "%s(%s)", b, basename(arg));
return p; }
/* invert the order by recursion. there will be only one recursion tree * so we can use a static var for managing the last ent */ static void addptree(int *txtpos, char *cmdtxt, int pid, int basepid) { static char l[512] = ""; char *p;
if (!pid || pid == basepid) return;
addptree(txtpos, cmdtxt, pid2ppid(pid), basepid);
p = getpname(pid);
if ( strcmp(l, p) ) *txtpos += snprintf(cmdtxt+*txtpos, 4096-*txtpos, "%s%s", *txtpos ? "." : "", getpname(pid)); else *txtpos += snprintf(cmdtxt+*txtpos, 4096-*txtpos, "*");
strcpy(l, p); }
void __attribute__ ((constructor)) fl_wrapper_init() { char cmdtxt[4096] = ""; char *basepid_txt = getenv("FLWRAPPER_BASEPID"); int basepid = 0, txtpos=0;
if (basepid_txt) basepid = atoi(basepid_txt);
addptree(&txtpos, cmdtxt, getpid(), basepid); cmdname = strdup(cmdtxt);
wlog = getenv("FLWRAPPER_WLOG"); rlog = getenv("FLWRAPPER_RLOG"); }
static void handle_file_access_before(const char * func, const char * file, struct status_t * status) { struct stat st; #if DEBUG == 1 fprintf(stderr, "fl_wrapper.so debug [%d]: begin of handle_file_access_before(\"%s\", \"%s\", xxx)\n", getpid(), func, file); #endif if ( lstat(file,&st) ) { status->inode=0; status->size=0; status->mtime=0; status->ctime=0; } else { status->inode=st.st_ino; status->size=st.st_size; status->mtime=st.st_mtime; status->ctime=st.st_ctime; } #if DEBUG == 1 fprintf(stderr, "fl_wrapper.so debug [%d]: end of handle_file_access_before(\"%s\", \"%s\", xxx)\n", getpid(), func, file); #endif }
static void handle_file_access_after(const char * func, const char * file, struct status_t * status) { char buf[512], *buf2, *logfile; int fd; struct stat st;
#if DEBUG == 1 fprintf(stderr, "fl_wrapper.so debug [%d]: begin of handle_file_access_after(\"%s\", \"%s\", xxx)\n", getpid(), func, file); #endif if ( wlog != 0 && !strcmp(file, wlog) ) return; if ( rlog != 0 && !strcmp(file, rlog) ) return; if ( lstat(file, &st) ) return;
if ( (status != 0) && (status->inode != st.st_ino || status->size != st.st_size || status->mtime != st.st_mtime || status->ctime != st.st_ctime) ) { logfile = wlog; } else { logfile = rlog; }
if ( logfile == 0 ) return; fd=open(logfile,O_APPEND|O_WRONLY,0); if (fd == -1) return;
if (file[0] == '/') { sprintf(buf,"%s.%s:\t%s\n", cmdname, func, file); } else { buf2=get_current_dir_name(); sprintf(buf,"%s.%s:\t%s%s%s\n", cmdname, func, buf2, strcmp(buf2,"/") ? "/" : "", file); free(buf2); } write(fd,buf,strlen(buf)); close(fd); #if DEBUG == 1 fprintf(stderr, "fl_wrapper.so debug [%d]: end of handle_file_access_after(\"%s\", \"%s\", xxx)\n", getpid(), func, file); #endif } EOT
|