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.

485 lines
12 KiB

  1. #!/bin/bash
  2. #
  3. # This shell-script generates 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 FD_TRACKER 1
  44. #define _GNU_SOURCE
  45. #define _REENTRANT
  46. #define open xxx_open
  47. #define open64 xxx_open64
  48. #define mknod xxx_mknod
  49. #define _LARGEFILE_SOURCE
  50. #define _LARGEFILE64_SOURCE
  51. # include <dlfcn.h>
  52. # include <errno.h>
  53. # include <fcntl.h>
  54. # include <stdio.h>
  55. # include <stdlib.h>
  56. # include <string.h>
  57. # include <sys/stat.h>
  58. # include <sys/types.h>
  59. # include <unistd.h>
  60. # include <utime.h>
  61. # include <stdarg.h>
  62. # include <sched.h>
  63. #undef _LARGEFILE64_SOURCE
  64. #undef _LARGEFILE_SOURCE
  65. #undef mknod
  66. #undef open
  67. #undef open64
  68. static void * get_dl_symbol(char *);
  69. struct status_t {
  70. ino_t inode;
  71. off_t size;
  72. time_t mtime;
  73. time_t ctime;
  74. };
  75. static void handle_file_access_before(const char *, const char *, struct status_t *);
  76. static void handle_file_access_after(const char *, const char *, struct status_t *);
  77. char *wlog = 0, *rlog = 0, *cmdname = "unkown";
  78. # if DEBUG == 1
  79. int debug = 0;
  80. # endif
  81. /* Wrapper Functions */
  82. EOT
  83. # This has been made with cpp-macros before until they turned to be absolutely
  84. # unreadable ...
  85. #
  86. add_wrapper()
  87. {
  88. line="$( echo "$*" | sed 's/ *, */,/g' )"
  89. old_ifs="$IFS" ; IFS="," ; set $line ; IFS="$old_ifs"
  90. ret_type=$1 ; shift ; function=$1 ; shift
  91. p1="" ; p2="" ; for x ; do p1="$p1$x, " ; done
  92. for x ; do x="${x%%\[\]}" ; p2="$p2${x##* }, " ; done
  93. p1="${p1%, }" ; p2="${p2%, }"
  94. if [ "${function#exec}" = "${function}" ]
  95. then
  96. echo ; cat << EOT
  97. extern $ret_type $function($p1);
  98. $ret_type (*orig_$function)($p1) = 0;
  99. $ret_type $function($p1)
  100. {
  101. struct status_t status;
  102. int old_errno=errno;
  103. $ret_type rc;
  104. handle_file_access_before("$function", f, &status);
  105. if (!orig_$function) orig_$function = get_dl_symbol("$function");
  106. # if DEBUG == 1
  107. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original $function() at %p (wrapper is at %p).\n",
  108. getpid(), orig_$function, $function);
  109. # endif
  110. errno=old_errno;
  111. rc = orig_$function($p2);
  112. old_errno=errno;
  113. handle_file_access_after("$function", f, &status);
  114. errno=old_errno;
  115. return rc;
  116. }
  117. EOT
  118. else
  119. echo ; cat << EOT
  120. extern $ret_type $function($p1);
  121. $ret_type (*orig_$function)($p1) = 0;
  122. $ret_type $function($p1)
  123. {
  124. int old_errno=errno;
  125. int rc;
  126. handle_file_access_after("$function", f, 0);
  127. if (!orig_$function) orig_$function = get_dl_symbol("$function");
  128. # if FD_TRACKER == 1
  129. struct pid_reg *pid = *find_pid(getpid());
  130. struct fd_reg ** fd_iter;
  131. if (pid)
  132. {
  133. fd_iter = &pid->fd_head;
  134. while (*fd_iter != 0)
  135. {
  136. (*fd_iter)->closed = fcntl((*fd_iter)->fd, F_GETFD) & FD_CLOEXEC;
  137. fd_iter = &(*fd_iter)->next;
  138. }
  139. pid->executed = 1;
  140. }
  141. # endif
  142. # if DEBUG == 1
  143. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: going to run original $function() at %p (wrapper is at %p).\n",
  144. getpid(), orig_$function, $function);
  145. # endif
  146. errno=old_errno;
  147. rc = orig_$function($p2);
  148. old_errno=errno;
  149. # if FD_TRACKER == 1
  150. if (pid)
  151. {
  152. fd_iter = &pid->fd_head;
  153. while (*fd_iter != 0)
  154. {
  155. (*fd_iter)->closed = 0;
  156. fd_iter = &(*fd_iter)->next;
  157. }
  158. pid->executed = 0;
  159. }
  160. # endif
  161. errno=old_errno;
  162. return rc;
  163. }
  164. EOT
  165. fi
  166. }
  167. echo
  168. cat fd_tracker.c
  169. cat fl_wrapper_execl.c
  170. cat fl_wrapper_open.c
  171. cat fl_wrapper_close.c
  172. # add_wrapper 'FILE*, fopen, const char* f, const char* g'
  173. # add_wrapper 'FILE*, fopen64, const char* f, const char* g'
  174. add_wrapper 'int, mkdir, const char* f, mode_t m'
  175. add_wrapper 'int, mknod, const char* f, mode_t m, dev_t d'
  176. add_wrapper 'int, link, const char* s, const char* f'
  177. add_wrapper 'int, symlink, const char* s, const char* f'
  178. add_wrapper 'int, rename, const char* s, const char* f'
  179. add_wrapper 'int, utime, const char* f, const struct utimbuf* t'
  180. add_wrapper 'int, utimes, const char* f, struct timeval* t'
  181. add_wrapper 'int, execv, const char* f, char* const a[]'
  182. add_wrapper 'int, execve, const char* f, char* const a[], char* const e[]'
  183. echo ; cat << "EOT"
  184. /* Internal Functions */
  185. static void * get_dl_symbol(char * symname)
  186. {
  187. void * rc;
  188. #if DLOPEN_LIBC
  189. static void * libc_handle = 0;
  190. if (!libc_handle) libc_handle=dlopen("libc.so.6", RTLD_LAZY);
  191. if (!libc_handle) {
  192. printf("fl_wrapper.so: Can't dlopen libc: %s\n", dlerror());
  193. abort();
  194. }
  195. rc = dlsym(libc_handle, symname);
  196. # if DEBUG == 1
  197. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: Symbol '%s' in libc (%p) has been resolved to %p.\n",
  198. getpid(), symname, libc_handle, rc);
  199. # endif
  200. #else
  201. rc = dlsym(RTLD_NEXT, symname);
  202. # if DEBUG == 1
  203. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: Symbol '%s' (RTLD_NEXT) has been resolved to %p.\n",
  204. getpid(), symname, rc);
  205. # endif
  206. #endif
  207. if (!rc) {
  208. printf("fl_wrapper.so: Can't resolve %s: %s\n",
  209. symname, dlerror());
  210. abort();
  211. }
  212. return rc;
  213. }
  214. static int pid2ppid(int pid)
  215. {
  216. char buffer[100];
  217. int fd, rc, ppid = 0;
  218. sprintf(buffer, "/proc/%d/stat", pid);
  219. if ( (fd = open(buffer, O_RDONLY, 0)) < 0 ) return 0;
  220. if ( (rc = read(fd, buffer, 99)) > 0) {
  221. buffer[rc] = 0;
  222. /* format: 27910 (bash) S 27315 ... */
  223. sscanf(buffer, "%*[^ ] %*[^ ] %*[^ ] %d", &ppid);
  224. }
  225. close(fd);
  226. return ppid;
  227. }
  228. /* this is only called from fl_wrapper_init(). so it doesn't need to be
  229. * reentrant. */
  230. static char *getpname(int pid)
  231. {
  232. static char p[512];
  233. char buffer[513]="";
  234. char *arg=0, *b;
  235. int i, fd, rc;
  236. sprintf(buffer, "/proc/%d/cmdline", pid);
  237. if ( (fd = open(buffer, O_RDONLY, 0)) < 0 ) return "unkown";
  238. if ( (rc = read(fd, buffer, 512)) > 0) {
  239. buffer[rc--] = 0;
  240. for (i=0; i<rc; i++)
  241. if (buffer[i] == 0 && buffer[i+1] != '-')
  242. { arg = buffer+i+1; break; }
  243. }
  244. close(fd);
  245. b = basename(buffer);
  246. snprintf(p, 512, "%s", b);
  247. if ( !strcmp(b, "bash") || !strcmp(b, "sh") ||
  248. !strcmp(b, "perl") || !strcmp(b, "python") )
  249. if ( arg && *arg &&
  250. strlen(arg) < 100 && !strchr(arg, '\n') &&
  251. !strchr(arg, ' ') && !strchr(arg, ';') )
  252. snprintf(p, 512, "%s(%s)", b, basename(arg));
  253. return p;
  254. }
  255. /* invert the order by recursion. there will be only one recursion tree
  256. * so we can use a static var for managing the last ent */
  257. static void addptree(int *txtpos, char *cmdtxt, int pid, int basepid)
  258. {
  259. static char l[512] = "";
  260. char *p;
  261. if (!pid || pid == basepid) return;
  262. addptree(txtpos, cmdtxt, pid2ppid(pid), basepid);
  263. p = getpname(pid);
  264. if (*txtpos < 4000)
  265. {
  266. if ( strcmp(l, p) )
  267. *txtpos += snprintf(cmdtxt+*txtpos, 4096-*txtpos, "%s%s",
  268. *txtpos ? "." : "", getpname(pid));
  269. else
  270. *txtpos += snprintf(cmdtxt+*txtpos, 4096-*txtpos, "*");
  271. }
  272. strcpy(l, p);
  273. }
  274. void __attribute__ ((constructor)) fl_wrapper_init()
  275. {
  276. # if DEBUG == 1
  277. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: fl_wrapper_init()\n", getpid());
  278. # endif
  279. char cmdtxt[4096] = "";
  280. char *basepid_txt = getenv("FLWRAPPER_BASEPID");
  281. int basepid = 0, txtpos=0;
  282. if (basepid_txt)
  283. basepid = atoi(basepid_txt);
  284. addptree(&txtpos, cmdtxt, getpid(), basepid);
  285. cmdname = strdup(cmdtxt);
  286. wlog = getenv("FLWRAPPER_WLOG");
  287. rlog = getenv("FLWRAPPER_RLOG");
  288. # if DEBUG == 1
  289. char *debugwrapper = getenv("FLWRAPPER_DEBUG");
  290. if (debugwrapper) debug = atoi(debugwrapper);
  291. # endif
  292. }
  293. /*
  294. Clean up file descriptors still registered for this pid, if any.
  295. */
  296. void __attribute__ ((destructor)) fl_wrapper_finish()
  297. {
  298. # if DEBUG == 1
  299. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: fl_wrapper_finish()\n", getpid());
  300. # endif
  301. struct pid_reg **pid = find_pid(getpid());
  302. if (*pid)
  303. {
  304. # if DEBUG == 1
  305. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: PID still registered!\n", getpid());
  306. # endif
  307. struct fd_reg **fd = &(*pid)->fd_head;
  308. while (*fd)
  309. {
  310. handle_file_access_after("fl_wrapper_finish", (*fd)->filename, &(*fd)->status);
  311. remove_fd(fd);
  312. }
  313. remove_pid(pid);
  314. }
  315. }
  316. static void handle_file_access_before(const char * func, const char * file,
  317. struct status_t * status)
  318. {
  319. struct stat st;
  320. # if DEBUG == 1
  321. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: begin of handle_file_access_before(\"%s\", \"%s\", xxx)\n",
  322. getpid(), func, file);
  323. # endif
  324. if ( lstat(file,&st) ) {
  325. status->inode=0; status->size=0;
  326. status->mtime=0; status->ctime=0;
  327. } else {
  328. status->inode=st.st_ino; status->size=st.st_size;
  329. status->mtime=st.st_mtime; status->ctime=st.st_ctime;
  330. }
  331. # if DEBUG == 1
  332. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: end of handle_file_access_before(\"%s\", \"%s\", xxx)\n",
  333. getpid(), func, file);
  334. # endif
  335. }
  336. /*
  337. Declared in fl_wrapper_open.c and fl_wrapper_close.c,
  338. reused here since logging access to the log files eventually
  339. overwrites close'd but not yet deregistered file descriptors.
  340. int (*orig_open)(const char* f, int a, ...) = 0;
  341. int (*orig_open64)(const char* f, int a, ...) = 0;
  342. int (*orig_close)(int fd) = 0;
  343. */
  344. static void handle_file_access_after(const char * func, const char * file,
  345. struct status_t * status)
  346. {
  347. char buf[512], *buf2, *logfile;
  348. int fd; struct stat st;
  349. #ifdef __USE_LARGEFILE
  350. if (!orig_open64) orig_open64 = get_dl_symbol("open64");
  351. #else
  352. if (!orig_open) orig_open = get_dl_symbol("open");
  353. #endif
  354. if (!orig_close) orig_close = get_dl_symbol("close");
  355. # if DEBUG == 1
  356. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: begin of handle_file_access_after(\"%s\", \"%s\", xxx), %d, %s, %s\n",
  357. getpid(), func, file, status != 0, wlog, rlog);
  358. # endif
  359. if ( lstat(file, &st) )
  360. {
  361. # if DEBUG == 1
  362. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: lstat(%s, ...) failed\n",
  363. getpid(), file);
  364. # endif
  365. return;
  366. }
  367. if ( (status != 0) && (status->inode != st.st_ino ||
  368. status->size != st.st_size || status->mtime != st.st_mtime ||
  369. status->ctime != st.st_ctime) ) { logfile = wlog; }
  370. else { logfile = rlog; }
  371. if ( logfile == 0 )
  372. {
  373. # if DEBUG == 1
  374. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: no log file\n",
  375. getpid());
  376. # endif
  377. return;
  378. }
  379. #ifdef __USE_LARGEFILE
  380. fd=orig_open64(logfile,O_APPEND|O_WRONLY|O_LARGEFILE,0);
  381. #else
  382. #warning "The wrapper library will not work properly for large logs!"
  383. fd=orig_open(logfile,O_APPEND|O_WRONLY,0);
  384. #endif
  385. if (fd == -1)
  386. {
  387. # if DEBUG == 1
  388. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: log open failed (%s)\n",
  389. getpid(), strerror(errno));
  390. # endif
  391. return;
  392. }
  393. if (file[0] == '/') {
  394. sprintf(buf,"%s.%s:\t%s\n",
  395. cmdname, func, file);
  396. } else {
  397. buf2=get_current_dir_name();
  398. sprintf(buf,"%s.%s:\t%s%s%s\n",
  399. cmdname, func, buf2,
  400. strcmp(buf2,"/") ? "/" : "", file);
  401. free(buf2);
  402. }
  403. write(fd,buf,strlen(buf));
  404. orig_close(fd);
  405. # if DEBUG == 1
  406. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: end of handle_file_access_after(\"%s\", \"%s\", xxx)\n",
  407. getpid(), func, file);
  408. # endif
  409. }
  410. EOT