1cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//===-- FDInterposing.cpp ---------------------------------------*- C++ -*-===//
2cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//
3cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//                     The LLVM Compiler Infrastructure
4cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//
5cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// This file is distributed under the University of Illinois Open Source
6cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// License. See LICENSE.TXT for details.
7cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//
8cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//===----------------------------------------------------------------------===//
9cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//
10cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// This file helps with catching double close calls on unix integer file
11cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// descriptors by interposing functions for all file descriptor create and
12cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// close operations. A stack backtrace for every create and close function is
13cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// maintained, and every create and close operation is logged. When a double
14cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// file descriptor close is encountered, it will be logged.
15cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//
16cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// To enable the interposing in a darwin program, set the DYLD_INSERT_LIBRARIES
17cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// environment variable as follows:
18cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// For sh:
19cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//  DYLD_INSERT_LIBRARIES=/path/to/FDInterposing.dylib /path/to/executable
20cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// For tcsh:
21cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//  (setenv DYLD_INSERT_LIBRARIES=/path/to/FDInterposing.dylib ; /path/to/executable)
22cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//
23cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// Other environment variables that can alter the default actions of this
24cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// interposing shared library include:
25cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//
26cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// "FileDescriptorStackLoggingNoCompact"
27cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//
28cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//      With this environment variable set, all file descriptor create and
29cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//      delete operations will be permanantly maintained in the event map.
30cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//      The default action is to compact the create/delete events by removing
31cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//      any previous file descriptor create events that are matched with a
32cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//      corresponding file descriptor delete event when the next valid file
33cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//      descriptor create event is detected.
34cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//
35cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// "FileDescriptorMinimalLogging"
36cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//
37cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//      By default every file descriptor create and delete operation is logged
38cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//      (to STDOUT by default, see the "FileDescriptorLogFile"). This can be
39cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//      suppressed to only show errors and warnings by setting this environment
40cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//      variable (the value in not important).
41cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//
42cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// "FileDescriptorLogFile=<path>"
43cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//
44cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//      By default logging goes to STDOUT_FILENO, but this can be changed by
45cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//      setting FileDescriptorLogFile. The value is a path to a file that
46cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//      will be opened and used for logging.
47cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//===----------------------------------------------------------------------===//
48cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
49cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <assert.h>
50cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <dirent.h>
51cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <errno.h>
52cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <fcntl.h>
53cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <execinfo.h>
54cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <libgen.h>
55cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <mach-o/dyld.h>
56cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <mach-o/dyld-interposing.h>
57cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <stdlib.h>
58cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <stdio.h>
59cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <string.h>
60cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <sys/event.h>
61cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <sys/mman.h>
62cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <sys/socket.h>
63cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <sys/types.h>
64cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <sys/time.h>
651844426728e231df60ea88660e8fb112400f14c7Benjamin Kramer#include <tr1/memory> // for std::tr1::shared_ptr
66cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <unistd.h>
67cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <string>
68cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <vector>
69cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <map>
70cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
71cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
72cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton/// @def DISALLOW_COPY_AND_ASSIGN(TypeName)
73cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton///     Macro definition for easily disallowing copy constructor and
74cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton///     assignment operators in C++ classes.
75cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
76cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
77cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonTypeName(const TypeName&); \
78cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonconst TypeName& operator=(const TypeName&)
79cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
80ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonextern "C" {
81ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    int accept$NOCANCEL (int, struct sockaddr * __restrict, socklen_t * __restrict);
82ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    int close$NOCANCEL(int);
83ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    int open$NOCANCEL(const char *, int, ...);
84ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    int __open_extended(const char *, int, uid_t, gid_t, int, struct kauth_filesec *);
85ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton}
86ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton
87cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonnamespace fd_interposing {
88cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
89cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
90cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// String class so we can get formatted strings without having to worry
91cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// about the memory storage since it will allocate the memory it needs.
92cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
93cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonclass String
94cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
95cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonpublic:
96cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    String () :
97cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        m_str (NULL)
98cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {}
99cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
100cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    String (const char *format, ...) :
101cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        m_str (NULL)
102cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
103cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        va_list args;
104cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        va_start (args, format);
105cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        vprintf (format, args);
106cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        va_end (args);
107cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
108cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
109cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    ~String()
110cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
111cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        reset();
112cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
113cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
114cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    void
115cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    reset (char *s = NULL)
116cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
117cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        if (m_str)
118cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            ::free (m_str);
119cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        m_str = s;
120cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
121cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
122cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    const char *
123cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    c_str () const
124cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
125cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        return m_str;
126cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
127cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
128cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    void
129cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    printf (const char *format, ...)
130cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
131cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        va_list args;
132cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        va_start (args, format);
133cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        vprintf (format, args);
134cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        va_end (args);
135cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
136cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    void
137cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    vprintf (const char *format, va_list args)
138cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
139cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        reset();
140cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        ::vasprintf (&m_str, format, args);
141cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
142cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
143cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    void
144cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    log (int log_fd)
145cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
146cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        if (m_str && log_fd >= 0)
147cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        {
148cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            const int len = strlen(m_str);
149cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            if (len > 0)
150cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            {
151cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                write (log_fd, m_str, len);
152cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                const char last_char = m_str[len-1];
153cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                if (!(last_char == '\n' || last_char == '\r'))
154cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                    write (log_fd, "\n", 1);
155cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            }
156cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        }
157cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
158cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonprotected:
159cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    char *m_str;
160cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
161cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonprivate:
162cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    DISALLOW_COPY_AND_ASSIGN (String);
163cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton};
164cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
165cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
166cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// Type definitions
167cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
168cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytontypedef std::vector<void *> Frames;
169cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonclass FDEvent;
170cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytontypedef std::vector<void *> Frames;
1711844426728e231df60ea88660e8fb112400f14c7Benjamin Kramertypedef std::tr1::shared_ptr<FDEvent> FDEventSP;
1721844426728e231df60ea88660e8fb112400f14c7Benjamin Kramertypedef std::tr1::shared_ptr<String> StringSP;
173cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
174cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
175cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
176cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// FDEvent
177cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//
178cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// A class that describes a file desciptor event.
179cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//
180cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// File descriptor events fall into one of two categories: create events
181cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// and delete events.
182cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
183cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonclass FDEvent
184cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
185cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonpublic:
186cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    FDEvent (int fd, int err, const StringSP &string_sp, bool is_create, const Frames& frames) :
187cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        m_string_sp (string_sp),
188cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        m_frames (frames.begin(), frames.end()),
189cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        m_fd (fd),
190cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        m_err (err),
191cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        m_is_create (is_create)
192cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {}
193cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
194cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    ~FDEvent () {}
195cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
196cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    bool
197cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    IsCreateEvent() const
198cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
199cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        return m_is_create;
200cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
201cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
202cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    bool
203cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    IsDeleteEvent() const
204cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
205cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        return !m_is_create;
206cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
207cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
208cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    Frames &
209cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    GetFrames ()
210cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
211cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        return m_frames;
212cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
213cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
214cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    const Frames &
215cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    GetFrames () const
216cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
217cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        return m_frames;
218cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
219cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
220cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    int
221cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    GetFD () const
222cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
223cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        return m_fd;
224cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
225cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
226cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    int
227cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    GetError () const
228cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
229cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        return m_err;
230cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
231cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
232cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    void
233cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    Dump (int log_fd) const;
234cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
235cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    void
236cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    SetCreateEvent (FDEventSP &create_event_sp)
237cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
238cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        m_create_event_sp = create_event_sp;
239cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
240cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
241cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonprivate:
242cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    // A shared pointer to a String that describes this event in
243cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    // detail (all args and return and error values)
244cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    StringSP m_string_sp;
245cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    // The frames for the stack backtrace for this event
246cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    Frames m_frames;
247cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    // If this is a file descriptor delete event, this might contain
248cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    // the correspoding file descriptor create event
249cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    FDEventSP m_create_event_sp;
250cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    // The file descriptor for this event
251cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    int m_fd;
252cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    // The error code (if any) for this event
253cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    int m_err;
254cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    // True if this event is a file descriptor create event, false
255cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    // if it is a file descriptor delete event
256cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    bool m_is_create;
257cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton};
258cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
259cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
260cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// Templatized class that will save errno only if the "value" it is
261cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// constructed with is equal to INVALID. When the class goes out of
262cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// scope, it will restore errno if it was saved.
263cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
264cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytontemplate <int INVALID>
265cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonclass Errno
266cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
267cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonpublic:
268cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    // Save errno only if we are supposed to
269cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    Errno (int value) :
270cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        m_saved_errno ((value == INVALID) ? errno : 0),
271cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        m_restore (value == INVALID)
272cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
273cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
274cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
275cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    // Restore errno only if we are supposed to
276cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    ~Errno()
277cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
278cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        if (m_restore)
279cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            errno = m_saved_errno;
280cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
281cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
282cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    // Accessor for the saved value of errno
283cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    int
284cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    get_errno() const
285cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
286cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        return m_saved_errno;
287cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
288cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
289cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonprotected:
290cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    const int m_saved_errno;
291cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    const bool m_restore;
292cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton};
293cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
294cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytontypedef Errno<-1> InvalidFDErrno;
295cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytontypedef Errno<-1> NegativeErrorErrno;
296cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytontypedef std::vector<FDEventSP> FDEventArray;
297cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytontypedef std::map<int, FDEventArray> FDEventMap;
298cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
299cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
300cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// Globals
301cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
302cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// Global event map that contains all file descriptor events. As file
303cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// descriptor create and close events come in, they will get filled
304cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// into this map (protected by g_mutex). When a file descriptor close
305cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// event is detected, the open event will be removed and placed into
306cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// the close event so if something tries to double close a file
307cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// descriptor we can show the previous close event and the file
308cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// desctiptor event that created it. When a new file descriptor create
309cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// event comes in, we will remove the previous one for that file
310cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// desctiptor unless the environment variable "FileDescriptorStackLoggingNoCompact"
311cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// is set. The file desctiptor history can be accessed using the
312cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// get_fd_history() function.
313cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonstatic FDEventMap g_fd_event_map;
314cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// A mutex to protect access to our data structures in g_fd_event_map
315cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// and also our logging messages
316cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonstatic pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
317cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// Log all file descriptor create and close events by default. Only log
318cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// warnings and erros if the "FileDescriptorMinimalLogging" environment
319cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// variable is set.
320cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonstatic int g_log_all_calls = 1;
321cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// We compact the file descriptor events by default. Set the environment
322cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// varible "FileDescriptorStackLoggingNoCompact" to keep a full history.
323cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonstatic int g_compact = 1;
324ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton// The current process ID
325ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonstatic int g_pid = -1;
326ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonstatic bool g_enabled = true;
327cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
328cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// Mutex class that will lock a mutex when it is constructed, and unlock
329cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// it when is goes out of scope
330cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
331cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonclass Locker
332cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
333cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonpublic:
334cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    Locker (pthread_mutex_t *mutex_ptr) :
335cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        m_mutex_ptr(mutex_ptr)
336cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
337cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        ::pthread_mutex_lock (m_mutex_ptr);
338cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
339cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
340cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    // This allows clients to test try and acquire the mutex...
341cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    Locker (pthread_mutex_t *mutex_ptr, bool &lock_acquired) :
342cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        m_mutex_ptr(NULL)
343cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
344cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        lock_acquired = ::pthread_mutex_trylock(mutex_ptr) == 0;
345cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        if (lock_acquired)
346cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            m_mutex_ptr = mutex_ptr;
347cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
348cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
349cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    ~Locker ()
350cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
351cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        if (m_mutex_ptr)
352cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            ::pthread_mutex_unlock (m_mutex_ptr);
353cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
354cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonprotected:
355cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    pthread_mutex_t *m_mutex_ptr;
356cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton};
357cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
358cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonstatic void
359cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonlog (const char *format, ...) __attribute__ ((format (printf, 1, 2)));
360cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
361cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonstatic void
362cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonlog (int log_fd, const FDEvent *event, const char *format, ...) __attribute__ ((format (printf, 3, 4)));
363cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
364cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonstatic void
365cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonbacktrace_log (const char *format, ...) __attribute__ ((format (printf, 1, 2)));
366cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
367cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonstatic void
368ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonbacktrace_error (const char *format, ...) __attribute__ ((format (printf, 1, 2)));
369ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton
370ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonstatic void
371cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonlog_to_fd (int log_fd, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
372cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
373cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonstatic inline size_t
374cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonget_backtrace (Frames &frame_buffer, size_t frames_to_remove)
375cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
376cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    void *frames[2048];
377cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    int count = ::backtrace (&frames[0], sizeof(frames)/sizeof(void*));
378cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    if (count > frames_to_remove)
379cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        frame_buffer.assign (&frames[frames_to_remove], &frames[count]);
380cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    else
381cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        frame_buffer.assign (&frames[0], &frames[count]);
382cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    while (frame_buffer.back() < (void *)1024)
383cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        frame_buffer.pop_back();
384cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    return frame_buffer.size();
385cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
386cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
387ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonstatic int g_log_fd = STDOUT_FILENO;
388ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonstatic int g_initialized = 0;
389ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton
390ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonconst char *
391ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonget_process_fullpath (bool force = false)
392ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton{
393ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    static char g_process_fullpath[PATH_MAX] = {0};
394ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    if (force || g_process_fullpath[0] == '\0')
395ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
396ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        // If DST is NULL, then return the number of bytes needed.
397ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        uint32_t len = sizeof(g_process_fullpath);
398ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (_NSGetExecutablePath (g_process_fullpath, &len) != 0)
399ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            strncpy (g_process_fullpath, "<error>", sizeof(g_process_fullpath));
400ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
401ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    return g_process_fullpath;
402ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton}
403ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton
404ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton// Returns the current process ID, or -1 if inserposing not enabled for
405ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton// this process
406ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonstatic int
407ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonget_interposed_pid()
408ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton{
409ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    if (!g_enabled)
410ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return -1;
411ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton
412ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    const pid_t pid = getpid();
413ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    if (g_pid != pid)
414ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
415ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (g_pid == -1)
416ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        {
417ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            g_pid = pid;
418ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            log ("Interposing file descriptor create and delete functions for %s (pid=%i)\n", get_process_fullpath (true), pid);
419ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        }
420ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        else
421ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        {
422ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            log ("pid=%i: disabling interposing file descriptor create and delete functions for child process %s (pid=%i)\n", g_pid, get_process_fullpath (true), pid);
423ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            g_enabled = false;
424ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            return -1;
425ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        }
426ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        // Log when our process changes
427ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
428ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    return g_pid;
429ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton}
430ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton
431cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonstatic int
432cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonget_logging_fd ()
433cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
434ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    if (!g_enabled)
435ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return -1;
436cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
437ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    if (!g_initialized)
438cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
439ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        g_initialized = 1;
440cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
441ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        const pid_t pid = get_interposed_pid();
442cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
443ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (g_enabled)
444ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        {
445ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            // Keep all stack info around for all fd create and delete calls.
446ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            // Otherwise we will remove the fd create call when a corresponding
447ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            // fd delete call is received
448ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            if (getenv("FileDescriptorStackLoggingNoCompact"))
449ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                g_compact = 0;
450ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton
451ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            if (getenv("FileDescriptorMinimalLogging"))
452ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                g_log_all_calls = 0;
453ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton
454ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            const char *log_path = getenv ("FileDescriptorLogFile");
455ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            if (log_path)
456ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                g_log_fd = ::creat (log_path, 0660);
457ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            else
458ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                g_log_fd = STDOUT_FILENO;
459cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
460ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            // Only let this interposing happen on the first time this matches
461ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            // and stop this from happening so any child processes don't also
462ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            // log their file descriptors
463ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            ::unsetenv ("DYLD_INSERT_LIBRARIES");
464ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        }
465ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        else
466cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        {
467ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            log ("pid=%i: logging disabled\n", getpid());
468cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        }
469cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
470cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    return g_log_fd;
471cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
472cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
473cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonvoid
474cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonlog_to_fd (int log_fd, const char *format, va_list args)
475cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
476cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    if (format && format[0] && log_fd >= 0)
477cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
478cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        char buffer[PATH_MAX];
479cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        const int count = ::vsnprintf (buffer, sizeof(buffer), format, args);
480cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        if (count > 0)
481cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            write (log_fd, buffer, count);
482cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
483cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
484cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
485cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonvoid
486cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonlog_to_fd (int log_fd, const char *format, ...)
487cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
488cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    if (format && format[0])
489cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
490cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        va_list args;
491cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        va_start (args, format);
492cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        log_to_fd (log_fd, format, args);
493cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        va_end (args);
494cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
495cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
496cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
497cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonvoid
498cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonlog (const char *format, va_list args)
499cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
500cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    log_to_fd (get_logging_fd (), format, args);
501cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
502cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
503cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonvoid
504cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonlog (const char *format, ...)
505cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
506cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    if (format && format[0])
507cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
508cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        va_list args;
509cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        va_start (args, format);
510cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        log (format, args);
511cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        va_end (args);
512cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
513cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
514cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
515cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonvoid
516cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonlog (int log_fd, const FDEvent *event, const char *format, ...)
517cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
518cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    if (format && format[0])
519cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
520cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        va_list args;
521cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        va_start (args, format);
522cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        log_to_fd (log_fd, format, args);
523cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        va_end (args);
524cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
525cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    if (event)
526cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        event->Dump(log_fd);
527cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
528cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
529cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonvoid
530cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonFDEvent::Dump (int log_fd) const
531cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
532cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    if (log_fd >= 0)
533cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
534cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        log_to_fd (log_fd, "%s\n", m_string_sp->c_str());
535cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        if (!m_frames.empty())
536cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            ::backtrace_symbols_fd (m_frames.data(), m_frames.size(), log_fd);
537cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
538cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        if (m_create_event_sp)
539cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        {
540cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            log_to_fd (log_fd, "\nfd=%i was created with this event:\n", m_fd);
541cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            m_create_event_sp->Dump (log_fd);
542cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            log_to_fd (log_fd, "\n");
543cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        }
544cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
545cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
546cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
547cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
548cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonvoid
549cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonbacktrace_log (const char *format, ...)
550cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
551cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    const int log_fd = get_logging_fd ();
552cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    if (log_fd >= 0)
553cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
554cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        if (format && format[0])
555cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        {
556cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            va_list args;
557cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            va_start (args, format);
558cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            log (format, args);
559cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            va_end (args);
560cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        }
561cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
562cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        Frames frames;
56306a305818fe09fa662ed09268a82b077e22f800fGreg Clayton        if (get_backtrace(frames, 2))
564cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            ::backtrace_symbols_fd (frames.data(), frames.size(), log_fd);
565cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
566cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
567cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
568cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
569cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonvoid
570ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonbacktrace_error (const char *format, ...)
571ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton{
572ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    const int pid = get_interposed_pid();
573ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    if (pid >= 0)
574ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
575ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        const int log_fd = get_logging_fd ();
576ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (log_fd >= 0)
577ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        {
578ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            log ("\nerror: %s (pid=%i): ", get_process_fullpath (), pid);
579ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton
580ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            if (format && format[0])
581ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            {
582ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                va_list args;
583ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                va_start (args, format);
584ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                log (format, args);
585ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                va_end (args);
586ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            }
587ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton
588ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            Frames frames;
589ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            if (get_backtrace(frames, 2))
590ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                ::backtrace_symbols_fd (frames.data(), frames.size(), log_fd);
591ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        }
592ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
593ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton}
594cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
595cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonvoid
596cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonsave_backtrace (int fd, int err, const StringSP &string_sp, bool is_create)
597cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
598cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    Frames frames;
599cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    get_backtrace(frames, 2);
600cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
601cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    FDEventSP fd_event_sp (new FDEvent (fd, err, string_sp, is_create, frames));
602cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
603cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    FDEventMap::iterator pos = g_fd_event_map.find (fd);
604cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
605cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    if (pos != g_fd_event_map.end())
606cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
607cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        // We have history for this fd...
608cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
609cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        FDEventArray &event_array = g_fd_event_map[fd];
610cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        if (fd_event_sp->IsCreateEvent())
611cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        {
612cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            // The current fd event is a function that creates
613cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            // a descriptor, check in case last event was
614cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            // a create event.
615cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            if (event_array.back()->IsCreateEvent())
616cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            {
617cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                const int log_fd = get_logging_fd();
618cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                // Two fd create functions in a row, we missed
619cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                // a function that closes a fd...
620cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                log (log_fd, fd_event_sp.get(), "\nwarning: unmatched file descriptor create event fd=%i (we missed a file descriptor close event):\n", fd);
621cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            }
622cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            else if (g_compact)
623cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            {
624cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                // We are compacting so we remove previous create event
625cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                // when we get the correspinding delete event
626cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                event_array.pop_back();
627cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            }
628cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        }
629cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        else
630cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        {
631cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            // The current fd event is a function that deletes
632cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            // a descriptor, check in case last event for this
633cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            // fd was a delete event (double close!)
634cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            if (event_array.back()->IsDeleteEvent())
635cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            {
636cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                const int log_fd = get_logging_fd();
637cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                // Two fd delete functions in a row, we must
638cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                // have missed some function that opened a descriptor
639cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                log (log_fd, fd_event_sp.get(), "\nwarning: unmatched file descriptor close event for fd=%d (we missed the file descriptor create event):\n", fd);
640cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            }
641cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            else if (g_compact)
642cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            {
643cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                // Since this is a close event, we want to remember the open event
644cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                // that this close if for...
645cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                fd_event_sp->SetCreateEvent(event_array.back());
646cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                // We are compacting so we remove previous create event
647cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                // when we get the correspinding delete event
648cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                event_array.pop_back();
649cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            }
650cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        }
651cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
652cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        event_array.push_back(fd_event_sp);
653cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
654cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    else
655cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
656cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        g_fd_event_map[fd].push_back(fd_event_sp);
657cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
658cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
659cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
660cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
661cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// socket() interpose function
662cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
663cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int
664cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonsocket$__interposed__ (int domain, int type, int protocol)
665cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
666ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    const int pid = get_interposed_pid();
667ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    if (pid >= 0)
668ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
669ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        Locker locker (&g_mutex);
670ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        const int fd = ::socket (domain, type, protocol);
671ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        InvalidFDErrno fd_errno(fd);
672ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        StringSP description_sp(new String);
673ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (fd == -1)
674ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            description_sp->printf("pid=%i: socket (domain = %i, type = %i, protocol = %i) => fd=%i  errno = %i", pid, domain, type, protocol, fd, fd_errno.get_errno());
675ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        else
676ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            description_sp->printf("pid=%i: socket (domain = %i, type = %i, protocol = %i) => fd=%i", pid, domain, type, protocol, fd);
677ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (g_log_all_calls)
678ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            description_sp->log (get_logging_fd());
679ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (fd >= 0)
680ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            save_backtrace (fd, fd_errno.get_errno(), description_sp, true);
681ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return fd;
682ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
683cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    else
684ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
685ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return ::socket (domain, type, protocol);
686ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
687cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
688cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
689cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
690cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// socketpair() interpose function
691cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
692cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int
693cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonsocketpair$__interposed__ (int domain, int type, int protocol, int fds[2])
694cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
695ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    const int pid = get_interposed_pid();
696ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    if (pid >= 0)
697ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
698ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        Locker locker (&g_mutex);
699ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        fds[0] = -1;
700ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        fds[1] = -1;
701ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        const int err = socketpair (domain, type, protocol, fds);
702ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        NegativeErrorErrno err_errno(err);
703ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        StringSP description_sp(new String ("pid=%i: socketpair (domain=%i, type=%i, protocol=%i, {fd=%i, fd=%i}) -> err=%i", pid, domain, type, protocol, fds[0], fds[1], err));
704ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (g_log_all_calls)
705ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            description_sp->log (get_logging_fd());
706ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (fds[0] >= 0)
707ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            save_backtrace (fds[0], err_errno.get_errno(), description_sp, true);
708ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (fds[1] >= 0)
709ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            save_backtrace (fds[1], err_errno.get_errno(), description_sp, true);
710ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return err;
711ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
712ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    else
713ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
714ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return socketpair (domain, type, protocol, fds);
715ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
716cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
717cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
718cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
719cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// open() interpose function
720cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
721cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int
722cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonopen$__interposed__ (const char *path, int oflag, int mode)
723cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
724ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    const int pid = get_interposed_pid();
725ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    if (pid >= 0)
726cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
727ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        Locker locker (&g_mutex);
728ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        int fd = -2;
729ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        StringSP description_sp(new String);
730ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (oflag & O_CREAT)
731ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        {
732ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            fd = ::open (path, oflag, mode);
733ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            description_sp->printf("pid=%i: open (path = '%s', oflag = %i, mode = %i) -> fd=%i", pid, path, oflag, mode, fd);
734ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        }
735ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        else
736ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        {
737ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            fd = ::open (path, oflag);
738ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            description_sp->printf("pid=%i: open (path = '%s', oflag = %i) -> fd=%i", pid, path, oflag, fd);
739ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        }
740ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton
741ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        InvalidFDErrno fd_errno(fd);
742ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (g_log_all_calls)
743ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            description_sp->log (get_logging_fd());
744ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (fd >= 0)
745ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            save_backtrace (fd, fd_errno.get_errno(), description_sp, true);
746ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return fd;
747cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
748cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    else
749cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
750ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return ::open (path, oflag, mode);
751cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
752cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
753cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
754cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
755cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// open$NOCANCEL() interpose function
756cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
757cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int
758cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonopen$NOCANCEL$__interposed__ (const char *path, int oflag, int mode)
759cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
760ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    const int pid = get_interposed_pid();
761ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    if (pid >= 0)
762ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
763ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        Locker locker (&g_mutex);
764ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        const int fd = ::open$NOCANCEL (path, oflag, mode);
765ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        InvalidFDErrno fd_errno(fd);
766ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        StringSP description_sp(new String ("pid=%i: open$NOCANCEL (path = '%s', oflag = %i, mode = %i) -> fd=%i", pid, path, oflag, mode, fd));
767ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (g_log_all_calls)
768ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            description_sp->log (get_logging_fd());
769ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (fd >= 0)
770ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            save_backtrace (fd, fd_errno.get_errno(), description_sp, true);
771ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return fd;
772ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
773ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    else
774ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
775ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return ::open$NOCANCEL (path, oflag, mode);
776ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
777cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
778cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
779cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
780cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
781cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// __open_extended() interpose function
782cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
783cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int
784cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton__open_extended$__interposed__ (const char *path, int oflag, uid_t uid, gid_t gid, int mode, struct kauth_filesec *fsacl)
785cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
786ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    const int pid = get_interposed_pid();
787ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    if (pid >= 0)
788ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
789ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        Locker locker (&g_mutex);
790ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        const int fd = ::__open_extended (path, oflag, uid, gid, mode, fsacl);
791ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        InvalidFDErrno fd_errno(fd);
792ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        StringSP description_sp(new String ("pid=%i: __open_extended (path='%s', oflag=%i, uid=%i, gid=%i, mode=%i, fsacl=%p) -> fd=%i", pid, path, oflag, uid, gid, mode, fsacl, fd));
793ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (g_log_all_calls)
794ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            description_sp->log (get_logging_fd());
795ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (fd >= 0)
796ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            save_backtrace (fd, fd_errno.get_errno(), description_sp, true);
797ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return fd;
798ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
799ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    else
800ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
801ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return ::__open_extended (path, oflag, uid, gid, mode, fsacl);
802ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
803cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
804cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
805cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
806cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// kqueue() interpose function
807cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
808cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int
809cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonkqueue$__interposed__ (void)
810cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
811ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    const int pid = get_interposed_pid();
812ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    if (pid >= 0)
813ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
814ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        Locker locker (&g_mutex);
815ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        const int fd = ::kqueue ();
816ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        InvalidFDErrno fd_errno(fd);
817ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        StringSP description_sp(new String ("pid=%i: kqueue () -> fd=%i", pid, fd));
818ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (g_log_all_calls)
819ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            description_sp->log (get_logging_fd());
820ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (fd >= 0)
821ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            save_backtrace (fd, fd_errno.get_errno(), description_sp, true);
822ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return fd;
823ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
824ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    else
825ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
826ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return ::kqueue ();
827ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
828cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
829cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
830cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
831cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// shm_open() interpose function
832cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
833cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int
834cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonshm_open$__interposed__ (const char *path, int oflag, int mode)
835cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
836ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    const int pid = get_interposed_pid();
837ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    if (pid >= 0)
838ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
839ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        Locker locker (&g_mutex);
840ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        const int fd = ::shm_open (path, oflag, mode);
841ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        InvalidFDErrno fd_errno(fd);
842ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        StringSP description_sp(new String ("pid=%i: shm_open (path = '%s', oflag = %i, mode = %i) -> fd=%i", pid, path, oflag, mode, fd));
843ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (g_log_all_calls)
844ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            description_sp->log (get_logging_fd());
845ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (fd >= 0)
846ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            save_backtrace (fd, fd_errno.get_errno(), description_sp, true);
847ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return fd;
848ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
849ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    else
850ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
851ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return ::shm_open (path, oflag, mode);
852ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
853cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
854cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
855cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
856cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// accept() interpose function
857cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
858cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int
859cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonaccept$__interposed__ (int socket, struct sockaddr *address, socklen_t *address_len)
860cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
861ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    const int pid = get_interposed_pid();
862ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    if (pid >= 0)
863ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
864ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        Locker locker (&g_mutex);
865ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        const int fd = ::accept (socket, address, address_len);
866ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        InvalidFDErrno fd_errno(fd);
867ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        StringSP description_sp(new String ("pid=%i: accept (socket=%i, ...) -> fd=%i", pid, socket, fd));
868ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (g_log_all_calls)
869ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            description_sp->log (get_logging_fd());
870ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (fd >= 0)
871ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            save_backtrace (fd, fd_errno.get_errno(), description_sp, true);
872ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return fd;
873ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
874ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    else
875ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
876ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return ::accept (socket, address, address_len);
877ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
878cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
879cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
880cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
881cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
882cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// accept$NOCANCEL() interpose function
883cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
884cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int
885cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonaccept$NOCANCEL$__interposed__ (int socket, struct sockaddr *address, socklen_t *address_len)
886cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
887ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    const int pid = get_interposed_pid();
888ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    if (pid >= 0)
889ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
890ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        Locker locker (&g_mutex);
891ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        const int fd = ::accept$NOCANCEL (socket, address, address_len);
892ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        InvalidFDErrno fd_errno(fd);
893ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        StringSP description_sp(new String ("pid=%i: accept$NOCANCEL (socket=%i, ...) -> fd=%i", pid, socket, fd));
894ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (g_log_all_calls)
895ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            description_sp->log (get_logging_fd());
896ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (fd >= 0)
897ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            save_backtrace (fd, fd_errno.get_errno(), description_sp, true);
898ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return fd;
899ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
900ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    else
901ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
902ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return ::accept$NOCANCEL (socket, address, address_len);
903ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
904cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
905cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
906cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
907cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// dup() interpose function
908cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
909cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int
910cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytondup$__interposed__ (int fd2)
911cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
912ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    const int pid = get_interposed_pid();
913ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    if (pid >= 0)
914ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
915ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        Locker locker (&g_mutex);
916ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        const int fd = ::dup (fd2);
917ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        InvalidFDErrno fd_errno(fd);
918ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        StringSP description_sp(new String ("pid=%i: dup (fd2=%i) -> fd=%i", pid, fd2, fd));
919ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (g_log_all_calls)
920ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            description_sp->log (get_logging_fd());
921ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (fd >= 0)
922ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            save_backtrace (fd, fd_errno.get_errno(), description_sp, true);
923ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return fd;
924ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
925ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    else
926ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
927ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return ::dup (fd2);
928ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
929cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
930cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
931cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
932cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// dup2() interpose function
933cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
934cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int
935cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytondup2$__interposed__ (int fd1, int fd2)
936cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
937ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    const int pid = get_interposed_pid();
938ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    if (pid >= 0)
939ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
940ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        Locker locker (&g_mutex);
941ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        // If "fd2" is already opened, it will be closed during the
942ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        // dup2 call below, so we need to see if we have fd2 in our
943ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        // open map and treat it as a close(fd2)
944ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        FDEventMap::iterator pos = g_fd_event_map.find (fd2);
945ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        StringSP dup2_close_description_sp(new String ("pid=%i: dup2 (fd1=%i, fd2=%i) -> will close (fd=%i)", pid, fd1, fd2, fd2));
946ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (pos != g_fd_event_map.end() && pos->second.back()->IsCreateEvent())
947ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            save_backtrace (fd2, 0, dup2_close_description_sp, false);
948ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton
949ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        const int fd = ::dup2(fd1, fd2);
950ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        InvalidFDErrno fd_errno(fd);
951ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        StringSP description_sp(new String ("pid=%i: dup2 (fd1=%i, fd2=%i) -> fd=%i", pid, fd1, fd2, fd));
952ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (g_log_all_calls)
953ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            description_sp->log (get_logging_fd());
954ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton
955ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (fd >= 0)
956ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            save_backtrace (fd, fd_errno.get_errno(), description_sp, true);
957ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return fd;
958ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
959ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    else
960ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
961ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return ::dup2(fd1, fd2);
962ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
963cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
964cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
965cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
966cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// close() interpose function
967cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
968cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int
969cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonclose$__interposed__ (int fd)
970cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
971ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    const int pid = get_interposed_pid();
972ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    if (pid >= 0)
973cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
974ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        Locker locker (&g_mutex);
975ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        const int err = close(fd);
976ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        NegativeErrorErrno err_errno(err);
977ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        StringSP description_sp (new String);
978ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (err == -1)
979ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            description_sp->printf("pid=%i: close (fd=%i) => %i errno = %i (%s))", pid, fd, err, err_errno.get_errno(), strerror(err_errno.get_errno()));
980ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        else
981ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            description_sp->printf("pid=%i: close (fd=%i) => %i", pid, fd, err);
982ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (g_log_all_calls)
983ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            description_sp->log (get_logging_fd());
984cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
985ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (err == 0)
986ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        {
987ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            if (fd >= 0)
988ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                save_backtrace (fd, err, description_sp, false);
989ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        }
990ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        else if (err == -1)
991ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        {
992ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            if (err_errno.get_errno() == EBADF && fd != -1)
993cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            {
994ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                backtrace_error ("close (fd=%d) resulted in EBADF:\n", fd);
995ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton
996ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                FDEventMap::iterator pos = g_fd_event_map.find (fd);
997ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                if (pos != g_fd_event_map.end())
998ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                {
999ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                    log (get_logging_fd(), pos->second.back().get(), "\nfd=%d was previously %s with this event:\n", fd, pos->second.back()->IsCreateEvent() ? "opened" : "closed");
1000ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                }
1001cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            }
1002cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        }
1003ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return err;
1004ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
1005ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    else
1006ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
1007ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return close (fd);
1008cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
1009cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
1010cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
1011cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
1012cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// close$NOCANCEL() interpose function
1013cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
1014cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int
1015cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonclose$NOCANCEL$__interposed__ (int fd)
1016cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
1017ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    const int pid = get_interposed_pid();
1018ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    if (pid >= 0)
1019cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
1020ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        Locker locker (&g_mutex);
1021ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        const int err = close$NOCANCEL(fd);
1022ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        NegativeErrorErrno err_errno(err);
1023ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        StringSP description_sp (new String);
1024ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (err == -1)
1025ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            description_sp->printf("pid=%i: close$NOCANCEL (fd=%i) => %i errno = %i (%s))", pid, fd, err, err_errno.get_errno(), strerror(err_errno.get_errno()));
1026ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        else
1027ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            description_sp->printf("pid=%i: close$NOCANCEL (fd=%i) => %i", pid, fd, err);
1028ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (g_log_all_calls)
1029ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            description_sp->log (get_logging_fd());
1030ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton
1031ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (err == 0)
1032cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        {
1033ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            if (fd >= 0)
1034ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                save_backtrace (fd, err, description_sp, false);
1035ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        }
1036ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        else if (err == -1)
1037ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        {
1038ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            if (err_errno.get_errno() == EBADF && fd != -1)
1039cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            {
1040ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                backtrace_error ("close$NOCANCEL (fd=%d) resulted in EBADF\n:", fd);
1041ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton
1042ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                FDEventMap::iterator pos = g_fd_event_map.find (fd);
1043ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                if (pos != g_fd_event_map.end())
1044ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                {
1045ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                    log (get_logging_fd(), pos->second.back().get(), "\nfd=%d was previously %s with this event:\n", fd, pos->second.back()->IsCreateEvent() ? "opened" : "closed");
1046ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton                }
1047cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            }
1048cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        }
1049ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return err;
1050cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
1051ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    else
1052ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
1053ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return close$NOCANCEL(fd);
1054ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
1055cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
1056cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
1057cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
1058cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// pipe() interpose function
1059cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
1060cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int
1061cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonpipe$__interposed__ (int fds[2])
1062cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
1063ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    const int pid = get_interposed_pid();
1064ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    if (pid >= 0)
1065ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
1066ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        Locker locker (&g_mutex);
1067ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        fds[0] = -1;
1068ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        fds[1] = -1;
1069ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        const int err = pipe (fds);
1070ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        const int saved_errno = errno;
1071ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        StringSP description_sp(new String ("pid=%i: pipe ({fd=%i, fd=%i}) -> err=%i", pid, fds[0], fds[1], err));
1072ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (g_log_all_calls)
1073ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            description_sp->log (get_logging_fd());
1074ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (fds[0] >= 0)
1075ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            save_backtrace (fds[0], saved_errno, description_sp, true);
1076ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        if (fds[1] >= 0)
1077ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton            save_backtrace (fds[1], saved_errno, description_sp, true);
1078ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        errno = saved_errno;
1079ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return err;
1080ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
1081ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    else
1082ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    {
1083ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton        return pipe (fds);
1084ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton    }
1085cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
1086cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
1087cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
1088cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// get_fd_history()
1089cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//
1090cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// This function allows runtime access to the file descriptor history.
1091cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//
1092cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// @param[in] log_fd
1093cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//      The file descriptor to log to
1094cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//
1095cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// @param[in] fd
1096cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//      The file descriptor whose history should be dumped
1097cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
1098cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" void
1099cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonget_fd_history (int log_fd, int fd)
1100cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{
1101cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    // "create" below needs to be outside of the mutex locker scope
1102cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    if (log_fd >= 0)
1103cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    {
1104cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        bool got_lock = false;
1105cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        Locker locker (&g_mutex, got_lock);
1106cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        if (got_lock)
1107cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        {
1108cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            FDEventMap::iterator pos = g_fd_event_map.find (fd);
1109cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            log_to_fd (log_fd, "Dumping file descriptor history for fd=%i:\n", fd);
1110cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            if (pos != g_fd_event_map.end())
1111cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            {
1112cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                FDEventArray &event_array = g_fd_event_map[fd];
1113cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                const size_t num_events = event_array.size();
1114cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                for (size_t i=0; i<num_events; ++i)
1115cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                    event_array[i]->Dump (log_fd);
1116cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            }
1117cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            else
1118cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            {
1119cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton                log_to_fd (log_fd, "error: no file descriptor events found for fd=%i\n", fd);
1120cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            }
1121cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        }
1122cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        else
1123cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        {
1124cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton            log_to_fd (log_fd, "error: fd event mutex is locked...\n");
1125cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton        }
1126cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton    }
1127cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}
1128cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
1129cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
1130cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// Interposing
1131cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//----------------------------------------------------------------------
1132cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// FD creation routines
1133cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(accept$__interposed__, accept);
1134cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(accept$NOCANCEL$__interposed__, accept$NOCANCEL);
1135cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(dup$__interposed__, dup);
1136cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(dup2$__interposed__, dup2);
1137cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(kqueue$__interposed__, kqueue);
1138cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(open$__interposed__, open);
1139cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(open$NOCANCEL$__interposed__, open$NOCANCEL);
1140cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(__open_extended$__interposed__, __open_extended);
1141cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(pipe$__interposed__, pipe);
1142cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(shm_open$__interposed__, shm_open);
1143cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(socket$__interposed__, socket);
1144cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(socketpair$__interposed__, socketpair);
1145cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
1146cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// FD deleting routines
1147cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(close$__interposed__, close);
1148cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(close$NOCANCEL$__interposed__, close$NOCANCEL);
1149cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
1150cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} // namespace fd_interposing
1151cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
1152cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton
1153