mirror of the now-defunct rocklinux.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

274 lines
7.5 KiB

#!/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 - 2003 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
void * get_dl_symbol(char *);
struct status_t {
ino_t inode;
off_t size;
time_t mtime;
time_t ctime;
};
void handle_file_access_before(const char *, const char *, struct status_t *);
void handle_file_access_after(const char *, const char *, struct status_t *);
/* 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) = NULL;
extern $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) = NULL;
extern $ret_type $function($p1) {
int old_errno=errno;
handle_file_access_after("$function", f, NULL);
if (!orig_$function) orig_$function = get_dl_symbol("$function");
errno=old_errno;
return orig_$function($p2);
}
EOT
fi
}
add_wrapper 'int, open, const char* f, int a, int b'
add_wrapper 'int, open64, const char* f, int a, int b'
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
echo ; cat << "EOT"
/* Internal Functions */
void * get_dl_symbol(char * symname) {
void * rc;
#if DLOPEN_LIBC
static void * libc_handle = NULL;
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
dlclose(libc_handle);
#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;
}
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
}
char *wlog = NULL, *rlog = NULL;
void handle_file_access_after(const char * func, const char * file,
struct status_t * status) {
char buf[512], *buf2, *logfile;
char cmdname[512] = "unknown";
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
fd=readlink("/proc/self/exe", cmdname, 512);
if (fd < 1) strcpy(cmdname, "unknown");
else cmdname[fd] = 0;
if ( wlog == NULL ) wlog = getenv("FLWRAPPER_WLOG");
if ( rlog == NULL ) rlog = getenv("FLWRAPPER_RLOG");
if ( wlog != NULL && !strcmp(file, wlog) ) return;
if ( rlog != NULL && !strcmp(file, rlog) ) return;
if ( lstat(file, &st) ) return;
if ( (status != NULL) && (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 == NULL ) return;
fd=open(logfile,O_APPEND|O_WRONLY,0);
if (fd == -1) return;
if (file[0] == '/') {
sprintf(buf,"%s.%s:\t%s\n",
basename(cmdname), func, file);
} else {
buf2=get_current_dir_name();
sprintf(buf,"%s.%s:\t%s%s%s\n",
basename(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