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.

352 lines
9.0 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 - 2004 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. * gcc -Wall -O2 -ldl -shared -o fl_wrapper.so fl_wrapper.c
  30. *
  31. * !!! THIS FILE IS AUTO-GENERATED BY $0 !!!
  32. *
  33. * ELF Dynamic Loading Documentation:
  34. * - http://www.linuxdoc.org/HOWTO/GCC-HOWTO-7.html
  35. * - http://www.educ.umu.se/~bjorn/mhonarc-files/linux-gcc/msg00576.html
  36. * - /usr/include/dlfcn.h
  37. */
  38. /* Headers and prototypes */
  39. #define DEBUG 0
  40. #define DLOPEN_LIBC 1
  41. #define _GNU_SOURCE
  42. #define _REENTRANT
  43. #define open xxx_open
  44. #define open64 xxx_open64
  45. #define mknod xxx_mknod
  46. # include <dlfcn.h>
  47. # include <errno.h>
  48. # include <fcntl.h>
  49. # include <stdio.h>
  50. # include <stdlib.h>
  51. # include <string.h>
  52. # include <sys/stat.h>
  53. # include <sys/types.h>
  54. # include <unistd.h>
  55. # include <utime.h>
  56. # include <stdarg.h>
  57. #undef mknod
  58. #undef open
  59. #undef open64
  60. static void * get_dl_symbol(char *);
  61. struct status_t {
  62. ino_t inode;
  63. off_t size;
  64. time_t mtime;
  65. time_t ctime;
  66. };
  67. static void handle_file_access_before(const char *, const char *, struct status_t *);
  68. static void handle_file_access_after(const char *, const char *, struct status_t *);
  69. char *wlog = 0, *rlog = 0, *cmdname = "unkown";
  70. /* Wrapper Functions */
  71. EOT
  72. # This has been made with cpp-macros before until they turned to be absolutely
  73. # unreadable ...
  74. #
  75. add_wrapper()
  76. {
  77. line="$( echo "$*" | sed 's/ *, */,/g' )"
  78. old_ifs="$IFS" ; IFS="," ; set $line ; IFS="$old_ifs"
  79. ret_type=$1 ; shift ; function=$1 ; shift
  80. p1="" ; p2="" ; for x ; do p1="$p1$x, " ; done
  81. for x ; do x="${x%%\[\]}" ; p2="$p2${x##* }, " ; done
  82. p1="${p1%, }" ; p2="${p2%, }"
  83. if [ "${function#exec}" = "${function}" ]
  84. then
  85. echo ; cat << EOT
  86. extern $ret_type $function($p1);
  87. $ret_type (*orig_$function)($p1) = 0;
  88. $ret_type $function($p1)
  89. {
  90. struct status_t status;
  91. int old_errno=errno;
  92. $ret_type rc;
  93. handle_file_access_before("$function", f, &status);
  94. if (!orig_$function) orig_$function = get_dl_symbol("$function");
  95. errno=old_errno;
  96. #if DEBUG == 1
  97. fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original $function() at %p (wrapper is at %p).\n",
  98. getpid(), orig_$function, $function);
  99. #endif
  100. rc = orig_$function($p2);
  101. old_errno=errno;
  102. handle_file_access_after("$function", f, &status);
  103. errno=old_errno;
  104. return rc;
  105. }
  106. EOT
  107. else
  108. echo ; cat << EOT
  109. extern $ret_type $function($p1);
  110. $ret_type (*orig_$function)($p1) = 0;
  111. $ret_type $function($p1)
  112. {
  113. int old_errno=errno;
  114. handle_file_access_after("$function", f, 0);
  115. if (!orig_$function) orig_$function = get_dl_symbol("$function");
  116. errno=old_errno;
  117. return orig_$function($p2);
  118. }
  119. EOT
  120. fi
  121. }
  122. add_wrapper 'FILE*, fopen, const char* f, const char* g'
  123. add_wrapper 'FILE*, fopen64, const char* f, const char* g'
  124. add_wrapper 'int, creat, const char* f, mode_t m'
  125. add_wrapper 'int, creat64, const char* f, mode_t m'
  126. add_wrapper 'int, mkdir, const char* f, mode_t m'
  127. add_wrapper 'int, mknod, const char* f, mode_t m, dev_t d'
  128. add_wrapper 'int, link, const char* s, const char* f'
  129. add_wrapper 'int, symlink, const char* s, const char* f'
  130. add_wrapper 'int, rename, const char* s, const char* f'
  131. add_wrapper 'int, utime, const char* f, const struct utimbuf* t'
  132. add_wrapper 'int, utimes, const char* f, struct timeval* t'
  133. add_wrapper 'int, execv, const char* f, char* const a[]'
  134. add_wrapper 'int, execve, const char* f, char* const a[], char* const e[]'
  135. echo
  136. cat fl_wrapper_execl.c
  137. cat fl_wrapper_open.c
  138. echo ; cat << "EOT"
  139. /* Internal Functions */
  140. static void * get_dl_symbol(char * symname)
  141. {
  142. void * rc;
  143. #if DLOPEN_LIBC
  144. static void * libc_handle = 0;
  145. if (!libc_handle) libc_handle=dlopen("libc.so.6", RTLD_LAZY);
  146. if (!libc_handle) {
  147. printf("fl_wrapper.so: Can't dlopen libc: %s\n", dlerror());
  148. abort();
  149. }
  150. rc = dlsym(libc_handle, symname);
  151. # if DEBUG == 1
  152. fprintf(stderr, "fl_wrapper.so debug [%d]: Symbol '%s' in libc (%p) has been resolved to %p.\n",
  153. getpid(), symname, libc_handle, rc);
  154. # endif
  155. dlclose(libc_handle);
  156. #else
  157. rc = dlsym(RTLD_NEXT, symname);
  158. # if DEBUG == 1
  159. fprintf(stderr, "fl_wrapper.so debug [%d]: Symbol '%s' (RTLD_NEXT) has been resolved to %p.\n",
  160. getpid(), symname, rc);
  161. # endif
  162. #endif
  163. if (!rc) {
  164. printf("fl_wrapper.so: Can't resolve %s: %s\n",
  165. symname, dlerror());
  166. abort();
  167. }
  168. return rc;
  169. }
  170. static int pid2ppid(int pid)
  171. {
  172. char buffer[100];
  173. int fd, rc, ppid = 0;
  174. sprintf(buffer, "/proc/%d/stat", pid);
  175. if ( (fd = open(buffer, O_RDONLY, 0)) < 0 ) return 0;
  176. if ( (rc = read(fd, buffer, 99)) > 0) {
  177. buffer[rc] = 0;
  178. /* format: 27910 (bash) S 27315 ... */
  179. sscanf(buffer, "%*[^ ] %*[^ ] %*[^ ] %d", &ppid);
  180. }
  181. close(fd);
  182. return ppid;
  183. }
  184. /* this is only called from fl_wrapper_init(). so it doesn't need to be
  185. * reentrant. */
  186. static char *getpname(int pid)
  187. {
  188. static char p[512];
  189. char buffer[100]="";
  190. char *arg=0, *b;
  191. int i, fd, rc;
  192. sprintf(buffer, "/proc/%d/cmdline", pid);
  193. if ( (fd = open(buffer, O_RDONLY, 0)) < 0 ) return "unkown";
  194. if ( (rc = read(fd, buffer, 99)) > 0) {
  195. buffer[rc--] = 0;
  196. for (i=0; i<rc; i++)
  197. if (!buffer[i]) { arg = buffer+i+1; break; }
  198. }
  199. close(fd);
  200. b = basename(buffer);
  201. snprintf(p, 512, "%s", b);
  202. if ( !strcmp(b, "bash") || !strcmp(b, "sh") || !strcmp(b, "perl") )
  203. if (arg && *arg && *arg != '-')
  204. snprintf(p, 512, "%s(%s)", b, basename(arg));
  205. return p;
  206. }
  207. /* invert the order by recursion. there will be only one recursion tree
  208. * so we can use a static var for managing the last ent */
  209. static void addptree(int *txtpos, char *cmdtxt, int pid, int basepid)
  210. {
  211. static char l[512] = "";
  212. char *p;
  213. if (!pid || pid == basepid) return;
  214. addptree(txtpos, cmdtxt, pid2ppid(pid), basepid);
  215. p = getpname(pid);
  216. if ( strcmp(l, p) )
  217. *txtpos += snprintf(cmdtxt+*txtpos, 4096-*txtpos, "%s%s",
  218. *txtpos ? "." : "", getpname(pid));
  219. else
  220. *txtpos += snprintf(cmdtxt+*txtpos, 4096-*txtpos, "*");
  221. strcpy(l, p);
  222. }
  223. void __attribute__ ((constructor)) fl_wrapper_init()
  224. {
  225. char cmdtxt[4096] = "";
  226. char *basepid_txt = getenv("FLWRAPPER_BASEPID");
  227. int basepid = 0, txtpos=0;
  228. if (basepid_txt)
  229. basepid = atoi(basepid_txt);
  230. addptree(&txtpos, cmdtxt, getpid(), basepid);
  231. cmdname = strdup(cmdtxt);
  232. wlog = getenv("FLWRAPPER_WLOG");
  233. rlog = getenv("FLWRAPPER_RLOG");
  234. }
  235. static void handle_file_access_before(const char * func, const char * file,
  236. struct status_t * status)
  237. {
  238. struct stat st;
  239. #if DEBUG == 1
  240. fprintf(stderr, "fl_wrapper.so debug [%d]: begin of handle_file_access_before(\"%s\", \"%s\", xxx)\n",
  241. getpid(), func, file);
  242. #endif
  243. if ( lstat(file,&st) ) {
  244. status->inode=0; status->size=0;
  245. status->mtime=0; status->ctime=0;
  246. } else {
  247. status->inode=st.st_ino; status->size=st.st_size;
  248. status->mtime=st.st_mtime; status->ctime=st.st_ctime;
  249. }
  250. #if DEBUG == 1
  251. fprintf(stderr, "fl_wrapper.so debug [%d]: end of handle_file_access_before(\"%s\", \"%s\", xxx)\n",
  252. getpid(), func, file);
  253. #endif
  254. }
  255. static void handle_file_access_after(const char * func, const char * file,
  256. struct status_t * status)
  257. {
  258. char buf[512], *buf2, *logfile;
  259. int fd; struct stat st;
  260. #if DEBUG == 1
  261. fprintf(stderr, "fl_wrapper.so debug [%d]: begin of handle_file_access_after(\"%s\", \"%s\", xxx)\n",
  262. getpid(), func, file);
  263. #endif
  264. if ( wlog != 0 && !strcmp(file, wlog) ) return;
  265. if ( rlog != 0 && !strcmp(file, rlog) ) return;
  266. if ( lstat(file, &st) ) return;
  267. if ( (status != 0) && (status->inode != st.st_ino ||
  268. status->size != st.st_size || status->mtime != st.st_mtime ||
  269. status->ctime != st.st_ctime) ) { logfile = wlog; }
  270. else { logfile = rlog; }
  271. if ( logfile == 0 ) return;
  272. fd=open(logfile,O_APPEND|O_WRONLY,0);
  273. if (fd == -1) return;
  274. if (file[0] == '/') {
  275. sprintf(buf,"%s.%s:\t%s\n",
  276. cmdname, func, file);
  277. } else {
  278. buf2=get_current_dir_name();
  279. sprintf(buf,"%s.%s:\t%s%s%s\n",
  280. cmdname, func, buf2,
  281. strcmp(buf2,"/") ? "/" : "", file);
  282. free(buf2);
  283. }
  284. write(fd,buf,strlen(buf));
  285. close(fd);
  286. #if DEBUG == 1
  287. fprintf(stderr, "fl_wrapper.so debug [%d]: end of handle_file_access_after(\"%s\", \"%s\", xxx)\n",
  288. getpid(), func, file);
  289. #endif
  290. }
  291. EOT