This patch adds a 'dev-template' configuration options which points to a
directory with a preconfigured /dev directory. This makes it possible to
use mock in environments where 'mknod(2)' operations are prohibited (e.g.
in vservers).
Usually, this directory is a mounted read-only and e.g. a cramfs. The
'create-template.sh' script will create such a cramfs image which must be
added to the host's /etc/fstab e.g. as
| /usr/share/mock/mock-dev.ramfs /usr/share/mock/dev-template cramfs dev
and added to mock configuration as
| config_opts['dev-template'] = '/usr/share/mock/dev-template'
The changes in the spec file are suggestions only and the cramfs image
can not be created during the normal build because it requires superuser
capabilities.
Signed-off-by: Enrico Scholz <enrico.scholz(a)informatik.tu-chemnitz.de>
---
Makefile | 2 ++
create-template.sh | 29 ++++++++++++++++++++++
mock-dev.ramfs | Bin
mock.py | 69 +++++++++++++++++++++++++++++-----------------------
mock.spec | 16 ++++++++++++
5 files changed, 85 insertions(+), 31 deletions(-)
diff --git a/Makefile b/Makefile
index bee4ad4..a2a5d0b 100644
--- a/Makefile
+++ b/Makefile
@@ -21,6 +21,8 @@ subdirs:
install:
install -D mock.py $(DESTDIR)/usr/libexec/mock.py
install -D mock-yum $(DESTDIR)/usr/libexec/mock-yum
+ install -D -m644 mock-dev.ramfs $(DESTDIR)/usr/share/mock/mock-dev.ramfs
+ install -d -m755 $(DESTDIR)/usr/share/mock/dev-template
mkdir -p $(DESTDIR)/var/lib/mock
for d in $(SUBDIRS); do make DESTDIR=`cd $(DESTDIR); pwd` -C $$d install; [ $$? = 0 ] || exit 1; done
diff --git a/create-template.sh b/create-template.sh
new file mode 100755
index 0000000..75e2529
--- /dev/null
+++ b/create-template.sh
@@ -0,0 +1,29 @@
+#! /bin/bash
+
+MKNOD=mknod
+MKCRAMFS=/sbin/mkfs.cramfs
+
+set -e
+
+d=$(mktemp -t -d mockdev.XXXXXX)
+trap "rm -rf $d" EXIT
+
+dev=$d/dev
+mkdir -p $dev
+
+$MKNOD -m666 $dev/null c 1 3
+$MKNOD -m644 $dev/urandom c 1 9
+$MKNOD -m644 $dev/random c 1 8
+$MKNOD -m666 $dev/full c 1 7
+$MKNOD -m666 $dev/ptmx c 5 2
+$MKNOD -m666 $dev/tty c 5 0
+$MKNOD -m666 $dev/zero c 1 5
+
+ln -s /proc/self/fd $dev/fd
+ln -s /proc/self/fd/0 $dev/stdin
+ln -s /proc/self/fd/1 $dev/stdout
+ln -s /proc/self/fd/2 $dev/stderr
+
+mkdir $dev/pts
+
+$MKCRAMFS $dev "$1"
diff --git a/mock-dev.ramfs b/mock-dev.ramfs
new file mode 100644
index 0000000..03851ca
Binary files /dev/null and b/mock-dev.ramfs differ
diff --git a/mock.py b/mock.py
index b06156c..3762324 100644
--- a/mock.py
+++ b/mock.py
@@ -497,6 +497,10 @@ class Root:
# mount /proc
self._mount('proc', 'proc', 'proc')
+ # mount /dev
+ if self.config.get('dev-template'):
+ self._mount('none --bind -o ro', self.config['dev-template'], 'dev')
+
# mount /dev/pts
self._mount('devpts', 'dev/pts', 'dev/pts')
@@ -536,7 +540,38 @@ class Root:
# poof, no more file
if os.path.exists(mf):
os.unlink(mf)
+
+ def __mknodall(self):
+ # we need stuff
+ devices = [('null', 'c', '1', '3', '666'),
+ ('urandom', 'c', '1', '9', '644'),
+ ('random', 'c', '1', '9', '644'),
+ ('full', 'c', '1', '7', '666'),
+ ('ptmx', 'c', '5', '2', '666'),
+ ('tty', 'c', '5', '0', '666'),
+ ('zero', 'c', '1', '5', '666')]
+
+ for (dev, devtype, major, minor, perm) in devices:
+ devpath = os.path.join(self.rootdir, 'dev', dev)
+ cmd = '%s %s -m %s %s %s %s' % (self.config['mknod'],
+ devpath, perm, devtype, major, minor)
+ if not os.path.exists(devpath):
+ (retval, output) = self.do_elevated(cmd)
+ if retval != 0:
+ raise RootError, "could not mknod error was: %s" % output
+
+ # link fd to ../proc/self/fd
+ devpath = os.path.join(self.rootdir, 'dev/fd')
+ if not os.path.exists(devpath):
+ os.symlink('../proc/self/fd', devpath)
+ fd = 0
+ for item in ('stdin', 'stdout', 'stderr'):
+ devpath = os.path.join(self.rootdir, 'dev', item)
+ if not os.path.exists(devpath):
+ fdpath = os.path.join('../proc/self/fd', str(fd))
+ os.symlink(fdpath, devpath)
+ fd += 1
def do(self, command):
"""execute given command outside of chroot"""
@@ -679,39 +714,11 @@ class Root:
os.path.join(self.rootdir, 'var/tmp'),
os.path.join(self.rootdir, 'etc/yum.repos.d')]:
self._ensure_dir(item)
-
- self._mountall()
- # we need stuff
- devices = [('null', 'c', '1', '3', '666'),
- ('urandom', 'c', '1', '9', '644'),
- ('random', 'c', '1', '9', '644'),
- ('full', 'c', '1', '7', '666'),
- ('ptmx', 'c', '5', '2', '666'),
- ('tty', 'c', '5', '0', '666'),
- ('zero', 'c', '1', '5', '666')]
-
- for (dev, devtype, major, minor, perm) in devices:
- devpath = os.path.join(self.rootdir, 'dev', dev)
- cmd = '%s %s -m %s %s %s %s' % (self.config['mknod'],
- devpath, perm, devtype, major, minor)
- if not os.path.exists(devpath):
- (retval, output) = self.do_elevated(cmd)
- if retval != 0:
- raise RootError, "could not mknod error was: %s" % output
+ self._mountall()
- # link fd to ../proc/self/fd
- devpath = os.path.join(self.rootdir, 'dev/fd')
- if not os.path.exists(devpath):
- os.symlink('../proc/self/fd', devpath)
-
- fd = 0
- for item in ('stdin', 'stdout', 'stderr'):
- devpath = os.path.join(self.rootdir, 'dev', item)
- if not os.path.exists(devpath):
- fdpath = os.path.join('../proc/self/fd', str(fd))
- os.symlink(fdpath, devpath)
- fd += 1
+ if not self.config.get('dev-template'):
+ self.__mknodall()
for item in [os.path.join(self.rootdir, 'etc', 'mtab'),
os.path.join(self.rootdir, 'etc', 'fstab'),
diff --git a/mock.spec b/mock.spec
index db59881..309e290 100644
--- a/mock.spec
+++ b/mock.spec
@@ -33,6 +33,7 @@ if [ -f fedora-%{fedora}-%{_target_cpu}-core.cfg ]; then
fi
%endif
+
# if we haven't created a default link yet, try to do so as devel
if [ ! -f default.cfg ]; then
if [ -f fedora-development-%{_target_cpu}-core.cfg ]; then
@@ -54,6 +55,12 @@ if [ $1 -eq 1 ]; then
groupadd -r mock >/dev/null 2>&1 || :
fi
+%post
+mkdir -p -m0755 %_datadir/mock/dev-template
+
+%preun
+test $1 != 0 || rmdir %_datadir/mock/dev-template || :
+
%files
%defattr(-, root, root)
%doc README ChangeLog buildsys-build.spec
@@ -65,6 +72,15 @@ fi
%attr(02775, root, mock) %dir /var/lib/mock
%{_libdir}/libselinux-mock.so
+# Do not ship the dev-template directory; it might be mounted during
+# upgrades which will cpio errors. Adding it to %%_netsharedpath is a
+# solution but requires manual editing of /etc/rpm/macros.
+#
+# Hence, create and remove this directory in scriptlets
+%dir %_datadir/mock
+%dir %_datadir/mock/*.ramfs
+%ghost %dir %_datadir/mock/dev-template
+
%changelog
* Mon Jan 8 2007 Clark Williams <williams(a)redhat.com>
- Added Josh Boyer's EPEL config files