Stefan Fiedler: add missing parts of fl_wrapper with file descriptor tracking (part 1) diff -N -du rock-linux/misc/tools-source/fd_tracker.c misc/tools-source/fd_tracker.c --- misc/tools-source/fd_tracker.c 1970-01-01 01:00:00.000000000 +0100 +++ misc/tools-source/fd_tracker.c 2006-09-24 16:58:23.000000000 +0200 @@ -0,0 +1,223 @@ + +/* + TODO: + get rid of the compiler warnings: + +fl_wrapper.c: In function '_Exit': +fl_wrapper.c:1100: warning: 'noreturn' function does return +fl_wrapper.c: In function '_exit': +fl_wrapper.c:1075: warning: 'noreturn' function does return +fl_wrapper.c: In function 'exit': +fl_wrapper.c:1050: warning: 'noreturn' function does return + + maybe TODO: + wrape clone(); catch termination of child process created with clone() +*/ + +# if FD_TRACKER == 1 + +/* + + Whenever a new file descriptor is opened, it will/should be added to the + fl_wrapper-internal register, together with its current file status. + Accordingly, when a file descriptor is closed, it will be removed from this + register, and handle_file_access_after() will be called with the stored + filename and status. +*/ + +struct pid_reg +{ + pid_t id; + int executed; + struct fd_reg *fd_head; + struct pid_reg *next; +}; + +struct pid_reg *pid_head = 0; + +struct fd_reg +{ + int fd; + int closed; + struct status_t status; + char *filename; + struct fd_reg *next; +}; + +void add_pid(pid_t pid) +{ + struct pid_reg *newpid = malloc(sizeof(struct pid_reg)); + + newpid->id = pid; + newpid->fd_head = 0; + newpid->executed = 0; + + newpid->next = pid_head; + pid_head = newpid; + +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: PID %d added.\n", + getpid(), pid); +# endif +} + +void add_fd(struct pid_reg *pid, int fd, const char *filename, struct status_t *status) +{ + struct fd_reg *newfd = malloc(sizeof(struct fd_reg)); + + newfd->fd = fd; + newfd->closed = 0; + newfd->status = *status; + newfd->filename = strdup(filename); + + newfd->next = pid->fd_head; + pid->fd_head = newfd; + +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: fd %d (%s) added.\n", + getpid(), fd, filename); +# endif +} + +void remove_fd(struct fd_reg **fd); + +void remove_pid(struct pid_reg **pid) +{ + struct pid_reg *tmp = *pid; + struct fd_reg **fd_iter = &(*pid)->fd_head; + +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: PID %d removed.\n", + getpid(), (*pid)->id); +# endif + + while (*fd_iter) remove_fd(fd_iter); + *pid = (*pid)->next; + free(tmp); +} + +void remove_fd(struct fd_reg **fd) +{ + struct fd_reg *tmp = *fd; + +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: fd %d (%s) removed.\n", + getpid(), (*fd)->fd, (*fd)->filename); +# endif + + free((*fd)->filename); + *fd = (*fd)->next; + free(tmp); +} + +void deregister_fd(int fd); + +struct pid_reg **find_pid(pid_t pid) +{ + struct pid_reg **pid_iter = &pid_head; + + while (*pid_iter) + { + if ((*pid_iter)->executed) + { + struct fd_reg **fd_iter = &(*pid_iter)->fd_head; + while (*fd_iter) + { + if ((*fd_iter)->closed) + { + handle_file_access_after("exec*", (*fd_iter)->filename, &(*fd_iter)->status); + deregister_fd((*fd_iter)->fd); + + } + else fd_iter = &(*fd_iter)->next; + } + } + + if ((*pid_iter)->fd_head == 0) remove_pid(pid_iter); + else pid_iter = &(*pid_iter)->next; + } + + pid_iter = &pid_head; + while (*pid_iter) + { + if ((*pid_iter)->id == pid) break; + pid_iter = &(*pid_iter)->next; + } + + return pid_iter; +} + +struct fd_reg **find_fd(struct pid_reg *pid, int fd) +{ + struct fd_reg **fd_iter = &pid->fd_head; + while (*fd_iter) + { + if ((*fd_iter)->fd == fd) break; + fd_iter = &(*fd_iter)->next; + } + + return fd_iter; +} + +void register_fd(int fd, const char *filename, struct status_t *status) +{ + struct pid_reg *pid_iter = *find_pid(getpid()); + if (pid_iter == 0) + { + add_pid(getpid()); + pid_iter = pid_head; + } + + struct fd_reg *fd_iter = *find_fd(pid_iter, fd); + if (fd_iter == 0) + { + add_fd(pid_iter, fd, filename, status); + } else { +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: fd %d already registered (is %s, was %s).\n", + getpid(), fd, filename, fd_iter->filename); +# endif + free(fd_iter->filename); + fd_iter->filename = strdup(filename); + fd_iter->status = *status; + } +} + +/* removes fd from register, returning its filename and status via filename + and status arguments. +*/ +void deregister_fd(int fd) +{ + struct pid_reg **pid_iter = find_pid(getpid()); + if (*pid_iter) + { + struct fd_reg **fd_iter = find_fd(*pid_iter, fd); + if (*fd_iter) + { + remove_fd(fd_iter); + if ((*pid_iter)->fd_head == 0) remove_pid(pid_iter); + } + } +} + +void copy_fds(pid_t parent, pid_t child) +{ + struct pid_reg *pid_iter = *find_pid(parent); + if (pid_iter) + { + struct fd_reg *fd_iter = pid_iter->fd_head; + + add_pid(child); + struct fd_reg **nextfd = &pid_head->fd_head; + + while (fd_iter) + { + *nextfd = malloc(sizeof(struct fd_reg)); + **nextfd = *fd_iter; + nextfd = &(*nextfd)->next; + fd_iter = fd_iter->next; + } + } +} + +# endif diff -N -du rock-linux/misc/tools-source/fl_wrapper_close.c misc/tools-source/fl_wrapper_close.c --- misc/tools-source/fl_wrapper_close.c 1970-01-01 01:00:00.000000000 +0100 +++ misc/tools-source/fl_wrapper_close.c 2006-09-24 16:58:23.000000000 +0200 @@ -0,0 +1,234 @@ +extern int close(int fd); +int (*orig_close)(int fd) = 0; + +int close(int fd) +{ + int old_errno=errno; + int rc; + + if (!orig_close) orig_close = get_dl_symbol("close"); +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original close(%d) at %p (wrapper is at %p).\n", + getpid(), fd, orig_close, close); +# endif + + errno=old_errno; + rc = orig_close(fd); + old_errno=errno; + +# if FD_TRACKER == 1 + if (rc == 0 || errno == EBADF) + { + struct pid_reg *pidreg = *find_pid(getpid()); + if (pidreg) + { + struct fd_reg *fdreg = *find_fd(pidreg, fd); + if (fdreg) + { + handle_file_access_after("close", fdreg->filename, &fdreg->status); + deregister_fd(fd); + } + } + } +# endif + + errno=old_errno; + return rc; +} + +extern int fclose(FILE* f); +int (*orig_fclose)(FILE* f) = 0; + +int fclose(FILE* f) +{ + int old_errno=errno; + int rc; + int fd=fileno(f); + + if (!orig_fclose) orig_fclose = get_dl_symbol("fclose"); +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original fclose(%d) at %p (wrapper is at %p).\n", + getpid(), fd, orig_fclose, fclose); +# endif + + errno=old_errno; + rc = orig_fclose(f); + old_errno=errno; + +# if FD_TRACKER == 1 + if (rc == 0) + { + struct pid_reg *pidreg = *find_pid(getpid()); + if (pidreg) + { + struct fd_reg *fdreg = *find_fd(pidreg, fd); + if (fdreg) + { + handle_file_access_after("fclose", fdreg->filename, &fdreg->status); + deregister_fd(fd); + } + } + } +# endif + + errno=old_errno; + return rc; +} + +/* +extern int fcloseall(); +int (*orig_fcloseall)() = 0; + +int fcloseall() +{ + int old_errno=errno; + int rc; + + if (!orig_fcloseall) orig_fcloseall = get_dl_symbol("fcloseall"); +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original fcloseall() at %p (wrapper is at %p).\n", + getpid(), orig_fcloseall, fcloseall); +# endif + + errno=old_errno; + rc = orig_fcloseall(); + + return rc; +} +*/ + +extern int fork(); +int (*orig_fork)() = 0; + +int fork() +{ + int old_errno = errno; + int rc; +# if FD_TRACKER == 1 + int caller_pid = getpid(); +# endif + + if (!orig_fork) orig_fork = get_dl_symbol("fork"); +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original fork() at %p (wrapper is at %p).\n", + getpid(), orig_fork, fork); +# endif + + errno = old_errno; + rc = orig_fork(); + old_errno = errno; + +# if FD_TRACKER == 1 + if ( rc == 0) copy_fds(caller_pid, getpid()); +# endif + +# if DEBUG == 1 + struct pid_reg *pid = pid_head; + while (pid) + { + struct fd_reg *fd = pid->fd_head; + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: fork: found PID %d.\n", + getpid(), pid->id); + while (fd) + { + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: fork: found fd %d (%s).\n", + getpid(), fd->fd, fd->filename); + fd = fd->next; + } + pid = pid->next; + } +# endif + + errno=old_errno; + return rc; +} + +extern void exit(int status) __attribute__ ((noreturn)); +void (*orig_exit)(int status) = 0; + +void exit(int status) +{ + int old_errno = errno; + + if (!orig_exit) orig_exit = get_dl_symbol("exit"); +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original exit(%d) at %p (wrapper is at %p).\n", + getpid(), status, orig_exit, exit); +# endif + +# if FD_TRACKER == 1 + struct pid_reg *pid = *find_pid(getpid()); + if (pid) + { + struct fd_reg **fd_iter = &pid->fd_head; + while (*fd_iter) + { + handle_file_access_after("exit", (*fd_iter)->filename, &(*fd_iter)->status); + deregister_fd((*fd_iter)->fd); + } + } +# endif + + errno=old_errno; + orig_exit(status); +} + +extern void _exit(int status) __attribute__ ((noreturn)); +void (*orig__exit)(int status) = 0; + +void _exit(int status) +{ + int old_errno = errno; + + if (!orig__exit) orig__exit = get_dl_symbol("_exit"); +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original _exit(%d) at %p (wrapper is at %p).\n", + getpid(), status, orig__exit, _exit); +# endif + +# if FD_TRACKER == 1 + struct pid_reg *pid = *find_pid(getpid()); + if (pid) + { + struct fd_reg **fd_iter = &pid->fd_head; + while (*fd_iter) + { + handle_file_access_after("_exit", (*fd_iter)->filename, &(*fd_iter)->status); + deregister_fd((*fd_iter)->fd); + } + } +# endif + + errno=old_errno; + orig__exit(status); +} + +extern void _Exit(int status) __attribute__ ((noreturn)); +void (*orig__Exit)(int status) = 0; + +void _Exit(int status) +{ + int old_errno = errno; + + if (!orig__Exit) orig__Exit = get_dl_symbol("_Exit"); +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original _Exit(%d) at %p (wrapper is at %p).\n", + getpid(), status, orig__Exit, _Exit); +# endif + +# if FD_TRACKER == 1 + struct pid_reg *pid = *find_pid(getpid()); + if (pid) + { + struct fd_reg **fd_iter = &pid->fd_head; + while (*fd_iter) + { + handle_file_access_after("_Exit", (*fd_iter)->filename, &(*fd_iter)->status); + deregister_fd((*fd_iter)->fd); + } + } +# endif + + errno=old_errno; + orig__Exit(status); +} diff -N -du rock-linux/misc/tools-source/fl_wrapper.c.sh misc/tools-source/fl_wrapper.c.sh --- misc/tools-source/fl_wrapper.c.sh 2006-07-22 18:33:55.000000000 +0200 +++ misc/tools-source/fl_wrapper.c.sh 2006-09-24 17:27:31.000000000 +0200 @@ -1,6 +1,6 @@ #!/bin/bash # -# This shell-script genereates the fl_wrapper.c source file. +# This shell-script generates the fl_wrapper.c source file. cat << EOT /* ROCK Linux Wrapper for getting a list of created files @@ -44,6 +44,7 @@ #define DEBUG 0 #define DLOPEN_LIBC 1 +#define FD_TRACKER 1 #define _GNU_SOURCE #define _REENTRANT @@ -66,6 +67,7 @@ # include # include # include +# include #undef _LARGEFILE64_SOURCE #undef _LARGEFILE_SOURCE @@ -88,6 +90,10 @@ char *wlog = 0, *rlog = 0, *cmdname = "unkown"; +# if DEBUG == 1 +int debug = 0; +# endif + /* Wrapper Functions */ EOT @@ -118,18 +124,19 @@ 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", +# if DEBUG == 1 + if (debug) 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); +# endif + errno=old_errno; + rc = orig_$function($p2); old_errno=errno; + handle_file_access_after("$function", f, &status); - errno=old_errno; + errno=old_errno; return rc; } EOT @@ -141,22 +148,64 @@ $ret_type $function($p1) { int old_errno=errno; + int rc; handle_file_access_after("$function", f, 0); if (!orig_$function) orig_$function = get_dl_symbol("$function"); + +# if FD_TRACKER == 1 + struct pid_reg *pid = *find_pid(getpid()); + struct fd_reg ** fd_iter; + if (pid) + { + fd_iter = &pid->fd_head; + while (*fd_iter != 0) + { + (*fd_iter)->closed = fcntl((*fd_iter)->fd, F_GETFD) & FD_CLOEXEC; + fd_iter = &(*fd_iter)->next; + } + pid->executed = 1; + } +# endif + +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original $function() at %p (wrapper is at %p).\n", + getpid(), orig_$function, $function); +# endif + errno=old_errno; + rc = orig_$function($p2); + old_errno=errno; - return orig_$function($p2); +# if FD_TRACKER == 1 + if (pid) + { + fd_iter = &pid->fd_head; + while (*fd_iter != 0) + { + (*fd_iter)->closed = 0; + fd_iter = &(*fd_iter)->next; + } + pid->executed = 0; + } +# endif + + errno=old_errno; + return rc; } EOT fi } -add_wrapper 'FILE*, fopen, const char* f, const char* g' -add_wrapper 'FILE*, fopen64, const char* f, const char* g' +echo +cat fd_tracker.c +cat fl_wrapper_execl.c +cat fl_wrapper_open.c +cat fl_wrapper_close.c -add_wrapper 'int, creat, const char* f, mode_t m' -add_wrapper 'int, creat64, const char* f, mode_t m' + +# add_wrapper 'FILE*, fopen, const char* f, const char* g' +# add_wrapper 'FILE*, fopen64, const char* f, const char* g' add_wrapper 'int, mkdir, const char* f, mode_t m' add_wrapper 'int, mknod, const char* f, mode_t m, dev_t d' @@ -171,10 +220,6 @@ 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 */ @@ -192,13 +237,13 @@ 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", + if (debug) 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", + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: Symbol '%s' (RTLD_NEXT) has been resolved to %p.\n", getpid(), symname, rc); # endif #endif @@ -274,17 +319,23 @@ p = getpname(pid); if (*txtpos < 4000) + { 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() { +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: fl_wrapper_init()\n", getpid()); +# endif + char cmdtxt[4096] = ""; char *basepid_txt = getenv("FLWRAPPER_BASEPID"); int basepid = 0, txtpos=0; @@ -297,16 +348,44 @@ wlog = getenv("FLWRAPPER_WLOG"); rlog = getenv("FLWRAPPER_RLOG"); +# if DEBUG == 1 + char *debugwrapper = getenv("FLWRAPPER_DEBUG"); + if (debugwrapper) debug = atoi(debugwrapper); +# endif +} + +/* + Clean up file descriptors still registered for this pid, if any. +*/ +void __attribute__ ((destructor)) fl_wrapper_finish() +{ +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: fl_wrapper_finish()\n", getpid()); +# endif + struct pid_reg **pid = find_pid(getpid()); + if (*pid) + { +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: PID still registered!\n", getpid()); +# endif + struct fd_reg **fd = &(*pid)->fd_head; + while (*fd) + { + handle_file_access_after("fl_wrapper_finish", (*fd)->filename, &(*fd)->status); + remove_fd(fd); + } + remove_pid(pid); + } } 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", +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: begin of handle_file_access_before(\"%s\", \"%s\", xxx)\n", getpid(), func, file); -#endif +# endif if ( lstat(file,&st) ) { status->inode=0; status->size=0; status->mtime=0; status->ctime=0; @@ -314,39 +393,77 @@ 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", +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: end of handle_file_access_before(\"%s\", \"%s\", xxx)\n", getpid(), func, file); -#endif +# endif } +/* + Declared in fl_wrapper_open.c and fl_wrapper_close.c, + reused here since logging access to the log files eventually + overwrites close'd but not yet deregistered file descriptors. + +int (*orig_open)(const char* f, int a, ...) = 0; +int (*orig_open64)(const char* f, int a, ...) = 0; +int (*orig_close)(int fd) = 0; +*/ + 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); +#ifdef __USE_LARGEFILE + if (!orig_open64) orig_open64 = get_dl_symbol("open64"); +#else + if (!orig_open) orig_open = get_dl_symbol("open"); #endif - if ( wlog != 0 && !strcmp(file, wlog) ) return; - if ( rlog != 0 && !strcmp(file, rlog) ) return; - if ( lstat(file, &st) ) return; + if (!orig_close) orig_close = get_dl_symbol("close"); +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: begin of handle_file_access_after(\"%s\", \"%s\", xxx), %d, %s, %s\n", + getpid(), func, file, status != 0, wlog, rlog); +# endif + + if ( lstat(file, &st) ) + { +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: lstat(%s, ...) failed\n", + getpid(), file); +# endif + 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; + if ( logfile == 0 ) + { +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: no log file\n", + getpid()); +# endif + return; + } + #ifdef __USE_LARGEFILE - fd=open64(logfile,O_APPEND|O_WRONLY|O_LARGEFILE,0); + fd=orig_open64(logfile,O_APPEND|O_WRONLY|O_LARGEFILE,0); #else #warning "The wrapper library will not work properly for large logs!" - fd=open(logfile,O_APPEND|O_WRONLY,0); + fd=orig_open(logfile,O_APPEND|O_WRONLY,0); #endif - if (fd == -1) return; + + if (fd == -1) + { +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: log open failed (%s)\n", + getpid(), strerror(errno)); +# endif + return; + } if (file[0] == '/') { sprintf(buf,"%s.%s:\t%s\n", @@ -359,11 +476,10 @@ 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", + orig_close(fd); +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: end of handle_file_access_after(\"%s\", \"%s\", xxx)\n", getpid(), func, file); -#endif +# endif } EOT - diff -N -du rock-linux/misc/tools-source/fl_wrapper_open.c misc/tools-source/fl_wrapper_open.c --- misc/tools-source/fl_wrapper_open.c 2006-07-22 18:33:55.000000000 +0200 +++ misc/tools-source/fl_wrapper_open.c 2006-09-24 17:20:11.000000000 +0200 @@ -35,10 +35,11 @@ if (!orig_open) orig_open = get_dl_symbol("open"); errno=old_errno; -#if DEBUG == 1 - fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original open() at %p (wrapper is at %p).\n", - getpid(), orig_open, open); -#endif +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original open(\"%s\", ...) at %p (wrapper is at %p).\n", + getpid(), f, orig_open, open); +# endif + if (a & O_CREAT) { va_list ap; @@ -52,11 +53,31 @@ } else rc = orig_open(f, a); - old_errno=errno; + +# if FD_TRACKER == 1 + if (rc != -1) + { + char *buf = 0; + int free_buf = 0; + if (f[0] != '/') + { + char *buf2 = get_current_dir_name(); + if (asprintf(&buf,"%s%s%s", buf2, + strcmp(buf2,"/") ? "/" : "", f) != -1) + { + f = buf; free_buf = 1; + } + free(buf2); + } + register_fd(rc, f, &status); + if (free_buf) free(buf); + } +# else handle_file_access_after("open", f, &status); - errno=old_errno; +# endif + errno=old_errno; return rc; } @@ -73,10 +94,11 @@ if (!orig_open64) orig_open64 = get_dl_symbol("open64"); errno=old_errno; -#if DEBUG == 1 - fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original open64() at %p (wrapper is at %p).\n", - getpid(), orig_open64, open64); -#endif +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original open64(\"%s\", ...) at %p (wrapper is at %p).\n", + getpid(), f, orig_open64, open64); +# endif + if (a & O_CREAT) { va_list ap; @@ -90,11 +112,346 @@ } else rc = orig_open64(f, a); - old_errno=errno; + +# if FD_TRACKER == 1 + if (rc != -1) + { + char *buf = 0; + int free_buf = 0; + if (f[0] != '/') + { + char *buf2 = get_current_dir_name(); + if (asprintf(&buf,"%s%s%s", buf2, + strcmp(buf2,"/") ? "/" : "", f) != -1) + { + f = buf; free_buf = 1; + } + free(buf2); + } + register_fd(rc, f, &status); + if (free_buf) free(buf); + } +# else handle_file_access_after("open64", f, &status); +# endif + + errno=old_errno; + return rc; +} + +extern int creat(const char* f, mode_t m); +int (*orig_creat)(const char* f, mode_t m) = 0; + +int creat(const char* f, mode_t m) +{ + struct status_t status; + int old_errno=errno; + int rc; + + handle_file_access_before("creat", f, &status); + if (!orig_creat) orig_creat = get_dl_symbol("creat"); +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original creat(\"%s\", ...) at %p (wrapper is at %p).\n", + getpid(), f, orig_creat, creat); +# endif + + errno=old_errno; + rc = orig_creat(f, m); + old_errno=errno; + +# if FD_TRACKER == 1 + if (rc != -1) + { + char *buf = 0; + int free_buf = 0; + if (f[0] != '/') + { + char *buf2 = get_current_dir_name(); + if (asprintf(&buf,"%s%s%s", buf2, + strcmp(buf2,"/") ? "/" : "", f) != -1) + { + f = buf; free_buf = 1; + } + free(buf2); + } + register_fd(rc, f, &status); + if (free_buf) free(buf); + } +# else + handle_file_access_after("creat", f, &status); +# endif + + errno=old_errno; + return rc; +} + +extern int creat64(const char* f, mode_t m); +int (*orig_creat64)(const char* f, mode_t m) = 0; + +int creat64(const char* f, mode_t m) +{ + struct status_t status; + int old_errno=errno; + int rc; + + handle_file_access_before("creat64", f, &status); + if (!orig_creat64) orig_creat64 = get_dl_symbol("creat64"); +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original creat64(%s, ...) at %p (wrapper is at %p).\n", + getpid(), f, orig_creat64, creat64); +# endif + errno=old_errno; + rc = orig_creat64(f, m); + old_errno=errno; +# if FD_TRACKER == 1 + if (rc != -1) + { + char *buf = 0; + int free_buf = 0; + if (f[0] != '/') + { + char *buf2 = get_current_dir_name(); + if (asprintf(&buf,"%s%s%s", buf2, + strcmp(buf2,"/") ? "/" : "", f) != -1) + { + f = buf; free_buf = 1; + } + free(buf2); + } + register_fd(rc, f, &status); + if (free_buf) free(buf); + } +# else + handle_file_access_after("creat64", f, &status); +# endif + + errno=old_errno; return rc; } +extern FILE* fopen(const char* f, const char* g); +FILE* (*orig_fopen)(const char* f, const char* g) = 0; + +FILE* fopen(const char* f, const char* g) +{ + struct status_t status; + int old_errno=errno; + FILE* rc; + + handle_file_access_before("fopen", f, &status); + if (!orig_fopen) orig_fopen = get_dl_symbol("fopen"); + +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original fopen() at %p (wrapper is at %p).\n", + getpid(), orig_fopen, fopen); +# endif + + errno=old_errno; + rc = orig_fopen(f, g); + old_errno=errno; + +# if FD_TRACKER == 1 + if (rc != 0) + { + char *buf = 0; + int free_buf = 0; + if (f[0] != '/') + { + char *buf2 = get_current_dir_name(); + if (asprintf(&buf,"%s%s%s", buf2, + strcmp(buf2,"/") ? "/" : "", f) != -1) + { + f = buf; free_buf = 1; + } + free(buf2); + } + register_fd(fileno(rc), f, &status); + if (free_buf) free(buf); + } +# else + handle_file_access_after("fopen", f, &status); +# endif + + errno=old_errno; + return rc; +} + +extern FILE* fopen64(const char* f, const char* g); +FILE* (*orig_fopen64)(const char* f, const char* g) = 0; + +FILE* fopen64(const char* f, const char* g) +{ + struct status_t status; + int old_errno=errno; + FILE* rc; + + handle_file_access_before("fopen64", f, &status); + if (!orig_fopen64) orig_fopen64 = get_dl_symbol("fopen64"); + +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original fopen64() at %p (wrapper is at %p).\n", + getpid(), orig_fopen64, fopen64); +# endif + + errno=old_errno; + rc = orig_fopen64(f, g); + old_errno=errno; + +# if FD_TRACKER == 1 + if (rc != 0) + { + char *buf = 0; + int free_buf = 0; + if (f[0] != '/') + { + char *buf2 = get_current_dir_name(); + if (asprintf(&buf,"%s%s%s", buf2, + strcmp(buf2,"/") ? "/" : "", f) != -1) + { + f = buf; free_buf = 1; + } + free(buf2); + } + register_fd(fileno(rc), f, &status); + if (free_buf) free(buf); + } +# else + handle_file_access_after("fopen64", f, &status); +# endif + + errno=old_errno; + return rc; +} + +extern int dup(int fd); +int (*orig_dup)(int fd) = 0; + +int dup(int fd) +{ + int old_errno = errno; + int rc; + + if (!orig_dup) orig_dup = get_dl_symbol("dup"); +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original dup(%d) at %p (wrapper is at %p).\n", + getpid(), fd, orig_dup, dup); +# endif + + errno=old_errno; + rc = orig_dup(fd); + old_errno = errno; + +# if FD_TRACKER == 1 + if (rc != -1) + { + struct pid_reg *pid = *find_pid(getpid()); + if (pid) + { + struct fd_reg *oldfd = *find_fd(pid, fd); + if (oldfd) register_fd(rc, oldfd->filename, &oldfd->status); + } + } +# endif + + errno=old_errno; + return rc; +} + +extern int dup2(int fd, int fd2); +int (*orig_dup2)(int fd, int fd2) = 0; + +int dup2(int oldfd, int newfd) +{ + int old_errno = errno; + int rc; + + if (!orig_dup2) orig_dup2 = get_dl_symbol("dup2"); +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original dup2(%d, %d) at %p (wrapper is at %p).\n", + getpid(), oldfd, newfd, orig_dup2, dup2); +# endif + + errno=old_errno; + rc = orig_dup2(oldfd, newfd); + old_errno = errno; + +# if FD_TRACKER == 1 + if (rc != -1) + { + struct pid_reg *pid = *find_pid(getpid()); + if (pid) + { + struct fd_reg *fd = *find_fd(pid, newfd); + if (fd && oldfd != newfd) + { + handle_file_access_after("dup2", fd->filename, &fd->status); + deregister_fd(newfd); + } + + fd = *find_fd(pid, oldfd); + if (fd) register_fd(rc, fd->filename, &fd->status); + } + } +# endif + + errno=old_errno; + return rc; +} + +extern int fcntl(int fd, int cmd, ...); +int (*orig_fcntl)(int fd, int cmd, ...) = 0; + +int fcntl(int fd, int cmd, ...) +{ + int old_errno = errno; + int rc; + int fd2 = -1; + + if (!orig_fcntl) orig_fcntl = get_dl_symbol("fcntl"); +# if DEBUG == 1 + if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original fcntl(%d, %d, ...) at %p (wrapper is at %p).\n", + getpid(), fd, cmd, orig_fcntl, fcntl); +# endif + + errno=old_errno; + if (cmd & F_GETLK || cmd & F_SETLK || cmd & F_SETLKW) + { + va_list ap; + struct flock *b = 0; + + va_start(ap, cmd); + b = va_arg(ap, struct flock*); + va_end(ap); + + rc = orig_fcntl(fd, cmd, b); + } else { + va_list ap; + long b = 0; + + va_start(ap, cmd); + b = va_arg(ap, long); + va_end(ap); + + rc = orig_fcntl(fd, cmd, b); + fd2 = (int) b; + } + old_errno = errno; + +# if FD_TRACKER == 1 + if (rc != -1 && cmd == F_DUPFD) + { + struct pid_reg *pid = *find_pid(getpid()); + if (pid) + { + struct fd_reg *oldfd = *find_fd(pid, fd); + if (oldfd) register_fd(rc, oldfd->filename, &oldfd->status); + } + } +# endif + + errno=old_errno; + return rc; +}