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.

369 lines
9.5 KiB

  1. #!/bin/bash
  2. #
  3. # This shell-script genereates the fl_wrapper.c source file.
  4. cat << EOT
  5. /* ROCK Linux Wrapper for getting a list of created files
  6. *
  7. * --- ROCK-COPYRIGHT-NOTE-BEGIN ---
  8. *
  9. * This copyright note is auto-generated by ./scripts/Create-CopyPatch.
  10. * Please add additional copyright information _after_ the line containing
  11. * the ROCK-COPYRIGHT-NOTE-END tag. Otherwise it might get removed by
  12. * the ./scripts/Create-CopyPatch script. Do not edit this copyright text!
  13. *
  14. * ROCK Linux: rock-src/misc/tools-source/fl_wrapper.c.sh
  15. * ROCK Linux is Copyright (C) 1998 - 2006 Clifford Wolf
  16. *
  17. * This program is free software; you can redistribute it and/or modify
  18. * it under the terms of the GNU General Public License as published by
  19. * the Free Software Foundation; either version 2 of the License, or
  20. * (at your option) any later version. A copy of the GNU General Public
  21. * License can be found at Documentation/COPYING.
  22. *
  23. * Many people helped and are helping developing ROCK Linux. Please
  24. * have a look at http://www.rocklinux.org/ and the Documentation/TEAM
  25. * file for details.
  26. *
  27. * --- ROCK-COPYRIGHT-NOTE-END ---
  28. *
  29. * Copyright (C) 2004-2005 The T2 SDE Project
  30. *
  31. * gcc -Wall -O2 -ldl -shared -o fl_wrapper.so fl_wrapper.c
  32. *
  33. * !!! THIS FILE IS AUTO-GENERATED BY $0 !!!
  34. *
  35. * ELF Dynamic Loading Documentation:
  36. * - http://www.linuxdoc.org/HOWTO/GCC-HOWTO-7.html
  37. * - http://www.educ.umu.se/~bjorn/mhonarc-files/linux-gcc/msg00576.html
  38. * - /usr/include/dlfcn.h
  39. */
  40. /* Headers and prototypes */
  41. #define DEBUG 0
  42. #define DLOPEN_LIBC 1
  43. #define _GNU_SOURCE
  44. #define _REENTRANT
  45. #define open xxx_open
  46. #define open64 xxx_open64
  47. #define mknod xxx_mknod
  48. #define _LARGEFILE_SOURCE
  49. #define _LARGEFILE64_SOURCE
  50. # include <dlfcn.h>
  51. # include <errno.h>
  52. # include <fcntl.h>
  53. # include <stdio.h>
  54. # include <stdlib.h>
  55. # include <string.h>
  56. # include <sys/stat.h>
  57. # include <sys/types.h>
  58. # include <unistd.h>
  59. # include <utime.h>
  60. # include <stdarg.h>
  61. #undef _LARGEFILE64_SOURCE
  62. #undef _LARGEFILE_SOURCE
  63. #undef mknod
  64. #undef open
  65. #undef open64
  66. static void * get_dl_symbol(char *);
  67. struct status_t {
  68. ino_t inode;
  69. off_t size;
  70. time_t mtime;
  71. time_t ctime;
  72. };
  73. static void handle_file_access_before(const char *, const char *, struct status_t *);
  74. static void handle_file_access_after(const char *, const char *, struct status_t *);
  75. char *wlog = 0, *rlog = 0, *cmdname = "unkown";
  76. /* Wrapper Functions */
  77. EOT
  78. # This has been made with cpp-macros before until they turned to be absolutely
  79. # unreadable ...
  80. #
  81. add_wrapper()
  82. {
  83. line="$( echo "$*" | sed 's/ *, */,/g' )"
  84. old_ifs="$IFS" ; IFS="," ; set $line ; IFS="$old_ifs"
  85. ret_type=$1 ; shift ; function=$1 ; shift
  86. p1="" ; p2="" ; for x ; do p1="$p1$x, " ; done
  87. for x ; do x="${x%%\[\]}" ; p2="$p2${x##* }, " ; done
  88. p1="${p1%, }" ; p2="${p2%, }"
  89. if [ "${function#exec}" = "${function}" ]
  90. then
  91. echo ; cat << EOT
  92. extern $ret_type $function($p1);
  93. $ret_type (*orig_$function)($p1) = 0;
  94. $ret_type $function($p1)
  95. {
  96. struct status_t status;
  97. int old_errno=errno;
  98. $ret_type rc;
  99. handle_file_access_before("$function", f, &status);
  100. if (!orig_$function) orig_$function = get_dl_symbol("$function");
  101. errno=old_errno;
  102. #if DEBUG == 1
  103. fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original $function() at %p (wrapper is at %p).\n",
  104. getpid(), orig_$function, $function);
  105. #endif
  106. rc = orig_$function($p2);
  107. old_errno=errno;
  108. handle_file_access_after("$function", f, &status);
  109. errno=old_errno;
  110. return rc;
  111. }
  112. EOT
  113. else
  114. echo ; cat << EOT
  115. extern $ret_type $function($p1);
  116. $ret_type (*orig_$function)($p1) = 0;
  117. $ret_type $function($p1)
  118. {
  119. int old_errno=errno;
  120. handle_file_access_after("$function", f, 0);
  121. if (!orig_$function) orig_$function = get_dl_symbol("$function");
  122. errno=old_errno;
  123. return orig_$function($p2);
  124. }
  125. EOT
  126. fi
  127. }
  128. add_wrapper 'FILE*, fopen, const char* f, const char* g'
  129. add_wrapper 'FILE*, fopen64, const char* f, const char* g'
  130. add_wrapper 'int, creat, const char* f, mode_t m'
  131. add_wrapper 'int, creat64, const char* f, mode_t m'
  132. add_wrapper 'int, mkdir, const char* f, mode_t m'
  133. add_wrapper 'int, mknod, const char* f, mode_t m, dev_t d'
  134. add_wrapper 'int, link, const char* s, const char* f'
  135. add_wrapper 'int, symlink, const char* s, const char* f'
  136. add_wrapper 'int, rename, const char* s, const char* f'
  137. add_wrapper 'int, utime, const char* f, const struct utimbuf* t'
  138. add_wrapper 'int, utimes, const char* f, struct timeval* t'
  139. add_wrapper 'int, execv, const char* f, char* const a[]'
  140. add_wrapper 'int, execve, const char* f, char* const a[], char* const e[]'
  141. echo
  142. cat fl_wrapper_execl.c
  143. cat fl_wrapper_open.c
  144. echo ; cat << "EOT"
  145. /* Internal Functions */
  146. static void * get_dl_symbol(char * symname)
  147. {
  148. void * rc;
  149. #if DLOPEN_LIBC
  150. static void * libc_handle = 0;
  151. if (!libc_handle) libc_handle=dlopen("libc.so.6", RTLD_LAZY);
  152. if (!libc_handle) {
  153. printf("fl_wrapper.so: Can't dlopen libc: %s\n", dlerror());
  154. abort();
  155. }
  156. rc = dlsym(libc_handle, symname);
  157. # if DEBUG == 1
  158. fprintf(stderr, "fl_wrapper.so debug [%d]: Symbol '%s' in libc (%p) has been resolved to %p.\n",
  159. getpid(), symname, libc_handle, rc);
  160. # endif
  161. #else
  162. rc = dlsym(RTLD_NEXT, symname);
  163. # if DEBUG == 1
  164. fprintf(stderr, "fl_wrapper.so debug [%d]: Symbol '%s' (RTLD_NEXT) has been resolved to %p.\n",
  165. getpid(), symname, rc);
  166. # endif
  167. #endif
  168. if (!rc) {
  169. printf("fl_wrapper.so: Can't resolve %s: %s\n",
  170. symname, dlerror());
  171. abort();
  172. }
  173. return rc;
  174. }
  175. static int pid2ppid(int pid)
  176. {
  177. char buffer[100];
  178. int fd, rc, ppid = 0;
  179. sprintf(buffer, "/proc/%d/stat", pid);
  180. if ( (fd = open(buffer, O_RDONLY, 0)) < 0 ) return 0;
  181. if ( (rc = read(fd, buffer, 99)) > 0) {
  182. buffer[rc] = 0;
  183. /* format: 27910 (bash) S 27315 ... */
  184. sscanf(buffer, "%*[^ ] %*[^ ] %*[^ ] %d", &ppid);
  185. }
  186. close(fd);
  187. return ppid;
  188. }
  189. /* this is only called from fl_wrapper_init(). so it doesn't need to be
  190. * reentrant. */
  191. static char *getpname(int pid)
  192. {
  193. static char p[512];
  194. char buffer[513]="";
  195. char *arg=0, *b;
  196. int i, fd, rc;
  197. sprintf(buffer, "/proc/%d/cmdline", pid);
  198. if ( (fd = open(buffer, O_RDONLY, 0)) < 0 ) return "unkown";
  199. if ( (rc = read(fd, buffer, 512)) > 0) {
  200. buffer[rc--] = 0;
  201. for (i=0; i<rc; i++)
  202. if (buffer[i] == 0 && buffer[i+1] != '-')
  203. { arg = buffer+i+1; break; }
  204. }
  205. close(fd);
  206. b = basename(buffer);
  207. snprintf(p, 512, "%s", b);
  208. if ( !strcmp(b, "bash") || !strcmp(b, "sh") ||
  209. !strcmp(b, "perl") || !strcmp(b, "python") )
  210. if ( arg && *arg &&
  211. strlen(arg) < 100 && !strchr(arg, '\n') &&
  212. !strchr(arg, ' ') && !strchr(arg, ';') )
  213. snprintf(p, 512, "%s(%s)", b, basename(arg));
  214. return p;
  215. }
  216. /* invert the order by recursion. there will be only one recursion tree
  217. * so we can use a static var for managing the last ent */
  218. static void addptree(int *txtpos, char *cmdtxt, int pid, int basepid)
  219. {
  220. static char l[512] = "";
  221. char *p;
  222. if (!pid || pid == basepid) return;
  223. addptree(txtpos, cmdtxt, pid2ppid(pid), basepid);
  224. p = getpname(pid);
  225. if (*txtpos < 4000)
  226. if ( strcmp(l, p) )
  227. *txtpos += snprintf(cmdtxt+*txtpos, 4096-*txtpos, "%s%s",
  228. *txtpos ? "." : "", getpname(pid));
  229. else
  230. *txtpos += snprintf(cmdtxt+*txtpos, 4096-*txtpos, "*");
  231. strcpy(l, p);
  232. }
  233. void __attribute__ ((constructor)) fl_wrapper_init()
  234. {
  235. char cmdtxt[4096] = "";
  236. char *basepid_txt = getenv("FLWRAPPER_BASEPID");
  237. int basepid = 0, txtpos=0;
  238. if (basepid_txt)
  239. basepid = atoi(basepid_txt);
  240. addptree(&txtpos, cmdtxt, getpid(), basepid);
  241. cmdname = strdup(cmdtxt);
  242. wlog = getenv("FLWRAPPER_WLOG");
  243. rlog = getenv("FLWRAPPER_RLOG");
  244. }
  245. static void handle_file_access_before(const char * func, const char * file,
  246. struct status_t * status)
  247. {
  248. struct stat st;
  249. #if DEBUG == 1
  250. fprintf(stderr, "fl_wrapper.so debug [%d]: begin of handle_file_access_before(\"%s\", \"%s\", xxx)\n",
  251. getpid(), func, file);
  252. #endif
  253. if ( lstat(file,&st) ) {
  254. status->inode=0; status->size=0;
  255. status->mtime=0; status->ctime=0;
  256. } else {
  257. status->inode=st.st_ino; status->size=st.st_size;
  258. status->mtime=st.st_mtime; status->ctime=st.st_ctime;
  259. }
  260. #if DEBUG == 1
  261. fprintf(stderr, "fl_wrapper.so debug [%d]: end of handle_file_access_before(\"%s\", \"%s\", xxx)\n",
  262. getpid(), func, file);
  263. #endif
  264. }
  265. static void handle_file_access_after(const char * func, const char * file,
  266. struct status_t * status)
  267. {
  268. char buf[512], *buf2, *logfile;
  269. int fd; struct stat st;
  270. #if DEBUG == 1
  271. fprintf(stderr, "fl_wrapper.so debug [%d]: begin of handle_file_access_after(\"%s\", \"%s\", xxx)\n",
  272. getpid(), func, file);
  273. #endif
  274. if ( wlog != 0 && !strcmp(file, wlog) ) return;
  275. if ( rlog != 0 && !strcmp(file, rlog) ) return;
  276. if ( lstat(file, &st) ) return;
  277. if ( (status != 0) && (status->inode != st.st_ino ||
  278. status->size != st.st_size || status->mtime != st.st_mtime ||
  279. status->ctime != st.st_ctime) ) { logfile = wlog; }
  280. else { logfile = rlog; }
  281. if ( logfile == 0 ) return;
  282. #ifdef __USE_LARGEFILE
  283. fd=open64(logfile,O_APPEND|O_WRONLY|O_LARGEFILE,0);
  284. #else
  285. #warning "The wrapper library will not work properly for large logs!"
  286. fd=open(logfile,O_APPEND|O_WRONLY,0);
  287. #endif
  288. if (fd == -1) return;
  289. if (file[0] == '/') {
  290. sprintf(buf,"%s.%s:\t%s\n",
  291. cmdname, func, file);
  292. } else {
  293. buf2=get_current_dir_name();
  294. sprintf(buf,"%s.%s:\t%s%s%s\n",
  295. cmdname, func, buf2,
  296. strcmp(buf2,"/") ? "/" : "", file);
  297. free(buf2);
  298. }
  299. write(fd,buf,strlen(buf));
  300. close(fd);
  301. #if DEBUG == 1
  302. fprintf(stderr, "fl_wrapper.so debug [%d]: end of handle_file_access_after(\"%s\", \"%s\", xxx)\n",
  303. getpid(), func, file);
  304. #endif
  305. }
  306. EOT