1 /* Automatic generation of BuildRequires dependencies for rpmbuild.
2 * Copyright (C) 2008 Red Hat Inc.
3 * Written by Richard W.M. Jones <rjones@redhat.com>
4 * Patches from Rajeesh K Nambiar <rajeeshknambiar@gmail.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 /* This is an LD_PRELOAD extension which logs accesses to any files by
22 * trapping access to any system calls which open files. Details of
23 * opened files are written to the file named in
24 * the AUTO_BUILDREQUIRES_LOGFILE environment variable.
33 #include <sys/types.h>
40 #define ALIAS(ret,syscall,params,brfunc) \
41 extern ret syscall params __attribute__((alias (brfunc)))
43 static char *br_path (const char *path);
44 static void br_init (void) __attribute__((constructor));
45 static void br_log (const char *fs, ...) __attribute__((format (printf,1,2)));
47 /* These are the real glibc symbols, initialized in br_init. */
48 static int (*glibc_open) (const char *pathname, int flags, mode_t mode);
49 static int (*glibc_execve) (const char *filename, char *const argv[],
52 /* Canonicalize a relative or absolute path. If that isn't possible,
53 * return an absolute path.
55 * The caller must free the result.
58 br_path (const char *path)
63 if (path == NULL) return NULL;
66 rp = realpath (path, NULL);
67 if (!rp) rp = strdup (path);
71 dir = get_current_dir_name ();
72 if (dir == NULL) return NULL;
74 len = strlen (dir) + 1 + strlen (path) + 1;
85 rp = realpath (cat, NULL);
87 if (!rp) rp = cat; else free (cat);
92 abr_open (const char *pathname, int flags, mode_t mode)
97 rp = br_path (pathname);
99 br_log ("open %s\n", rp);
104 fd = glibc_open (pathname, flags, mode);
108 ALIAS (int, open, (const char *, int, ...), "abr_open");
111 abr_execve (const char *filename, char *const argv[], char *const envp[])
116 rp = br_path (filename);
118 br_log ("execve %s\n", rp);
123 r = glibc_execve (filename, argv, envp);
127 ALIAS (int, execve, (const char *filename, char *const argv[],
128 char *const envp[]), "abr_execve");
130 /* Other syscalls to consider:
138 * 'connect' params can contain a path in some rare circumstances.
141 /* This is the logging function. We have to be very cautious in this
142 * function and not disturb any part of the process (so far as that is
143 * possible). eg. When we open a file descriptor we must close it
146 * Any errors should either call abort() if they are serious, or
147 * return without harm if not.
149 * Also remember to call glibc_* for any syscalls that we are
150 * intercepting, otherwise you'll get an infinite loop.
153 br_log (const char *fs, ...)
155 const char *filename;
160 /* Got the logging environment variable? Should we cleanse this
161 * variable for security reasons, or is it not a problem because RPM
162 * specfiles can do arbitrary Bad Stuff already? (XXX)
164 filename = getenv ("AUTO_BUILDREQUIRES_LOGFILE");
165 if (filename == NULL) return;
167 fd = glibc_open (filename, O_WRONLY | O_APPEND, 0);
168 if (fd == -1) { perror ("open logfile"); abort (); }
170 /* Create the log string. */
172 len = vasprintf (&msg, fs, args);
174 perror ("vasprintf");
179 /* Write it in a single operation. Should be atomic, right?? (XXX) */
180 if (write (fd, msg, len) != len) {
194 dl = dlopen ("/lib64/libc.so.6", RTLD_LAZY|RTLD_LOCAL);
195 if (dl == NULL) // Try '/lib/' also
196 dl = dlopen("/lib/libc.so.6", RTLD_LAZY|RTLD_LOCAL);
198 fprintf (stderr, "%s\n", dlerror ());
201 glibc_open = dlsym (dl, "open");
202 glibc_execve = dlsym (dl, "execve");