aboutsummaryrefslogtreecommitdiffstats
path: root/testing/aufs-util
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2017-01-18 07:50:19 -0300
committerNatanael Copa <ncopa@alpinelinux.org>2017-01-18 07:53:02 -0300
commit4638928b779efbfe274248d2d52f44e275c52957 (patch)
tree80ba08aea12564cac3e54a84f79d751631934885 /testing/aufs-util
parentdf5167a5ac6280b82c94e22e18ee9da744e90c68 (diff)
downloadaports-4638928b779efbfe274248d2d52f44e275c52957.tar.bz2
aports-4638928b779efbfe274248d2d52f44e275c52957.tar.xz
testing/aufs-utils: new aport
utils for aufs
Diffstat (limited to 'testing/aufs-util')
-rw-r--r--testing/aufs-util/0001-implement-glibc-compatible-nftw-if-libc-does-not-pro.patch536
-rw-r--r--testing/aufs-util/0002-add-aufs_type.h-from-linux-header.patch441
-rw-r--r--testing/aufs-util/0003-make-install-compatible-with-busybox-install.patch26
-rw-r--r--testing/aufs-util/APKBUILD43
4 files changed, 1046 insertions, 0 deletions
diff --git a/testing/aufs-util/0001-implement-glibc-compatible-nftw-if-libc-does-not-pro.patch b/testing/aufs-util/0001-implement-glibc-compatible-nftw-if-libc-does-not-pro.patch
new file mode 100644
index 0000000000..27a550b0f6
--- /dev/null
+++ b/testing/aufs-util/0001-implement-glibc-compatible-nftw-if-libc-does-not-pro.patch
@@ -0,0 +1,536 @@
+From d29a5a61509eeb3dbde375c74c5ec2a9ec0e82ec Mon Sep 17 00:00:00 2001
+From: Natanael Copa <natanael.copa@docker.com>
+Date: Thu, 29 Sep 2016 14:49:26 +0200
+Subject: [PATCH 1/3] implement glibc compatible nftw if libc does not provide
+ it
+
+This is so we can use the exact same code without resorting to call an
+external script on musl libc.
+
+Signed-off-by: Natanael Copa <natanael.copa@docker.com>
+---
+ Makefile | 9 --
+ au_nftw.h | 20 +++++
+ auplink_ftw | 58 ------------
+ extlib/glibc/au_nftw.c | 80 -----------------
+ extlib/non-glibc/au_nftw.c | 215 +++++++++++++++++++++++++++++----------------
+ plink.c | 56 ++++++++++++
+ 6 files changed, 215 insertions(+), 223 deletions(-)
+ create mode 100644 au_nftw.h
+ delete mode 100755 auplink_ftw
+ delete mode 100644 extlib/glibc/au_nftw.c
+
+diff --git a/Makefile b/Makefile
+index 3838f0e..ffa4b11 100644
+--- a/Makefile
++++ b/Makefile
+@@ -90,12 +90,6 @@ Etc = etc_default_aufs
+ Bin = auibusy aumvdown auplink mount.aufs umount.aufs #auctl
+ BinObj = $(addsuffix .o, ${Bin})
+
+-ifeq (${Glibc},no)
+-AuplinkFtwCmd=/sbin/auplink_ftw
+-override CPPFLAGS += -DAUPLINK_FTW_CMD=\"${AuplinkFtwCmd}\"
+-Cmd += auplink_ftw
+-endif
+-
+ # suppress 'eval' for ${v}
+ $(foreach v, CC CPPFLAGS CFLAGS INSTALL Install ManDir TopDir LibUtilHdr \
+ Glibc LibAuDir ExtlibPath, \
+@@ -155,9 +149,6 @@ c2sh c2tmac ver: CC = ${HOSTCC}
+ .INTERMEDIATE: c2sh c2tmac ver
+
+ install_sbin: File = auibusy aumvdown auplink mount.aufs umount.aufs
+-ifeq (${Glibc},no)
+-install_sbin: File += auplink_ftw
+-endif
+ install_sbin: Tgt = ${DESTDIR}/sbin
+ install_ubin: File = aubusy auchk aubrsync #auctl
+ install_ubin: Tgt = ${DESTDIR}/usr/bin
+diff --git a/au_nftw.h b/au_nftw.h
+new file mode 100644
+index 0000000..4b1c724
+--- /dev/null
++++ b/au_nftw.h
+@@ -0,0 +1,20 @@
++#include <ftw.h>
++
++#if defined(FTW_ACTIONRETVAL) && defined(FTW_CONTINUE) && defined(FTW_SKIP_SUBTREE)
++#define au_nftw nftw
++#else
++
++#ifndef FTW_CONTINUE
++#define FTW_CONTINUE 0
++#endif
++
++#ifndef FTW_SKIP_SUBTREE
++#define FTW_SKIP_SUBTREE 2
++#endif
++
++#ifndef FTW_ACTIONRETVAL
++#define FTW_ACTIONRETVAL 16
++#endif
++
++int au_nftw(const char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int fd_limit, int flags);
++#endif
+diff --git a/auplink_ftw b/auplink_ftw
+deleted file mode 100755
+index 9d1564d..0000000
+--- a/auplink_ftw
++++ /dev/null
+@@ -1,58 +0,0 @@
+-#!/bin/sh
+-
+-# Copyright (C) 2016 Junjiro R. Okajima
+-#
+-# This program, aufs is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
+-# (at your option) any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+-
+-# usage: $0 inum_list dir list|cpup
+-
+-tmp=/tmp/$$
+-set -eu
+-rc=${DebugRc:-/etc/default/aufs}
+-. $rc
+-
+-inum=$1
+-dir=$2
+-action=$3
+-
+-# build the grep pattern
+-sed -e 's/^/^/' $inum > $tmp.inum
+-
+-Find()
+-{
+- find $dir -xdev -name $AUFS_WH_PLINKDIR -prune \
+- -o -printf "%i %p\0" | #2> /dev/null |
+- grep -z -w -f $tmp.inum |
+- sed -e 's/^[0-9][0-9]* //g' -e 's/\x00[0-9][0-9]* /\x00/g'
+-}
+-
+-err=0
+-case $3 in
+-list)
+- Find |
+- tr '\0' '\n'
+- ;;
+-cpup)
+- Find |
+- xargs -r0 touch -ac
+- ;;
+-*)
+- echo Usage
+- err=1
+- ;;
+-esac
+-
+-rm -fr $tmp $tmp.*
+-exit $err
+diff --git a/extlib/glibc/au_nftw.c b/extlib/glibc/au_nftw.c
+deleted file mode 100644
+index 3ff7ad2..0000000
+--- a/extlib/glibc/au_nftw.c
++++ /dev/null
+@@ -1,80 +0,0 @@
+-/*
+- * Copyright (C) 2005-2016 Junjiro R. Okajima
+- *
+- * This program, aufs is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+- */
+-
+-#include <ftw.h>
+-#include <stdio.h>
+-#include <string.h>
+-#include <unistd.h>
+-
+-#include <linux/aufs_type.h>
+-#include "au_util.h"
+-
+-static int ia_test(ino_t ino)
+-{
+- int i;
+- ino_t *p;
+-
+- /* todo: hash table */
+- ia.p = ia.o;
+- p = ia.cur;
+- for (i = 0; i < ia.nino; i++)
+- if (*p++ == ino)
+- return 1;
+- return 0;
+-}
+-
+-
+-int ftw_list(const char *fname, const struct stat *st, int flags,
+- struct FTW *ftw)
+-{
+- if (!strcmp(fname + ftw->base, AUFS_WH_PLINKDIR))
+- return FTW_SKIP_SUBTREE;
+- if (flags == FTW_D || flags == FTW_DNR)
+- return FTW_CONTINUE;
+-
+- if (ia_test(st->st_ino))
+- puts(fname);
+-
+- return FTW_CONTINUE;
+-}
+-
+-int ftw_cpup(const char *fname, const struct stat *st, int flags,
+- struct FTW *ftw)
+-{
+- int err;
+-
+- if (!strcmp(fname + ftw->base, AUFS_WH_PLINKDIR))
+- return FTW_SKIP_SUBTREE;
+- if (flags == FTW_D || flags == FTW_DNR)
+- return FTW_CONTINUE;
+-
+- /*
+- * do nothing but update something harmless in order to make it copyup
+- */
+- if (ia_test(st->st_ino)) {
+- Dpri("%s\n", fname);
+- if (!S_ISLNK(st->st_mode))
+- err = chown(fname, -1, -1);
+- else
+- err = lchown(fname, -1, -1);
+- if (err)
+- AuFin("%s", fname);
+- }
+-
+- return FTW_CONTINUE;
+-}
+diff --git a/extlib/non-glibc/au_nftw.c b/extlib/non-glibc/au_nftw.c
+index 8e053a4..15ab929 100644
+--- a/extlib/non-glibc/au_nftw.c
++++ b/extlib/non-glibc/au_nftw.c
+@@ -1,90 +1,153 @@
+ /*
+- * Copyright (C) 2016 Junjiro R. Okajima
+- *
+- * This program, aufs is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+- */
++copied from musl libc and added support for FWT_SKIP_SUBTREE
+
+-#include <sys/stat.h>
+-#include <sys/types.h>
++musl as a whole is licensed under the following standard MIT license:
++
++----------------------------------------------------------------------
++Copyright © 2005-2014 Rich Felker, et al.
++
++Permission is hereby granted, free of charge, to any person obtaining
++a copy of this software and associated documentation files (the
++"Software"), to deal in the Software without restriction, including
++without limitation the rights to use, copy, modify, merge, publish,
++distribute, sublicense, and/or sell copies of the Software, and to
++permit persons to whom the Software is furnished to do so, subject to
++the following conditions:
++
++The above copyright notice and this permission notice shall be
++included in all copies or substantial portions of the Software.
++
++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
++CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
++TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
++SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
++----------------------------------------------------------------------
++*/
+ #include <ftw.h>
+-#include <stdio.h>
+-#include <stdlib.h>
++#include <dirent.h>
++#include <sys/stat.h>
++#include <errno.h>
++#include <unistd.h>
++#include <string.h>
++#include <limits.h>
++#include <pthread.h>
+
+-#include "au_util.h"
++#include "au_nftw.h"
+
+-/* dummy */
+-int ftw_list(const char *fname, const struct stat *st, int flags,
+- struct FTW *ftw)
++struct history
+ {
+- return 0;
+-}
++ struct history *chain;
++ dev_t dev;
++ ino_t ino;
++ int level;
++ int base;
++};
++
++#undef dirfd
++#define dirfd(d) (*(int *)d)
+
+-/* dummy */
+-int ftw_cpup(const char *fname, const struct stat *st, int flags,
+- struct FTW *ftw)
++static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int fd_limit, int flags, struct history *h)
+ {
++ size_t l = strlen(path), j = l && path[l-1]=='/' ? l-1 : l;
++ struct stat st;
++ struct history new;
++ int type;
++ int r;
++ struct FTW lev;
++ char *name;
++
++ if ((flags & FTW_PHYS) ? lstat(path, &st) : stat(path, &st) < 0) {
++ if (!(flags & FTW_PHYS) && errno==ENOENT && !lstat(path, &st))
++ type = FTW_SLN;
++ else if (errno != EACCES) return -1;
++ else type = FTW_NS;
++ } else if (S_ISDIR(st.st_mode)) {
++ if (access(path, R_OK) < 0) type = FTW_DNR;
++ else if (flags & FTW_DEPTH) type = FTW_DP;
++ else type = FTW_D;
++ } else if (S_ISLNK(st.st_mode)) {
++ if (flags & FTW_PHYS) type = FTW_SL;
++ else type = FTW_SLN;
++ } else {
++ type = FTW_F;
++ }
++
++ if ((flags & FTW_MOUNT) && h && st.st_dev != h->dev)
++ return 0;
++
++ new.chain = h;
++ new.dev = st.st_dev;
++ new.ino = st.st_ino;
++ new.level = h ? h->level+1 : 0;
++ new.base = l+1;
++
++ lev.level = new.level;
++ lev.base = h ? h->base : (name=strrchr(path, '/')) ? name-path : 0;
++
++ if (!(flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev)))
++ return ((flags & FTW_ACTIONRETVAL)
++ && (r == FTW_SKIP_SUBTREE)
++ && (type == FTW_D)) ? FTW_CONTINUE : r;
++
++ for (; h; h = h->chain)
++ if (h->dev == st.st_dev && h->ino == st.st_ino)
++ return 0;
++
++ if ((type == FTW_D || type == FTW_DP) && fd_limit) {
++ DIR *d = opendir(path);
++ if (d) {
++ struct dirent *de;
++ while ((de = readdir(d))) {
++ if (de->d_name[0] == '.'
++ && (!de->d_name[1]
++ || (de->d_name[1]=='.'
++ && !de->d_name[2]))) continue;
++ if (strlen(de->d_name) >= PATH_MAX-l) {
++ errno = ENAMETOOLONG;
++ closedir(d);
++ return -1;
++ }
++ path[j]='/';
++ strcpy(path+j+1, de->d_name);
++ if ((r=do_nftw(path, fn, fd_limit-1, flags, &new))) {
++ closedir(d);
++ return r;
++ }
++ }
++ closedir(d);
++ } else if (errno != EACCES) {
++ return -1;
++ }
++ }
++
++ path[l] = 0;
++ if ((flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev)))
++ return r;
++
+ return 0;
+ }
+
+-int au_nftw(const char *dirpath,
+- int (*fn) (const char *fpath, const struct stat *sb,
+- int typeflag, struct FTW *ftwbuf),
+- int nopenfd, int flags)
++int au_nftw(const char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int fd_limit, int flags)
+ {
+- int err, fd, i;
+- mode_t mask;
+- FILE *fp;
+- ino_t *p;
+- char *action, ftw[1024], tmp[] = "/tmp/auplink_ftw.XXXXXX";
+-
+- mask = umask(S_IRWXG | S_IRWXO);
+- fd = mkstemp(tmp);
+- if (fd < 0)
+- AuFin("mkstemp");
+- umask(mask);
+- fp = fdopen(fd, "r+");
+- if (!fp)
+- AuFin("fdopen");
+-
+- ia.p = ia.o;
+- p = ia.cur;
+- for (i = 0; i < ia.nino; i++) {
+- err = fprintf(fp, "%llu\n", (unsigned long long)*p++);
+- if (err < 0)
+- break;
++ int r, cs;
++ size_t l;
++ char pathbuf[PATH_MAX+1];
++
++ if (fd_limit <= 0) return 0;
++
++ l = strlen(path);
++ if (l > PATH_MAX) {
++ errno = ENAMETOOLONG;
++ return -1;
+ }
+- err = fflush(fp) || ferror(fp);
+- if (err)
+- AuFin("%s", tmp);
+- err = fclose(fp);
+- if (err)
+- AuFin("%s", tmp);
+-
+- action = "list";
+- if (fn == ftw_cpup)
+- action = "cpup";
+- else
+- fflush(stdout); /* inode numbers */
+- i = snprintf(ftw, sizeof(ftw), AUPLINK_FTW_CMD " %s %s %s",
+- tmp, dirpath, action);
+- if (i > sizeof(ftw))
+- AuFin("snprintf");
+- err = system(ftw);
+- err = WEXITSTATUS(err);
+- if (err)
+- AuFin("%s", ftw);
+-
+- return err;
++ memcpy(pathbuf, path, l+1);
++
++ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
++ r = do_nftw(pathbuf, fn, fd_limit, flags, NULL);
++ pthread_setcancelstate(cs, 0);
++ return r;
+ }
++
+diff --git a/plink.c b/plink.c
+index a048ed1..00c73c9 100644
+--- a/plink.c
++++ b/plink.c
+@@ -33,6 +33,7 @@
+
+ #include <linux/aufs_type.h>
+ #include "au_util.h"
++#include "au_nftw.h"
+
+ /* todo: try argz? */
+ static struct name_array {
+@@ -181,6 +182,61 @@ void au_clean_plink(void)
+ #endif
+ }
+
++static int ia_test(ino_t ino)
++{
++ int i;
++ ino_t *p;
++
++ /* todo: hash table */
++ ia.p = ia.o;
++ p = ia.cur;
++ for (i = 0; i < ia.nino; i++)
++ if (*p++ == ino)
++ return 1;
++ return 0;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int ftw_list(const char *fname, const struct stat *st, int flags,
++ struct FTW *ftw)
++{
++ if (!strcmp(fname + ftw->base, AUFS_WH_PLINKDIR))
++ return FTW_SKIP_SUBTREE;
++ if (flags == FTW_D || flags == FTW_DNR)
++ return FTW_CONTINUE;
++
++ if (ia_test(st->st_ino))
++ puts(fname);
++
++ return FTW_CONTINUE;
++}
++
++int ftw_cpup(const char *fname, const struct stat *st, int flags,
++ struct FTW *ftw)
++{
++ int err;
++
++ if (!strcmp(fname + ftw->base, AUFS_WH_PLINKDIR))
++ return FTW_SKIP_SUBTREE;
++ if (flags == FTW_D || flags == FTW_DNR)
++ return FTW_CONTINUE;
++
++ /*
++ * do nothing but update something harmless in order to make it copyup
++ */
++ if (ia_test(st->st_ino)) {
++ Dpri("%s\n", fname);
++ if (!S_ISLNK(st->st_mode))
++ err = chown(fname, -1, -1);
++ else
++ err = lchown(fname, -1, -1);
++ if (err)
++ AuFin("%s", fname);
++ }
++
++ return FTW_CONTINUE;
++}
+ static int do_plink(char *cwd, int cmd, int nbr, union aufs_brinfo *brinfo)
+ {
+ int err, i, l, nopenfd;
+--
+2.11.0
+
diff --git a/testing/aufs-util/0002-add-aufs_type.h-from-linux-header.patch b/testing/aufs-util/0002-add-aufs_type.h-from-linux-header.patch
new file mode 100644
index 0000000000..330df0a5d9
--- /dev/null
+++ b/testing/aufs-util/0002-add-aufs_type.h-from-linux-header.patch
@@ -0,0 +1,441 @@
+From d4ee4592850206342f55ce85fac49f00bdd2128f Mon Sep 17 00:00:00 2001
+From: Natanael Copa <natanael.copa@docker.com>
+Date: Thu, 29 Sep 2016 15:33:53 +0200
+Subject: [PATCH 2/3] add aufs_type.h from linux header
+
+This makes it possible to build the userland utils without having the
+kernelheaders patched with aufs.
+---
+ libau/linux/aufs_type.h | 420 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 420 insertions(+)
+ create mode 100644 libau/linux/aufs_type.h
+
+diff --git a/libau/linux/aufs_type.h b/libau/linux/aufs_type.h
+new file mode 100644
+index 0000000..f7dd59d
+--- /dev/null
++++ b/libau/linux/aufs_type.h
+@@ -0,0 +1,420 @@
++/*
++ * Copyright (C) 2005-2016 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __AUFS_TYPE_H__
++#define __AUFS_TYPE_H__
++
++#define AUFS_NAME "aufs"
++
++#ifdef __KERNEL__
++/*
++ * define it before including all other headers.
++ * sched.h may use pr_* macros before defining "current", so define the
++ * no-current version first, and re-define later.
++ */
++#define pr_fmt(fmt) AUFS_NAME " %s:%d: " fmt, __func__, __LINE__
++#include <linux/sched.h>
++#undef pr_fmt
++#define pr_fmt(fmt) \
++ AUFS_NAME " %s:%d:%.*s[%d]: " fmt, __func__, __LINE__, \
++ (int)sizeof(current->comm), current->comm, current->pid
++#else
++#include <stdint.h>
++#include <sys/types.h>
++#define __user
++#endif /* __KERNEL__ */
++
++#include <linux/limits.h>
++
++#define AUFS_VERSION "4.9-20161219"
++
++/* todo? move this to linux-2.6.19/include/magic.h */
++#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_BRANCH_MAX_127
++typedef int8_t aufs_bindex_t;
++#define AUFS_BRANCH_MAX 127
++#else
++typedef int16_t aufs_bindex_t;
++#ifdef CONFIG_AUFS_BRANCH_MAX_511
++#define AUFS_BRANCH_MAX 511
++#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
++#define AUFS_BRANCH_MAX 1023
++#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
++#define AUFS_BRANCH_MAX 32767
++#endif
++#endif
++
++#ifdef __KERNEL__
++#ifndef AUFS_BRANCH_MAX
++#error unknown CONFIG_AUFS_BRANCH_MAX value
++#endif
++#endif /* __KERNEL__ */
++
++/* ---------------------------------------------------------------------- */
++
++#define AUFS_FSTYPE AUFS_NAME
++
++#define AUFS_ROOT_INO 2
++#define AUFS_FIRST_INO 11
++
++#define AUFS_WH_PFX ".wh."
++#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
++#define AUFS_WH_TMP_LEN 4
++/* a limit for rmdir/rename a dir and copyup */
++#define AUFS_MAX_NAMELEN (NAME_MAX \
++ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\
++ - 1 /* dot */\
++ - AUFS_WH_TMP_LEN) /* hex */
++#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
++#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
++#define AUFS_XINO_DEF_SEC 30 /* seconds */
++#define AUFS_XINO_DEF_TRUNC 45 /* percentage */
++#define AUFS_DIRWH_DEF 3
++#define AUFS_RDCACHE_DEF 10 /* seconds */
++#define AUFS_RDCACHE_MAX 3600 /* seconds */
++#define AUFS_RDBLK_DEF 512 /* bytes */
++#define AUFS_RDHASH_DEF 32
++#define AUFS_WKQ_NAME AUFS_NAME "d"
++#define AUFS_MFS_DEF_SEC 30 /* seconds */
++#define AUFS_MFS_MAX_SEC 3600 /* seconds */
++#define AUFS_FHSM_CACHE_DEF_SEC 30 /* seconds */
++#define AUFS_PLINK_WARN 50 /* number of plinks in a single bucket */
++
++/* pseudo-link maintenace under /proc */
++#define AUFS_PLINK_MAINT_NAME "plink_maint"
++#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME
++#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME
++
++#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
++#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
++
++#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
++#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
++#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
++
++/* doubly whiteouted */
++#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
++#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
++#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
++
++/* branch permissions and attributes */
++#define AUFS_BRPERM_RW "rw"
++#define AUFS_BRPERM_RO "ro"
++#define AUFS_BRPERM_RR "rr"
++#define AUFS_BRATTR_COO_REG "coo_reg"
++#define AUFS_BRATTR_COO_ALL "coo_all"
++#define AUFS_BRATTR_FHSM "fhsm"
++#define AUFS_BRATTR_UNPIN "unpin"
++#define AUFS_BRATTR_ICEX "icex"
++#define AUFS_BRATTR_ICEX_SEC "icexsec"
++#define AUFS_BRATTR_ICEX_SYS "icexsys"
++#define AUFS_BRATTR_ICEX_TR "icextr"
++#define AUFS_BRATTR_ICEX_USR "icexusr"
++#define AUFS_BRATTR_ICEX_OTH "icexoth"
++#define AUFS_BRRATTR_WH "wh"
++#define AUFS_BRWATTR_NLWH "nolwh"
++#define AUFS_BRWATTR_MOO "moo"
++
++#define AuBrPerm_RW 1 /* writable, hardlinkable wh */
++#define AuBrPerm_RO (1 << 1) /* readonly */
++#define AuBrPerm_RR (1 << 2) /* natively readonly */
++#define AuBrPerm_Mask (AuBrPerm_RW | AuBrPerm_RO | AuBrPerm_RR)
++
++#define AuBrAttr_COO_REG (1 << 3) /* copy-up on open */
++#define AuBrAttr_COO_ALL (1 << 4)
++#define AuBrAttr_COO_Mask (AuBrAttr_COO_REG | AuBrAttr_COO_ALL)
++
++#define AuBrAttr_FHSM (1 << 5) /* file-based hsm */
++#define AuBrAttr_UNPIN (1 << 6) /* rename-able top dir of
++ branch. meaningless since
++ linux-3.18-rc1 */
++
++/* ignore error in copying XATTR */
++#define AuBrAttr_ICEX_SEC (1 << 7)
++#define AuBrAttr_ICEX_SYS (1 << 8)
++#define AuBrAttr_ICEX_TR (1 << 9)
++#define AuBrAttr_ICEX_USR (1 << 10)
++#define AuBrAttr_ICEX_OTH (1 << 11)
++#define AuBrAttr_ICEX (AuBrAttr_ICEX_SEC \
++ | AuBrAttr_ICEX_SYS \
++ | AuBrAttr_ICEX_TR \
++ | AuBrAttr_ICEX_USR \
++ | AuBrAttr_ICEX_OTH)
++
++#define AuBrRAttr_WH (1 << 12) /* whiteout-able */
++#define AuBrRAttr_Mask AuBrRAttr_WH
++
++#define AuBrWAttr_NoLinkWH (1 << 13) /* un-hardlinkable whiteouts */
++#define AuBrWAttr_MOO (1 << 14) /* move-up on open */
++#define AuBrWAttr_Mask (AuBrWAttr_NoLinkWH | AuBrWAttr_MOO)
++
++#define AuBrAttr_CMOO_Mask (AuBrAttr_COO_Mask | AuBrWAttr_MOO)
++
++/* #warning test userspace */
++#ifdef __KERNEL__
++#ifndef CONFIG_AUFS_FHSM
++#undef AuBrAttr_FHSM
++#define AuBrAttr_FHSM 0
++#endif
++#ifndef CONFIG_AUFS_XATTR
++#undef AuBrAttr_ICEX
++#define AuBrAttr_ICEX 0
++#undef AuBrAttr_ICEX_SEC
++#define AuBrAttr_ICEX_SEC 0
++#undef AuBrAttr_ICEX_SYS
++#define AuBrAttr_ICEX_SYS 0
++#undef AuBrAttr_ICEX_TR
++#define AuBrAttr_ICEX_TR 0
++#undef AuBrAttr_ICEX_USR
++#define AuBrAttr_ICEX_USR 0
++#undef AuBrAttr_ICEX_OTH
++#define AuBrAttr_ICEX_OTH 0
++#endif
++#endif
++
++/* the longest combination */
++/* AUFS_BRATTR_ICEX and AUFS_BRATTR_ICEX_TR don't affect here */
++#define AuBrPermStrSz sizeof(AUFS_BRPERM_RW \
++ "+" AUFS_BRATTR_COO_REG \
++ "+" AUFS_BRATTR_FHSM \
++ "+" AUFS_BRATTR_UNPIN \
++ "+" AUFS_BRATTR_ICEX_SEC \
++ "+" AUFS_BRATTR_ICEX_SYS \
++ "+" AUFS_BRATTR_ICEX_USR \
++ "+" AUFS_BRATTR_ICEX_OTH \
++ "+" AUFS_BRWATTR_NLWH)
++
++typedef struct {
++ char a[AuBrPermStrSz];
++} au_br_perm_str_t;
++
++static inline int au_br_writable(int brperm)
++{
++ return brperm & AuBrPerm_RW;
++}
++
++static inline int au_br_whable(int brperm)
++{
++ return brperm & (AuBrPerm_RW | AuBrRAttr_WH);
++}
++
++static inline int au_br_wh_linkable(int brperm)
++{
++ return !(brperm & AuBrWAttr_NoLinkWH);
++}
++
++static inline int au_br_cmoo(int brperm)
++{
++ return brperm & AuBrAttr_CMOO_Mask;
++}
++
++static inline int au_br_fhsm(int brperm)
++{
++ return brperm & AuBrAttr_FHSM;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* ioctl */
++enum {
++ /* readdir in userspace */
++ AuCtl_RDU,
++ AuCtl_RDU_INO,
++
++ AuCtl_WBR_FD, /* pathconf wrapper */
++ AuCtl_IBUSY, /* busy inode */
++ AuCtl_MVDOWN, /* move-down */
++ AuCtl_BR, /* info about branches */
++ AuCtl_FHSM_FD /* connection for fhsm */
++};
++
++/* borrowed from linux/include/linux/kernel.h */
++#ifndef ALIGN
++#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
++#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
++#endif
++
++/* borrowed from linux/include/linux/compiler-gcc3.h */
++#ifndef __aligned
++#define __aligned(x) __attribute__((aligned(x)))
++#endif
++
++#ifdef __KERNEL__
++#ifndef __packed
++#define __packed __attribute__((packed))
++#endif
++#endif
++
++struct au_rdu_cookie {
++ uint64_t h_pos;
++ int16_t bindex;
++ uint8_t flags;
++ uint8_t pad;
++ uint32_t generation;
++} __aligned(8);
++
++struct au_rdu_ent {
++ uint64_t ino;
++ int16_t bindex;
++ uint8_t type;
++ uint8_t nlen;
++ uint8_t wh;
++ char name[0];
++} __aligned(8);
++
++static inline int au_rdu_len(int nlen)
++{
++ /* include the terminating NULL */
++ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
++ sizeof(uint64_t));
++}
++
++union au_rdu_ent_ul {
++ struct au_rdu_ent __user *e;
++ uint64_t ul;
++};
++
++enum {
++ AufsCtlRduV_SZ,
++ AufsCtlRduV_End
++};
++
++struct aufs_rdu {
++ /* input */
++ union {
++ uint64_t sz; /* AuCtl_RDU */
++ uint64_t nent; /* AuCtl_RDU_INO */
++ };
++ union au_rdu_ent_ul ent;
++ uint16_t verify[AufsCtlRduV_End];
++
++ /* input/output */
++ uint32_t blk;
++
++ /* output */
++ union au_rdu_ent_ul tail;
++ /* number of entries which were added in a single call */
++ uint64_t rent;
++ uint8_t full;
++ uint8_t shwh;
++
++ struct au_rdu_cookie cookie;
++} __aligned(8);
++
++/* ---------------------------------------------------------------------- */
++
++struct aufs_wbr_fd {
++ uint32_t oflags;
++ int16_t brid;
++} __aligned(8);
++
++/* ---------------------------------------------------------------------- */
++
++struct aufs_ibusy {
++ uint64_t ino, h_ino;
++ int16_t bindex;
++} __aligned(8);
++
++/* ---------------------------------------------------------------------- */
++
++/* error code for move-down */
++/* the actual message strings are implemented in aufs-util.git */
++enum {
++ EAU_MVDOWN_OPAQUE = 1,
++ EAU_MVDOWN_WHITEOUT,
++ EAU_MVDOWN_UPPER,
++ EAU_MVDOWN_BOTTOM,
++ EAU_MVDOWN_NOUPPER,
++ EAU_MVDOWN_NOLOWERBR,
++ EAU_Last
++};
++
++/* flags for move-down */
++#define AUFS_MVDOWN_DMSG 1
++#define AUFS_MVDOWN_OWLOWER (1 << 1) /* overwrite lower */
++#define AUFS_MVDOWN_KUPPER (1 << 2) /* keep upper */
++#define AUFS_MVDOWN_ROLOWER (1 << 3) /* do even if lower is RO */
++#define AUFS_MVDOWN_ROLOWER_R (1 << 4) /* did on lower RO */
++#define AUFS_MVDOWN_ROUPPER (1 << 5) /* do even if upper is RO */
++#define AUFS_MVDOWN_ROUPPER_R (1 << 6) /* did on upper RO */
++#define AUFS_MVDOWN_BRID_UPPER (1 << 7) /* upper brid */
++#define AUFS_MVDOWN_BRID_LOWER (1 << 8) /* lower brid */
++#define AUFS_MVDOWN_FHSM_LOWER (1 << 9) /* find fhsm attr for lower */
++#define AUFS_MVDOWN_STFS (1 << 10) /* req. stfs */
++#define AUFS_MVDOWN_STFS_FAILED (1 << 11) /* output: stfs is unusable */
++#define AUFS_MVDOWN_BOTTOM (1 << 12) /* output: no more lowers */
++
++/* index for move-down */
++enum {
++ AUFS_MVDOWN_UPPER,
++ AUFS_MVDOWN_LOWER,
++ AUFS_MVDOWN_NARRAY
++};
++
++/*
++ * additional info of move-down
++ * number of free blocks and inodes.
++ * subset of struct kstatfs, but smaller and always 64bit.
++ */
++struct aufs_stfs {
++ uint64_t f_blocks;
++ uint64_t f_bavail;
++ uint64_t f_files;
++ uint64_t f_ffree;
++};
++
++struct aufs_stbr {
++ int16_t brid; /* optional input */
++ int16_t bindex; /* output */
++ struct aufs_stfs stfs; /* output when AUFS_MVDOWN_STFS set */
++} __aligned(8);
++
++struct aufs_mvdown {
++ uint32_t flags; /* input/output */
++ struct aufs_stbr stbr[AUFS_MVDOWN_NARRAY]; /* input/output */
++ int8_t au_errno; /* output */
++} __aligned(8);
++
++/* ---------------------------------------------------------------------- */
++
++union aufs_brinfo {
++ /* PATH_MAX may differ between kernel-space and user-space */
++ char _spacer[4096];
++ struct {
++ int16_t id;
++ int perm;
++ char path[0];
++ };
++} __aligned(8);
++
++/* ---------------------------------------------------------------------- */
++
++#define AuCtlType 'A'
++#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
++#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
++#define AUFS_CTL_WBR_FD _IOW(AuCtlType, AuCtl_WBR_FD, \
++ struct aufs_wbr_fd)
++#define AUFS_CTL_IBUSY _IOWR(AuCtlType, AuCtl_IBUSY, struct aufs_ibusy)
++#define AUFS_CTL_MVDOWN _IOWR(AuCtlType, AuCtl_MVDOWN, \
++ struct aufs_mvdown)
++#define AUFS_CTL_BRINFO _IOW(AuCtlType, AuCtl_BR, union aufs_brinfo)
++#define AUFS_CTL_FHSM_FD _IOW(AuCtlType, AuCtl_FHSM_FD, int)
++
++#endif /* __AUFS_TYPE_H__ */
+--
+2.11.0
+
diff --git a/testing/aufs-util/0003-make-install-compatible-with-busybox-install.patch b/testing/aufs-util/0003-make-install-compatible-with-busybox-install.patch
new file mode 100644
index 0000000000..7a734a0d51
--- /dev/null
+++ b/testing/aufs-util/0003-make-install-compatible-with-busybox-install.patch
@@ -0,0 +1,26 @@
+From 98c3dab2a36ae5beaedf0df2a45333bbfeb0e65b Mon Sep 17 00:00:00 2001
+From: Natanael Copa <natanael.copa@docker.com>
+Date: Thu, 29 Sep 2016 15:36:10 +0200
+Subject: [PATCH 3/3] make install compatible with busybox install
+
+busybox install does not support the option -T
+---
+ Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/Makefile b/Makefile
+index ffa4b11..e003832 100644
+--- a/Makefile
++++ b/Makefile
+@@ -159,7 +159,7 @@ install_etc: File = etc_default_aufs
+ install_etc: Tgt = ${DESTDIR}/etc/default/aufs
+ install_etc: ${File}
+ ${INSTALL} -d $(dir ${Tgt})
+- ${Install} -m 644 -T ${File} ${Tgt}
++ ${Install} -m 644 ${File} ${Tgt}
+ install_man5: File = aufs.5
+ install_man5: Tgt = ${DESTDIR}${ManDir}/man5
+ install_man8: File = aumvdown.8
+--
+2.11.0
+
diff --git a/testing/aufs-util/APKBUILD b/testing/aufs-util/APKBUILD
new file mode 100644
index 0000000000..3ce5d890eb
--- /dev/null
+++ b/testing/aufs-util/APKBUILD
@@ -0,0 +1,43 @@
+# Maintainer: Natanael Copa <ncopa@alpinleinux.org>
+pkgname=aufs-util
+pkgver=20161219
+pkgrel=0
+pkgdesc="Utilities for aufs"
+url="http://aufs.sourceforge.net/"
+arch="all"
+license="GPLv2"
+depends=""
+depends_dev=""
+makedepends="$depends_dev"
+install=""
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://dev.alpinelinux.org/archive/aufs-util/aufs-util-$pkgver.tar.gz
+ 0001-implement-glibc-compatible-nftw-if-libc-does-not-pro.patch
+ 0002-add-aufs_type.h-from-linux-header.patch
+ 0003-make-install-compatible-with-busybox-install.patch
+ "
+
+builddir="$srcdir/aufs-utils"
+
+build() {
+ cd "$builddir"
+ make || return 1
+}
+
+package() {
+ cd "$builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="2bed79a7f63a411cd8b1642886276cbc aufs-util-20161219.tar.gz
+7ef61437ca8a9ff6efb72fe1f240fec9 0001-implement-glibc-compatible-nftw-if-libc-does-not-pro.patch
+38333696df22393b6c2883ec9f334c91 0002-add-aufs_type.h-from-linux-header.patch
+1dd84fb82b400bcf53e10a0274aaeee3 0003-make-install-compatible-with-busybox-install.patch"
+sha256sums="b3419356904f2dad5af7938cd16fc860bd0646c4b05d70938d7de7047de11e09 aufs-util-20161219.tar.gz
+4f613e4e00c59a241a1aef3c85a9f4e4d609b8727f00e3ff62c0f7cb2c114034 0001-implement-glibc-compatible-nftw-if-libc-does-not-pro.patch
+8a440f1f129457bf245328ca69bc083333f229df7258fb81f0b2abdc0ac4b5f8 0002-add-aufs_type.h-from-linux-header.patch
+3fbd6320de72b65f6ddbf760bbe1fcdec78ce0a097e4febea9962c72a5d8a10b 0003-make-install-compatible-with-busybox-install.patch"
+sha512sums="345ef1643191a6de35eb3036ce41b0ea0725fd2195d4d15dcc904b449e8159fad9a9e3676f7300d624c39403bf4380c7b2f58f2133f9cbcc82be3ceb4097c877 aufs-util-20161219.tar.gz
+156ffb064b90abb1a035f8fcd9db20c6b0ee6ce7f4d9aa2029549d32d93edce0ac59f9a4ae110e9a0ca088af6e360574055af0f320ee5552648d5abaa8b93211 0001-implement-glibc-compatible-nftw-if-libc-does-not-pro.patch
+4481a470ec029b3af5da5f69023ab62f49a889677c828944a4f3dc0802fe163f5ac5c55576e53f0cd656e92d7e503dd6e874184e22e9ff3651aa81073e6161d6 0002-add-aufs_type.h-from-linux-header.patch
+f9d877de3bb93e4b874476ee956f3bfb26b73ac00eecf52b9a5ffabae19b2085abb7e1647db4a7a459d0b0efc59f1e0282ba1407a1202cf937ed52781ff661fa 0003-make-install-compatible-with-busybox-install.patch"