66#include <errno.h>
77#include <fcntl.h>
88#include <limits.h>
9- #include <pthread.h>
109#include <stdarg.h>
1110#include <stdio.h>
1211#include <stdlib.h>
1615#include <sys/types.h>
1716#include <unistd.h>
1817
19- static pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ;
2018static FILE * log_f = NULL ;
2119static const char * pwd = NULL ;
2220
21+ #ifdef __APPLE__
22+
23+ struct dyld_interpose {
24+ const void * replacement ;
25+ const void * replacee ;
26+ };
27+
28+ #define WRAPPER (RET , FUN ) static RET _cns_wrapper_##FUN
29+ #define REAL (FUN ) FUN
30+ #define DEF_WRAPPER (FUN ) \
31+ __attribute__((used)) static struct dyld_interpose _cns_interpose_##FUN \
32+ __attribute__((section("__DATA,__interpose"))) = { &_cns_wrapper_##FUN, &FUN };
33+
34+ #else /* __APPLE__ */
35+
2336static int (* real___lxstat )(int ver , const char * path , struct stat * buf ) = NULL ;
2437static int (* real_open )(const char * path , int flags , ...) = NULL ;
2538static DIR * (* real_opendir )(const char * name ) = NULL ;
2639
40+ #define WRAPPER (RET , FUN ) RET FUN
2741#define REAL (FUN ) \
2842 (real_##FUN == NULL ? (real_##FUN = dlsym(RTLD_NEXT, #FUN)) : real_##FUN)
43+ #define DEF_WRAPPER (FUN )
44+
45+ #endif /* __APPLE__ */
2946
3047#define FATAL () \
3148 do { \
@@ -36,8 +53,36 @@ static DIR *(*real_opendir)(const char *name) = NULL;
3653
3754#define LEN 16
3855
56+ // Locks
57+
58+ #ifdef __APPLE__
59+
60+ #include <dispatch/dispatch.h>
61+ static dispatch_semaphore_t print_mutex ;
62+ static dispatch_semaphore_t buf_mutex ;
63+ #define INIT_MUTEX (MUTEX ) \
64+ MUTEX = dispatch_semaphore_create(1)
65+ #define LOCK (MUTEX ) \
66+ dispatch_semaphore_wait(MUTEX, DISPATCH_TIME_FOREVER)
67+ #define UNLOCK (MUTEX ) \
68+ dispatch_semaphore_signal(MUTEX)
69+
70+ #else /* __APPLE__ */
71+
72+ #include <pthread.h>
73+ static pthread_mutex_t print_mutex = PTHREAD_MUTEX_INITIALIZER ;
74+ static pthread_mutex_t buf_mutex = PTHREAD_MUTEX_INITIALIZER ;
75+ #define INIT_MUTEX (MUTEX )
76+ #define LOCK (MUTEX ) \
77+ pthread_mutex_lock(&MUTEX)
78+ #define UNLOCK (MUTEX ) \
79+ pthread_mutex_unlock(&MUTEX)
80+
81+ #endif /* __APPLE__ */
82+
3983// Predeclarations
4084
85+ static void print_stat (int result , const char * path , struct stat * sb );
4186static void convert_digest (char [static LEN * 2 + 1 ], const uint8_t [static LEN ]);
4287static int enable (const char * );
4388static void hash_dir (char [static LEN * 2 + 1 ], DIR * );
@@ -47,10 +92,65 @@ static int strcmp_qsort(const void *, const void *);
4792
4893////////////////////////////////////////////////////////////////////////////////
4994
95+ #ifdef __APPLE__
96+
97+ /* $OpenBSD: reallocarray.c,v 1.3 2015/09/13 08:31:47 guenther Exp $ */
98+ /*
99+ * Copyright (c) 2008 Otto Moerbeek <[email protected] > 100+ *
101+ * Permission to use, copy, modify, and distribute this software for any
102+ * purpose with or without fee is hereby granted, provided that the above
103+ * copyright notice and this permission notice appear in all copies.
104+ *
105+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
106+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
107+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
108+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
109+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
110+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
111+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
112+ */
113+
114+ #include <sys/types.h>
115+ #include <errno.h>
116+ #include <stdint.h>
117+ #include <stdlib.h>
118+
119+ /*
120+ * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
121+ * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
122+ */
123+ #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
124+
125+ static void * reallocarray (void * optr , size_t nmemb , size_t size ) {
126+ if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW ) &&
127+ nmemb > 0 && SIZE_MAX / nmemb < size ) {
128+ errno = ENOMEM ;
129+ return NULL ;
130+ }
131+ return realloc (optr , size * nmemb );
132+ }
133+
134+ static const char * get_current_dir_name () {
135+ char * buf = NULL ;
136+ size_t bufsize = 64 * sizeof (char );
137+ do {
138+ buf = realloc (buf , bufsize );
139+ if (buf == NULL )
140+ FATAL ();
141+ if (getcwd (buf , bufsize ))
142+ return buf ;
143+ bufsize *= 2 ;
144+ } while (errno == ERANGE );
145+ FATAL ();
146+ }
147+ #endif /* __APPLE__ */
148+
50149static void __attribute__((constructor )) init () {
51- // Remove ourselves from LD_PRLOAD . We do not want to log child processes.
150+ // Remove ourselves from LD_PRELOAD and DYLD_INSERT_LIBRARIES . We do not want to log child processes.
52151 // TODO: use `ld.so --preload` instead
53152 unsetenv ("LD_PRELOAD" );
153+ unsetenv ("DYLD_INSERT_LIBRARIES" );
54154
55155 const char * fname = getenv ("TRACE_NIX" );
56156 if (fname != NULL ) {
@@ -65,42 +165,32 @@ static void __attribute__((constructor)) init() {
65165 FATAL ();
66166 }
67167 unsetenv ("TRACE_NIX" );
168+
169+ INIT_MUTEX (print_mutex );
170+ INIT_MUTEX (buf_mutex );
68171}
69172
70- int __lxstat (int ver , const char * path , struct stat * sb ) {
71- static char * buf = NULL ;
72- static off_t buf_len = 0 ;
173+ #ifdef __APPLE__
73174
74- int result = REAL (__lxstat )(ver , path , sb );
175+ WRAPPER (int , lstat )(const char * path , struct stat * sb ) {
176+ int result = REAL (lstat )(path , sb );
177+ print_stat (result , path , sb );
178+ return result ;
179+ }
180+ DEF_WRAPPER (lstat );
75181
76- if (enable (path )) {
77- if (result != 0 ) {
78- print_log ('s' , path , "-" );
79- } else if (S_ISLNK (sb -> st_mode )) {
80- pthread_mutex_lock (& mutex );
81- if (buf_len < sb -> st_size + 2 ) {
82- buf_len = sb -> st_size + 2 ;
83- buf = realloc (buf , buf_len );
84- if (buf == NULL )
85- FATAL ();
86- }
87- ssize_t link_len = readlink (path , buf + 1 , sb -> st_size );
88- if (link_len < 0 || link_len != sb -> st_size )
89- FATAL ();
90- buf [0 ] = 'l' ;
91- buf [sb -> st_size + 1 ] = 0 ;
92- print_log ('s' , path , buf );
93- pthread_mutex_unlock (& mutex );
94- } else if (S_ISDIR (sb -> st_mode )) {
95- print_log ('s' , path , "d" );
96- } else {
97- print_log ('s' , path , "+" );
98- }
99- }
182+ #else /* __APPLE__ */
183+
184+ WRAPPER (int , __lxstat )(int ver , const char * path , struct stat * sb ) {
185+ int result = REAL (__lxstat )(ver , path , sb );
186+ print_stat (result , path , sb );
100187 return result ;
101- }
188+ }
189+ DEF_WRAPPER (__lxstat )
190+
191+ #endif /* __APPLE__ */
102192
103- int open (const char * path , int flags , ...) {
193+ WRAPPER ( int , open ) (const char * path , int flags , ...) {
104194 va_list args ;
105195 va_start (args , flags );
106196 int mode = va_arg (args , int );
@@ -120,8 +210,9 @@ int open(const char *path, int flags, ...) {
120210
121211 return fd ;
122212}
213+ DEF_WRAPPER (open )
123214
124- DIR * opendir (const char * path ) {
215+ WRAPPER ( DIR * , opendir ) (const char * path ) {
125216 DIR * dirp = REAL (opendir )(path );
126217 if (enable (path )) {
127218 if (dirp == NULL ) {
@@ -134,6 +225,7 @@ DIR *opendir(const char *path) {
134225 }
135226 return dirp ;
136227}
228+ DEF_WRAPPER (opendir )
137229
138230////////////////////////////////////////////////////////////////////////////////
139231
@@ -164,8 +256,38 @@ static int enable(const char *path) {
164256 return 1 ;
165257}
166258
259+ static void print_stat (int result , const char * path , struct stat * sb ) {
260+ static char * buf = NULL ;
261+ static off_t buf_len = 0 ;
262+
263+ if (enable (path )) {
264+ if (result != 0 ) {
265+ print_log ('s' , path , "-" );
266+ } else if (S_ISLNK (sb -> st_mode )) {
267+ LOCK (buf_mutex );
268+ if (buf_len < sb -> st_size + 2 ) {
269+ buf_len = sb -> st_size + 2 ;
270+ buf = realloc (buf , buf_len );
271+ if (buf == NULL )
272+ FATAL ();
273+ }
274+ ssize_t link_len = readlink (path , buf + 1 , sb -> st_size );
275+ if (link_len < 0 || link_len != sb -> st_size )
276+ FATAL ();
277+ buf [0 ] = 'l' ;
278+ buf [sb -> st_size + 1 ] = 0 ;
279+ print_log ('s' , path , buf );
280+ UNLOCK (buf_mutex );
281+ } else if (S_ISDIR (sb -> st_mode )) {
282+ print_log ('s' , path , "d" );
283+ } else {
284+ print_log ('s' , path , "+" );
285+ }
286+ }
287+ }
288+
167289static void print_log (char op , const char * path , const char * result ) {
168- pthread_mutex_lock ( & mutex );
290+ LOCK ( print_mutex );
169291 fprintf (
170292 log_f ,
171293 "%c" "%s%s" "%s%c" "%s%c" ,
@@ -175,7 +297,7 @@ static void print_log(char op, const char *path, const char *result) {
175297 result , (char )0
176298 );
177299 fflush (log_f );
178- pthread_mutex_unlock ( & mutex );
300+ UNLOCK ( print_mutex );
179301}
180302
181303static void hash_file (char digest_s [static LEN * 2 + 1 ], int fd ) {
0 commit comments