diff --git Makefile Makefile
index 167225a..e45e338 100644
--- Makefile
+++ Makefile
@@ -7,7 +7,7 @@ LD	?= $(CC)
 prefix	= $(PREFIX)
 libdir	= $(prefix)/lib
 
-LOBJS	= syncdir.lo
+LOBJS	= syncdir.lo wrappers.lo
 
 LIBTOOL	= libtool --tag=CC
 
@@ -18,7 +18,7 @@ all:	libsyncdir.la
 	$(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c -o $@ $<
 
 testsync: testsync.lo libsyncdir.la
-	$(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ $< libsyncdir.la
+	$(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ testsync.lo libsyncdir.la
 
 libsyncdir.la: libtool-version-info $(LOBJS)
 	$(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ $(LOBJS) -version-info `cat libtool-version-info` -rpath $(libdir)
@@ -26,6 +26,28 @@ libsyncdir.la: libtool-version-info $(LOBJS)
 libtool-version-info:
 	echo $(VERSION) | awk -F. '{ printf "%d:%d:0", $$1, $$2 }' > $@
 
+wrappers.c: trysyscall.c
+	if $(CC) $(CFLAGS) -Wall -Werror -c trysyscall.c >/dev/null 2>&1; then cp syscall.c $@; else cp dlsym.c $@; fi
+
+wrappers.h: wrappers.c dlfcn.h fsync.h
+	if [ -f trysyscall.o ]; then cp syscall.h $@; else cp dlsym.h $@; fi
+
+dlfcn.h: trydlfcn.c
+	> $@
+	if ! $(CC) $(CFLAGS) -Wall -Werror -c trydlfcn.c >/dev/null 2>&1 \
+	&& $(CC) $(CFLAGS) -D_GNU_SOURCE=1 -Wall -Werror -c trydlfcn.c >/dev/null 2>&1; \
+	then echo "#define _GNU_SOURCE" >> $@; fi
+	echo "#include <dlfcn.h>" >> $@
+
+fsync.h: tryfsync.c
+	> $@
+	if $(CC) $(CFLAGS) -Wall -Werror -c tryfsync.c >/dev/null 2>&1; \
+	then echo "#define SYS_FSYNC(FD) syscall(SYS_fsync, FD)" >> $@; \
+	else echo "#define SYS_FSYNC(FD) fsync(FD)" >> $@; \
+	fi
+
+syncdir.lo: wrappers.h
+
 install:	all
 	$(LIBTOOL) --mode=install $(BSD_INSTALL_LIB) libsyncdir.la $(DESTDIR)$(libdir)
 
@@ -38,5 +60,6 @@ distrib:
 	$(RM) -r $(TARGET)
 
 clean:
-	$(RM) libtool-version-info core *.o *.lo *.la *.so *.a testsync $(TARGET).tar.gz
+	$(RM) core *.o *.lo *.la *.so *.a testsync $(TARGET).tar.gz
+	$(RM) libtool-version-info wrappers.c wrappers.h dlfcn.h fsync.h
 	$(RM) -r .libs
diff --git dlsym.c dlsym.c
new file mode 100644
index 0000000..0d78266
--- /dev/null
+++ dlsym.c
@@ -0,0 +1,37 @@
+#include "dlfcn.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+static int checked_noisy = 0;
+static int be_noisy = 0;
+
+int (*real_open)();
+int (*real_close)();
+int (*real_link)();
+int (*real_unlink)();
+int (*real_rename)();
+int (*real_fsync)();
+
+static void log_failure(const char *which)
+{
+  if (be_noisy) fprintf(stderr, "syncdir: can't load system %s()\n", which);
+}
+
+void load_dlsym_syscalls()
+{
+  if (!checked_noisy && getenv("SYNCDIRDEBUG"))
+    be_noisy = 1;
+
+  if (!real_open && !(real_open = dlsym(RTLD_NEXT, "open")))
+    log_failure("open");
+  if (!real_close && !(real_close = dlsym(RTLD_NEXT, "close")))
+    log_failure("close");
+  if (!real_link && !(real_link = dlsym(RTLD_NEXT, "link")))
+    log_failure("link");
+  if (!real_unlink && !(real_unlink = dlsym(RTLD_NEXT, "unlink")))
+    log_failure("unlink");
+  if (!real_rename && !(real_rename = dlsym(RTLD_NEXT, "rename")))
+    log_failure("rename");
+  if (!real_fsync && !(real_fsync = dlsym(RTLD_NEXT, "fsync")))
+    log_failure("fsync");
+}
diff --git dlsym.h dlsym.h
new file mode 100644
index 0000000..a25b9d3
--- /dev/null
+++ dlsym.h
@@ -0,0 +1,16 @@
+extern int (*real_open)();
+extern int (*real_close)();
+extern int (*real_link)();
+extern int (*real_unlink)();
+extern int (*real_rename)();
+extern int (*real_fsync)();
+
+#define SYS_OPEN(FILE,FLAG,MODE) real_open(FILE, FLAG, MODE)
+#define SYS_CLOSE(FD) real_close(FD)
+#define SYS_LINK(OLD,NEW) real_link(OLD, NEW)
+#define SYS_UNLINK(PATH) real_unlink(PATH)
+#define SYS_RENAME(OLD,NEW) real_rename(OLD, NEW)
+#define SYS_FSYNC(FD) real_fsync(FD)
+
+void load_dlsym_syscalls(void);
+#define load_real_syscalls(x) load_dlsym_syscalls(x)
diff --git syncdir.c syncdir.c
index 2ec2b46..22371a4 100644
--- syncdir.c
+++ syncdir.c
@@ -25,16 +25,10 @@
 #undef open
 #include <unistd.h>
 #include <string.h>
-#include <sys/syscall.h>
 #include <stdio.h>
 #include <errno.h>
 
-#define SYS_OPEN(FILE,FLAG,MODE) syscall(SYS_open, FILE, FLAG, MODE)
-#define SYS_CLOSE(FD) syscall(SYS_close, FD)
-#define SYS_LINK(OLD,NEW) syscall(SYS_link, OLD, NEW)
-#define SYS_UNLINK(PATH) syscall(SYS_unlink, PATH)
-#define SYS_RENAME(OLD,NEW) syscall(SYS_rename, OLD, NEW)
-#define SYS_FSYNC(FD) syscall(SYS_fsync, FD)
+#include "wrappers.h"
 
 static int fdirsync(const char* filename, unsigned length)
 {
@@ -43,6 +37,7 @@ static int fdirsync(const char* filename, unsigned length)
    * char* dirname = alloca(length+1); */
   int dirfd;
   int retval;
+  load_real_syscalls();
   memcpy(dirname, filename, length);
   dirname[length] = 0;
   if((dirfd = SYS_OPEN(dirname,O_RDONLY,0)) == -1)
@@ -75,7 +70,9 @@ static int fdirsyncfn(const char *filename)
 
 int open(const char *file,int oflag,mode_t mode)
 {
-  int fd = SYS_OPEN(file, oflag, mode);
+  int fd;
+  load_real_syscalls();
+  fd = SYS_OPEN(file, oflag, mode);
   if(fd == -1)
     return fd;
   if (oflag & (O_WRONLY | O_RDWR))
@@ -88,6 +85,7 @@ int open(const char *file,int oflag,mode_t mode)
 
 int link(const char *oldpath,const char *newpath)
 {
+   load_real_syscalls();
    if(SYS_LINK(oldpath,newpath) == -1)
      return -1;
    return fdirsyncfn(newpath);
@@ -95,6 +93,7 @@ int link(const char *oldpath,const char *newpath)
 
 int unlink(const char *path)
 {
+   load_real_syscalls();
    if(SYS_UNLINK(path) == -1)
      return -1;
    return fdirsyncfn(path);
@@ -102,6 +101,7 @@ int unlink(const char *path)
 
 int rename(const char *oldpath,const char *newpath)
 {
+   load_real_syscalls();
    if (SYS_RENAME(oldpath,newpath) == -1)
      return -1;
    if (fdirsyncfn(newpath) == -1)
diff --git syscall.c syscall.c
new file mode 100644
index 0000000..092bc2b
--- /dev/null
+++ syscall.c
@@ -0,0 +1 @@
+;
diff --git syscall.h syscall.h
new file mode 100644
index 0000000..05cdaf6
--- /dev/null
+++ syscall.h
@@ -0,0 +1,11 @@
+#include <sys/syscall.h>
+
+#define SYS_OPEN(FILE,FLAG,MODE) syscall(SYS_open, FILE, FLAG, MODE)
+#define SYS_CLOSE(FD) syscall(SYS_close, FD)
+#define SYS_LINK(OLD,NEW) syscall(SYS_link, OLD, NEW)
+#define SYS_UNLINK(PATH) syscall(SYS_unlink, PATH)
+#define SYS_RENAME(OLD,NEW) syscall(SYS_rename, OLD, NEW)
+
+#include "fsync.h"
+
+#define load_real_syscalls(x) ;
diff --git trydlfcn.c trydlfcn.c
new file mode 100644
index 0000000..3104198
--- /dev/null
+++ trydlfcn.c
@@ -0,0 +1,6 @@
+#include <dlfcn.h>
+
+int main(void) {
+  if (dlsym(RTLD_NEXT, "foo")) return 1;
+  return 0;
+}
diff --git tryfsync.c tryfsync.c
new file mode 100644
index 0000000..f18cdbf
--- /dev/null
+++ tryfsync.c
@@ -0,0 +1,6 @@
+#include <sys/syscall.h>
+#include <unistd.h>
+
+int main(void) {
+  return syscall(SYS_fsync, 1);
+}
diff --git trysyscall.c trysyscall.c
new file mode 100644
index 0000000..1413974
--- /dev/null
+++ trysyscall.c
@@ -0,0 +1,6 @@
+#include <sys/syscall.h>
+#include <unistd.h>
+
+int main(void) {
+  return syscall(5);
+}
