blob: 94cf27ac9e0da42a963b053fad4cda6fc287ec1d [file]
#define open Oopen
#define open64 Oopen64
#define openat Oopenat
#define openat64 Oopenat64
#define rename Orename
#define unlink Ounlink
#define fopen Ofopen
#define fopen64 Ofopen64
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <limits.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#include "fsatrace.h"
#undef open
#undef open64
#undef openat
#undef openat64
#undef rename
#undef unlink
#undef fopen
#undef fopen64
static int s_fd;
static char *s_buf;
static const int wmode = O_RDWR | O_WRONLY | O_APPEND | O_CREAT | O_TRUNC;
static int
good(const char *s, int sz)
{
int i;
int bad = 0;
for (i = 0; i < sz; i++)
bad += s[i] == 0;
return !bad;
}
static void
swrite(const char *p, int sz)
{
int g;
char *dst = s_buf + sizeof(size_t);
size_t *psofar = (size_t *) s_buf;
size_t sofar;
if (!s_buf)
return;
sofar = __sync_fetch_and_add(psofar, sz);
memcpy(dst + sofar, p, sz);
g = good(p, sz);
if (!g)
fprintf(stderr, "BAD: %s\n", p);
assert(g);
}
static void
__attribute((constructor(101)))
init()
{
const char *shname = getenv(ENVOUT);
s_fd = shm_open(shname, O_RDWR, 0666);
s_buf = mmap(0, LOGSZ, PROT_READ | PROT_WRITE, MAP_SHARED, s_fd, 0);
assert(s_fd >= 0);
}
static void
__attribute((destructor(101)))
term()
{
munmap(s_buf, LOGSZ);
close(s_fd);
}
static inline void
iemit(int c, const char *p1, const char *p2)
{
char buf [10000];
int sz = 0;
sz += snprintf(buf, sizeof(buf) - 1 - sz, "%c|%s", c, p1);
if (p2)
sz += snprintf(buf + sz, sizeof(buf) - 1 - sz, "|%s", p2);
sz += snprintf(buf + sz, sizeof(buf) - 1 - sz, "\n");
assert(sz < sizeof(buf) - 1);
buf[sz] = 0;
swrite(buf, sz);
}
static void
emit(int c, const char *p1)
{
char ap [PATH_MAX];
iemit(c, realpath(p1, ap), 0);
}
FILE *
fopen(const char *p, const char *m)
{
FILE *r;
static FILE *(*ofopen) (const char *, const char *)= 0;
if (!ofopen)
ofopen = dlsym(RTLD_NEXT, "fopen");
assert(ofopen);
r = ofopen(p, m);
if (r)
emit(strchr(m, 'r') ? 'r' : 'w', p);
return r;
}
FILE *
fopen64(const char *p, const char *m)
{
FILE *r;
static FILE *(*ofopen64) (const char *, const char *)= 0;
if (!ofopen64)
ofopen64 = dlsym(RTLD_NEXT, "fopen64");
assert(ofopen64);
r = ofopen64(p, m);
if (r)
emit(strchr(m, 'r') ? 'r' : 'w', p);
return r;
}
int
open(const char *p, int f, mode_t m)
{
int r;
static int (*oopen) (const char *, int, mode_t)= 0;
if (!oopen)
oopen = dlsym(RTLD_NEXT, "open");
assert(oopen);
r = oopen(p, f, m);
if (r >= 0)
emit(f & wmode ? 'w' : 'r', p);
return r;
}
int
open64(const char *p, int f, mode_t m)
{
int r;
static int (*oopen64) (const char *, int, mode_t)= 0;
if (!oopen64)
oopen64 = dlsym(RTLD_NEXT, "open64");
assert(oopen64);
r = oopen64(p, f, m);
if (r >= 0)
emit(f & wmode ? 'w' : 'r', p);
return r;
}
int
openat(int fd, const char *p, int f, mode_t m)
{
int r;
if (fd != AT_FDCWD) {
static int (*oopenat) (int, const char *, int, mode_t)= 0;
if (!oopenat)
oopenat = dlsym(RTLD_NEXT, "openat");
assert(oopenat);
r = oopenat(fd, p, f, m);
if (r >= 0)
iemit(f & wmode ? 'W' : 'R', p, 0);
}
else
r = open(p, f, m);
return r;
}
int
openat64(int fd, const char *p, int f, mode_t m)
{
int r;
if (fd != AT_FDCWD) {
static int (*oopenat64) (int, const char *, int, mode_t)= 0;
if (!oopenat64)
oopenat64 = dlsym(RTLD_NEXT, "openat64");
assert(oopenat64);
r = oopenat64(fd, p, f, m);
if (r >= 0)
iemit(f & wmode ? 'W' : 'R', p, 0);
}
else
r = open64(p, f, m);
return r;
}
int
rename(const char *p1, const char *p2)
{
int r;
char b1 [PATH_MAX];
char b2 [PATH_MAX];
char *rp1 = realpath(p1, b1);
static int (*orename) (const char *, const char *)= 0;
if (!orename)
orename = dlsym(RTLD_NEXT, "rename");
assert(orename);
r = orename(p1, p2);
if (!r)
iemit('m', realpath(p2, b2), rp1);
return r;
}
int
renameat(int fd1, const char *p1, int fd2, const char *p2)
{
int r;
if (fd1 != AT_FDCWD || fd2 != AT_FDCWD) {
static int (*orenameat) (const char *, const char *)= 0;
if (!orenameat)
orenameat = dlsym(RTLD_NEXT, "renameat");
assert(orenameat);
r = orenameat(p1, p2);
if (!r)
iemit('R', p2, p1);
}
else
r = rename(p1, p2);
return r;
}
int
unlink(const char *p)
{
int r;
char b [PATH_MAX];
char *rp = realpath(p, b);
static int (*ounlink) (const char *)= 0;
if (!ounlink)
ounlink = dlsym(RTLD_NEXT, "unlink");
assert(ounlink);
r = ounlink(p);
if (!r)
iemit('d', rp, 0);
return r;
}
int
unlinkat(int fd, const char *p, int f)
{
int r;
if (fd != AT_FDCWD) {
static int (*ounlinkat) (int fd, const char *p, int f);
if (!ounlinkat)
ounlinkat = dlsym(RTLD_NEXT, "unlinkat");
assert(ounlinkat);
r = ounlinkat(fd, p, f);
if (!r)
iemit('D', p, 0);
assert(0);
}
else if (f & AT_REMOVEDIR)
r = rmdir(p);
else
r = unlink(p);
return r;
}