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 " >> $@ + +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 +#include + +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 #include -#include #include #include -#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 + +#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 + +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 +#include + +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 +#include + +int main(void) { + return syscall(5); +}