In order to make the build reproducible, we ensure that the files are written to the .deb in a deterministic file order. ---
Here is a test case for pkg-tests that should ensure that files are always written in the same order in the control and data tarball, despite what readdir() says. t-deterministic-file-order/Makefile | 28 +++++ t-deterministic-file-order/hookdir.c | 110 ++++++++++++++++++++ .../pkg-file-order/DEBIAN/control | 7 ++ .../pkg-file-order/DEBIAN/md5sums | 2 + 4 files changed, 147 insertions(+) create mode 100644 t-deterministic-file-order/Makefile create mode 100644 t-deterministic-file-order/hookdir.c create mode 100644 t-deterministic-file-order/pkg-file-order/DEBIAN/control create mode 100644 t-deterministic-file-order/pkg-file-order/DEBIAN/md5sums create mode 100644 t-deterministic-file-order/pkg-file-order/a create mode 100644 t-deterministic-file-order/pkg-file-order/b diff --git a/t-deterministic-file-order/Makefile b/t-deterministic-file-order/Makefile new file mode 100644 index 0000000..5ba11b0 --- /dev/null +++ b/t-deterministic-file-order/Makefile @@ -0,0 +1,28 @@ +include ../Test.mk + +test-case: libhookdir.so + rm -rf pkg-file-order-1 && cp -a pkg-file-order pkg-file-order-1 + rm -rf pkg-file-order-2 && cp -a pkg-file-order pkg-file-order-2 + + $(DPKG_BUILD_DEB) pkg-file-order-1 + LD_PRELOAD=$$(pwd)/libhookdir.so $(DPKG_BUILD_DEB) pkg-file-order-2 + + ar x pkg-file-order-1.deb + tar -ztf control.tar.gz > content-control-1 + tar -atf data.tar.* > content-data-1 + ar x pkg-file-order-2.deb + tar -ztf control.tar.gz > content-control-2 + tar -atf data.tar.* > content-data-2 + diff -u content-control-1 content-control-2 + diff -u content-data-1 content-data-2 + +test-clean: + rm -rf pkg-file-order-1 pkg-file-order-2 + rm -f pkg-file-order-1.deb pkg-file-order-2.deb + rm -f data.tar.* control.tar.* debian-binary + rm -f content-control-1 content-control-2 + rm -f content-data-1 content-data-2 + rm -f libhookdir.so + +libhookdir.so: hookdir.c + gcc -Wall -shared -fPIC -o $@ $< -ldl diff --git a/t-deterministic-file-order/hookdir.c b/t-deterministic-file-order/hookdir.c new file mode 100644 index 0000000..49c4bd1 --- /dev/null +++ b/t-deterministic-file-order/hookdir.c @@ -0,0 +1,110 @@ +/* libhookdir.c: LD_PRELOAD lib to return readdir() results in reverse order + * Code snippet from Niklas B. copied from <http://stackoverflow.com/a/8866709> + * Licensed under CC BY-SA 3.0 + */ + +#define _GNU_SOURCE 1 +#include <stdio.h> +#include <dirent.h> +#include <dlfcn.h> +#include <stdlib.h> +#include <string.h> + +struct __dirstream +{ + int __fd; + char *__data; + size_t __allocation; + size_t __offset; + size_t __size; + struct dirent __entry; +}; + +typedef struct _dirent_list { + struct dirent *value; + struct _dirent_list *next; +} dirent_list; + +typedef struct _my_DIR { + struct __dirstream orig; + dirent_list *first_entry; + int first_readdir; +} my_DIR; + +DIR *fdopendir(int fd) { + DIR *(*orig_fdopendir)(int) = dlsym(RTLD_NEXT, "fdopendir"); + DIR *dir = orig_fdopendir(fd); + + // save additional information along with the + // original DIR structure + my_DIR *my_dir = calloc(1, sizeof(*my_dir)); + my_dir->first_readdir = 1; + memcpy(my_dir, dir, sizeof(*dir)); + return (DIR*)my_dir; +} + +DIR *opendir(const char *name) { + DIR *(*orig_opendir)(const char*) = dlsym(RTLD_NEXT, "opendir"); + DIR *dir = orig_opendir(name); + + // save additional information along with the + // original DIR structure + my_DIR *my_dir = calloc(1, sizeof(*my_dir)); + my_dir->first_readdir = 1; + memcpy(my_dir, dir, sizeof(*dir)); + return (DIR*)my_dir; +} + +struct dirent *readdir(DIR *dir) { + struct dirent *(*orig_readdir)(DIR*) = dlsym(RTLD_NEXT, "readdir"); + my_DIR *my_dir = (my_DIR*)dir; + dirent_list *item; + + if (my_dir->first_readdir) { + struct dirent *entry; + while ((entry = orig_readdir(dir))) { + item = calloc(1, sizeof(*item)); + item->value = entry; + item->next = my_dir->first_entry; + my_dir->first_entry = item; + } + my_dir->first_readdir = 0; + } + + if (!my_dir->first_entry) + return NULL; + + item = my_dir->first_entry; + struct dirent *result = item->value; + my_dir->first_entry = item->next; + free(item); + + return result; +} + +int closedir(DIR *dir) { + int (*orig_closedir)(DIR *) = dlsym(RTLD_NEXT, "closedir"); + + return orig_closedir(dir); +} + +long telldir(DIR *dir) { + long (*orig_telldir)(DIR *) = dlsym(RTLD_NEXT, "telldir"); + + fprintf(stderr, "telldir(%p): not properly implemented in libhookdir\n", dir); + return orig_telldir(dir); +} + +void seekdir(DIR *dir, long offset) { + void (*orig_seekdir)(DIR *, long) = dlsym(RTLD_NEXT, "seekdir"); + + fprintf(stderr, "seekdir(%p, %ld): not properly implemented in libhookdir\n", dir, offset); + return orig_seekdir(dir, offset); +} + +void rewinddir(DIR *dir) { + void (*orig_rewinddir)(DIR *) = dlsym(RTLD_NEXT, "rewinddir"); + + fprintf(stderr, "rewinddir(%p): not properly implemented in libhookdir\n", dir); + return orig_rewinddir(dir); +} diff --git a/t-deterministic-file-order/pkg-file-order/DEBIAN/control b/t-deterministic-file-order/pkg-file-order/DEBIAN/control new file mode 100644 index 0000000..a7f4437 --- /dev/null +++ b/t-deterministic-file-order/pkg-file-order/DEBIAN/control @@ -0,0 +1,7 @@ +Package: pkg-file-order +Version: 0.0-1 +Section: test +Priority: extra +Maintainer: Dpkg Developers <debian-d...@lists.debian.org> +Architecture: all +Description: test package for deterministic file ordering diff --git a/t-deterministic-file-order/pkg-file-order/DEBIAN/md5sums b/t-deterministic-file-order/pkg-file-order/DEBIAN/md5sums new file mode 100644 index 0000000..70ef2fa --- /dev/null +++ b/t-deterministic-file-order/pkg-file-order/DEBIAN/md5sums @@ -0,0 +1,2 @@ +d41d8cd98f00b204e9800998ecf8427e a +d41d8cd98f00b204e9800998ecf8427e b diff --git a/t-deterministic-file-order/pkg-file-order/a b/t-deterministic-file-order/pkg-file-order/a new file mode 100644 index 0000000..e69de29 diff --git a/t-deterministic-file-order/pkg-file-order/b b/t-deterministic-file-order/pkg-file-order/b new file mode 100644 index 0000000..e69de29 -- Lunar .''`. lu...@debian.org : :Ⓐ : # apt-get install anarchism `. `'` `-
signature.asc
Description: Digital signature