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
                                    `. `'` 
                                      `-   

Attachment: signature.asc
Description: Digital signature

Reply via email to