voyeur-0.1.0.0: libvoyeur/src/voyeur-open.c
#ifndef __APPLE__
#define _GNU_SOURCE
#endif
#include <fcntl.h>
#include <pthread.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include "dyld.h"
#include "env.h"
#include "net.h"
typedef int (*open_fptr_t)(const char*, int, ...);
VOYEUR_STATIC_DECLARE_NEXT(open_fptr_t, open)
static pthread_mutex_t voyeur_open_mutex = PTHREAD_MUTEX_INITIALIZER;
static char voyeur_open_initialized = 0;
static uint8_t voyeur_open_opts = 0;
static int voyeur_open_sock = 0;
__attribute__((destructor)) void voyeur_cleanup_open()
{
pthread_mutex_lock(&voyeur_open_mutex);
if (voyeur_open_initialized) {
if (voyeur_open_sock >= 0) {
voyeur_write_msg_type(voyeur_open_sock, VOYEUR_MSG_DONE);
voyeur_close_socket(voyeur_open_sock);
voyeur_open_sock = -1;
}
voyeur_open_initialized = 0;
}
pthread_mutex_unlock(&voyeur_open_mutex);
}
int VOYEUR_FUNC(open)(const char* path, int oflag, ...)
{
pthread_mutex_lock(&voyeur_open_mutex);
if (!voyeur_open_initialized) {
const char* voyeur_open_sockpath = getenv("LIBVOYEUR_SOCKET");
voyeur_open_opts = voyeur_decode_options(getenv("LIBVOYEUR_OPTS"),
VOYEUR_EVENT_OPEN);
voyeur_open_sock = voyeur_create_client_socket(voyeur_open_sockpath);
VOYEUR_LOOKUP_NEXT(open_fptr_t, open);
voyeur_open_initialized = 1;
}
// Extract the mode argument if necessary.
mode_t mode;
if (oflag & O_CREAT) {
va_list args;
va_start(args, oflag);
// Note that 'int' is used instead of 'mode_t' due to warnings
// that mode_t, being in reality a short on OS X, is of promotable
// type, which is verboten for va_arg.
mode = va_arg(args, int);
va_end(args);
}
// Pass through the call to the real open.
int retval;
if (oflag & O_CREAT) {
retval = VOYEUR_CALL_NEXT(open, path, oflag, mode);
} else {
retval = VOYEUR_CALL_NEXT(open, path, oflag);
}
// Write the event to the socket.
if (voyeur_open_sock >= 0) {
voyeur_write_msg_type(voyeur_open_sock, VOYEUR_MSG_EVENT);
voyeur_write_event_type(voyeur_open_sock, VOYEUR_EVENT_OPEN);
voyeur_write_string(voyeur_open_sock, path, 0);
voyeur_write_int(voyeur_open_sock, oflag);
if (oflag & O_CREAT) {
voyeur_write_int(voyeur_open_sock, (int) mode);
} else {
voyeur_write_int(voyeur_open_sock, 0);
}
voyeur_write_int(voyeur_open_sock, retval);
if (voyeur_open_opts & OBSERVE_OPEN_CWD) {
char* cwd = getcwd(NULL, 0);
voyeur_write_string(voyeur_open_sock, cwd, 0);
free(cwd);
}
voyeur_write_pid(voyeur_open_sock, getpid());
}
pthread_mutex_unlock(&voyeur_open_mutex);
return retval;
}
VOYEUR_INTERPOSE(open)