diff options
author | Rob Austein <sra@hactrn.net> | 2013-04-05 19:10:24 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2013-04-05 19:10:24 +0000 |
commit | f25b1a9a55fd9e61b19d073fe8426cc2aac3c0ef (patch) | |
tree | 4495dac631992d4fe843a42b15b833ec6fb9d12b | |
parent | 0b3938408e8340af9487a02c144661f60ea94931 (diff) |
Whack build environment with a club to get rpki-ca package to start up
properly after install on Ubuntu. Some cleanup still required,
rpki-ca cron stuff isn't done yet, and GUI has not yet been tested
with this, but daemons now start up properly upon install as an Ubuntu
user would expect, which is some kind of progress.
svn path=/trunk/; revision=5283
-rw-r--r-- | Makefile.in | 6 | ||||
-rw-r--r-- | buildtools/debian-skeleton/rpki-ca.install | 2 | ||||
-rw-r--r-- | buildtools/debian-skeleton/rpki-ca.postinst | 46 | ||||
-rw-r--r-- | buildtools/debian-skeleton/rpki-ca.postrm | 48 | ||||
-rw-r--r-- | buildtools/debian-skeleton/rpki-ca.prerm | 48 | ||||
-rw-r--r-- | rpkid/Makefile.in | 62 | ||||
-rw-r--r-- | rpkid/irbe_cli.py | 2 | ||||
-rw-r--r-- | rpkid/irdbd.py | 2 | ||||
-rw-r--r-- | rpkid/portal-gui/scripts/rpki-manage.py | 4 | ||||
-rw-r--r-- | rpkid/portal-gui/scripts/rpkigui-check-expired.py | 2 | ||||
-rw-r--r-- | rpkid/portal-gui/scripts/rpkigui-import-routes.py | 2 | ||||
-rw-r--r-- | rpkid/portal-gui/scripts/rpkigui-rcynic.py | 2 | ||||
-rw-r--r-- | rpkid/pubd.py | 2 | ||||
-rw-r--r-- | rpkid/rootd.py | 2 | ||||
-rw-r--r-- | rpkid/rpki-confgen.py | 2 | ||||
-rw-r--r-- | rpkid/rpki-confgen.xml | 6 | ||||
-rw-r--r-- | rpkid/rpki-sql-backup.py | 2 | ||||
-rw-r--r-- | rpkid/rpki-sql-setup.py | 2 | ||||
-rw-r--r-- | rpkid/rpki-start-servers.py | 2 | ||||
-rw-r--r-- | rpkid/rpkic.py | 2 | ||||
-rw-r--r-- | rpkid/rpkid.py | 2 | ||||
-rw-r--r-- | rpkid/setup.py | 46 |
22 files changed, 236 insertions, 58 deletions
diff --git a/Makefile.in b/Makefile.in index 6b06d12d..508d6973 100644 --- a/Makefile.in +++ b/Makefile.in @@ -11,9 +11,6 @@ test:: all all install clean test distclean deinstall uninstall:: @for i in ${SUBDIRS}; do echo "Making $@ in $$i"; (cd $$i && ${MAKE} $@); done -distclean:: - rm -f Makefile config.log config.status - export: svn export http://subvert-rpki.hactrn.net/ tar czf subvert-rpki.hactrn.net-$$(date +%Y.%m.%d).tar.gz subvert-rpki.hactrn.net @@ -21,3 +18,6 @@ export: distclean clean:: rm -rf build autom4te.cache + +distclean:: + rm -rf Makefile config.log config.status diff --git a/buildtools/debian-skeleton/rpki-ca.install b/buildtools/debian-skeleton/rpki-ca.install index 2a68ddb3..bf926af0 100644 --- a/buildtools/debian-skeleton/rpki-ca.install +++ b/buildtools/debian-skeleton/rpki-ca.install @@ -1,4 +1,4 @@ -etc/rpki.conf.sample +etc/rpki/rpki-confgen.xml etc/rpki/apache.conf usr/lib usr/sbin diff --git a/buildtools/debian-skeleton/rpki-ca.postinst b/buildtools/debian-skeleton/rpki-ca.postinst index 68daa7b7..8b93c2bd 100644 --- a/buildtools/debian-skeleton/rpki-ca.postinst +++ b/buildtools/debian-skeleton/rpki-ca.postinst @@ -20,7 +20,7 @@ setup_rpkid_group() { } setup_apache() { - # edit existing file + # Edit existing file f=/etc/apache2/sites-available/default-ssl conf=/etc/rpki/apache.conf cmd=no @@ -53,15 +53,46 @@ setup_apache() { fi } -setup_django() { - # we can't perform automatic upgrade when rpki.conf isn't present - if test -f /etc/rpki.conf +setup_rpki_conf() { + # Update /etc/rpki.conf.sample for this system, and copy it to + # /etc/rpki.conf if no configuration file exists yet. + + # We don't (yet) have the ability to merge in settings from an + # existing rpki.conf, so we generate a new secret_key and a new + # SQL password every time, but that's harmless so long as we're + # careful not to overwrite an existing configuration. + + mysql_passwd=`python -c 'import random, string; print "".join(random.choice(string.uppercase + string.lowercase + string.digits) for _ in xrange(16))'` + secret_key=`python -c 'import random, string; print "".join(random.choice(string.uppercase + string.lowercase + string.digits) for _ in xrange(50))'` + + rpki-confgen --read-xml /etc/rpki/rpki-confgen.xml \ + --autoconf \ + --set myrpki::handle=`hostname -f | sed 's/[.]/_/g'` \ + --set myrpki::rpkid_server_host=`hostname -f` \ + --set myrpki::pubd_server_host=`hostname -f` \ + --set myrpki::shared_sql_password="$mysql_passwd" \ + --set web_portal::secret-key="$secret_key" \ + --write-conf /etc/rpki.conf.sample + + if test ! -f /etc/rpki.conf then - rpki-manage syncdb - rpki-manage migrate app + cp -p /etc/rpki.conf.sample /etc/rpki.conf fi } +setup_mysql() { + rpki-sql-setup --missing_only --mysql_defaults /etc/mysql/debian.cnf +} + +setup_bpki() { + rpkic initialize_server_bpki +} + +setup_django() { + rpki-manage syncdb --noinput + rpki-manage migrate app +} + setup_cron() { t=$(hexdump -n 1 -e '"%u"' /dev/urandom) && echo "$(($t % 60)) */2 * * * nobody /usr/share/rpki/routeviews.sh" > /etc/cron.d/rpkigui-routeviews chmod 644 /etc/cron.d/rpkigui-routeviews @@ -86,6 +117,9 @@ case "$1" in setup_rpkid_group setup_rpkid_user setup_apache + setup_rpki_conf + setup_mysql + setup_bpki setup_django setup_cron ;; diff --git a/buildtools/debian-skeleton/rpki-ca.postrm b/buildtools/debian-skeleton/rpki-ca.postrm new file mode 100644 index 00000000..14c14dab --- /dev/null +++ b/buildtools/debian-skeleton/rpki-ca.postrm @@ -0,0 +1,48 @@ +#!/bin/sh +# postrm script for #PACKAGE# +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * <postrm> `remove' +# * <postrm> `purge' +# * <old-postrm> `upgrade' <new-version> +# * <new-postrm> `failed-upgrade' <old-version> +# * <new-postrm> `abort-install' +# * <new-postrm> `abort-install' <old-version> +# * <new-postrm> `abort-upgrade' <old-version> +# * <disappearer's-postrm> `disappear' <overwriter> +# <overwriter-version> +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + + purge) + + # If we had an rpki-purge-sql script, we might call it here to + # whack the SQL databases before we whack the configuration + # file that tells us what their names and passwords are. Then + # again, we might not. + + rm -f /etc/rpki.conf /etc/rpki.conf.sample + ;; + + remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) + ;; + + *) + echo "postrm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/buildtools/debian-skeleton/rpki-ca.prerm b/buildtools/debian-skeleton/rpki-ca.prerm new file mode 100644 index 00000000..5b83de2f --- /dev/null +++ b/buildtools/debian-skeleton/rpki-ca.prerm @@ -0,0 +1,48 @@ +#!/bin/sh +# prerm script for rpki-ca +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * <prerm> `remove' +# * <old-prerm> `upgrade' <new-version> +# * <new-prerm> `failed-upgrade' <old-version> +# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version> +# * <deconfigured's-prerm> `deconfigure' `in-favour' +# <package-being-installed> <version> `removing' +# <conflicting-package> <version> +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + remove) + rm -f /usr/share/rpki/ca.cer + rm -f /usr/share/rpki/irbe.cer + rm -f /usr/share/rpki/irdbd.cer + rm -f /usr/share/rpki/pubd.cer + rm -f /usr/share/rpki/pubd.key + rm -f /usr/share/rpki/rpkid.cer + rm -f /usr/share/rpki/rpkid.key + ;; + + upgrade|deconfigure) + ;; + + failed-upgrade) + ;; + + *) + echo "prerm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/rpkid/Makefile.in b/rpkid/Makefile.in index 35b26617..5c697f91 100644 --- a/rpkid/Makefile.in +++ b/rpkid/Makefile.in @@ -56,7 +56,7 @@ POW_SO = rpki/POW/_POW.so SCRIPTS = \ rpki-sql-backup rpki-sql-setup rpki-start-servers irbe_cli irdbd \ - pubd rootd rpkic rpkid \ + pubd rootd rpkic rpkid rpki-confgen \ portal-gui/scripts/rpkigui-import-routes \ portal-gui/scripts/rpkigui-check-expired \ portal-gui/scripts/rpkigui-rcynic \ @@ -71,11 +71,11 @@ BUILD_SCRIPTS = \ DATA_FILES = portal-gui/routeviews.sh # these files get put in ${sysconfdir}/rpki -CONF_FILES = portal-gui/apache.conf +CONF_FILES = portal-gui/apache.conf rpki-confgen.xml all:: ${POW_SO} rpki/relaxng.py myrpki.rng rpki/sql_schemas.py ${SCRIPTS} ${BUILD_SCRIPTS} -${POW_SO}: ext/POW.c setup.py +${POW_SO}: ext/POW.c setup.py setup_autoconf.py ${SETUP_PY} build_ext --inplace clean:: @@ -220,59 +220,61 @@ install:: clean:: rm -f examples/rpki.conf -# Scripts +# Scripts. This whole business of copying scripts is a holdover from +# a more complex build process which we haven't quite finished +# cleaning up yet. In theory, eventually this will all be handled by +# setup.py without any need for copying anything here. -COMPILE_PYTHON = \ - rm -f $@; \ - ${PYTHON} ${abs_top_srcdir}/buildtools/make-python-executable.py <$? >$@; \ - chmod 555 $@ +COPY_SCRIPT = cp -pf $? $@; chmod 555 $@ rpki-sql-backup: rpki-sql-backup.py - ${COMPILE_PYTHON} + ${COPY_SCRIPT} rpki-sql-setup: rpki-sql-setup.py - ${COMPILE_PYTHON} + ${COPY_SCRIPT} rpki-start-servers: rpki-start-servers.py - ${COMPILE_PYTHON} + ${COPY_SCRIPT} irbe_cli: irbe_cli.py - ${COMPILE_PYTHON} + ${COPY_SCRIPT} irdbd: irdbd.py - ${COMPILE_PYTHON} + ${COPY_SCRIPT} pubd: pubd.py - ${COMPILE_PYTHON} + ${COPY_SCRIPT} rootd: rootd.py - ${COMPILE_PYTHON} + ${COPY_SCRIPT} rpkic: rpkic.py - ${COMPILE_PYTHON} + ${COPY_SCRIPT} rpkid: rpkid.py - ${COMPILE_PYTHON} + ${COPY_SCRIPT} + +rpki-confgen: rpki-confgen.py + ${COPY_SCRIPT} # These are here for legacy reasons, but no longer required. The problem is # that anyone with an existing copy of the repository will already have # previously built files by these names, so I can't rename them in the # repository, or svn will abort when the user tries to update. portal-gui/scripts/rpkigui-rcynic: portal-gui/scripts/rpkigui-rcynic.py - ${COMPILE_PYTHON} + ${COPY_SCRIPT} portal-gui/scripts/rpkigui-import-routes: portal-gui/scripts/rpkigui-import-routes.py - ${COMPILE_PYTHON} + ${COPY_SCRIPT} portal-gui/scripts/rpkigui-check-expired: portal-gui/scripts/rpkigui-check-expired.py - ${COMPILE_PYTHON} + ${COPY_SCRIPT} portal-gui/rpki.wsgi: ${srcdir}/portal-gui/rpki.wsgi.in - cp $? $@ + ${COPY_SCRIPT} portal-gui/scripts/rpki-manage: ${srcdir}/portal-gui/scripts/rpki-manage.py - cp $? $@ - chmod 755 $@ + ${COPY_SCRIPT} rpki/autoconf.py: Makefile @echo 'Generating $@'; \ @@ -282,5 +284,17 @@ rpki/autoconf.py: Makefile echo 'localstatedir = "${localstatedir}"'; \ echo 'sbindir = "${sbindir}"'; \ echo 'sharedstatedir = "${sharedstatedir}"'; \ - echo 'sysconfdir = "${sysconfdir}"' \ + echo 'sysconfdir = "${sysconfdir}"'; \ + echo 'libexecdir = "${libexecdir}"'; \ + ) > $@ + +setup_autoconf.py: rpki/autoconf.py + @echo 'Generating $@'; \ + (cat rpki/autoconf.py; \ + echo 'CFLAGS = """${CFLAGS}"""'; \ + echo 'LDFLAGS = """${LDFLAGS}"""'; \ + echo 'LIBS = """${LIBS}"""'; \ ) > $@ + +clean:: + rm -f setup_autoconf.py setup_autoconf.pyc diff --git a/rpkid/irbe_cli.py b/rpkid/irbe_cli.py index 9d691da4..f8f87990 100644 --- a/rpkid/irbe_cli.py +++ b/rpkid/irbe_cli.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + """ Command line IR back-end control program for rpkid and pubd. diff --git a/rpkid/irdbd.py b/rpkid/irdbd.py index ef99048e..63370ab5 100644 --- a/rpkid/irdbd.py +++ b/rpkid/irdbd.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + """ $Id$ diff --git a/rpkid/portal-gui/scripts/rpki-manage.py b/rpkid/portal-gui/scripts/rpki-manage.py index 7bf84709..0d581ce9 100644 --- a/rpkid/portal-gui/scripts/rpki-manage.py +++ b/rpkid/portal-gui/scripts/rpki-manage.py @@ -4,8 +4,8 @@ import os from django.core.management import execute_from_command_line # django-admin seems to have problems creating the superuser account when -# $LANG is unset -if not 'LANG' in os.environ: +# $LANG is unset or is set to something totally incompatible with UTF-8. +if os.environ.get('LANG') in (None, "", "C"): os.environ['LANG'] = 'en_US.UTF-8' os.environ['DJANGO_SETTINGS_MODULE'] = 'rpki.gui.default_settings' diff --git a/rpkid/portal-gui/scripts/rpkigui-check-expired.py b/rpkid/portal-gui/scripts/rpkigui-check-expired.py index 90c492ff..eb0c7fbb 100644 --- a/rpkid/portal-gui/scripts/rpkigui-check-expired.py +++ b/rpkid/portal-gui/scripts/rpkigui-check-expired.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + # Copyright (C) 2012 SPARTA, Inc. a Parsons Company # # Permission to use, copy, modify, and distribute this software for any diff --git a/rpkid/portal-gui/scripts/rpkigui-import-routes.py b/rpkid/portal-gui/scripts/rpkigui-import-routes.py index 776a16e2..fa3ff3e9 100644 --- a/rpkid/portal-gui/scripts/rpkigui-import-routes.py +++ b/rpkid/portal-gui/scripts/rpkigui-import-routes.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + # Copyright (C) 2012, 2013 SPARTA, Inc. a Parsons Company # # Permission to use, copy, modify, and distribute this software for any diff --git a/rpkid/portal-gui/scripts/rpkigui-rcynic.py b/rpkid/portal-gui/scripts/rpkigui-rcynic.py index 4f18c5bb..c8f1b994 100644 --- a/rpkid/portal-gui/scripts/rpkigui-rcynic.py +++ b/rpkid/portal-gui/scripts/rpkigui-rcynic.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + # Copyright (C) 2011 SPARTA, Inc. dba Cobham # Copyright (C) 2012, 2013 SPARTA, Inc. a Parsons Company # diff --git a/rpkid/pubd.py b/rpkid/pubd.py index c806d124..8445b6e1 100644 --- a/rpkid/pubd.py +++ b/rpkid/pubd.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + """ $Id$ diff --git a/rpkid/rootd.py b/rpkid/rootd.py index dd6adb41..8e98bd89 100644 --- a/rpkid/rootd.py +++ b/rpkid/rootd.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + """ $Id$ diff --git a/rpkid/rpki-confgen.py b/rpkid/rpki-confgen.py index a2d4fbd1..9913a1e5 100644 --- a/rpkid/rpki-confgen.py +++ b/rpkid/rpki-confgen.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + import sys import getopt import textwrap diff --git a/rpkid/rpki-confgen.xml b/rpkid/rpki-confgen.xml index b92b4ae4..055ea813 100644 --- a/rpkid/rpki-confgen.xml +++ b/rpkid/rpki-confgen.xml @@ -25,7 +25,7 @@ </option> <option name = "run_rpkid" - value = "True"> + value = "yes"> <doc> Whether you want to run your own copy of rpkid (and irdbd). You want this on unless somebody else is hosting rpkid service for you. @@ -64,7 +64,7 @@ </option> <option name = "run_pubd" - value = "False"> + value = "yes"> <doc> Whether you want to run your own copy of pubd. In general, it's best to use your parent's pubd if you can, to reduce the overall @@ -99,7 +99,7 @@ </option> <option name = "run_rootd" - value = "False"> + value = "no"> <doc> Whether you want to run your very own copy of rootd. Don't enable this unless you really know what you're doing. diff --git a/rpkid/rpki-sql-backup.py b/rpkid/rpki-sql-backup.py index ea11d957..561aa4e5 100644 --- a/rpkid/rpki-sql-backup.py +++ b/rpkid/rpki-sql-backup.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + """ Back up data from SQL databases, looking at config file to figure out which databases and what credentials to use with them. diff --git a/rpkid/rpki-sql-setup.py b/rpkid/rpki-sql-setup.py index 3ca42b04..01de0822 100644 --- a/rpkid/rpki-sql-setup.py +++ b/rpkid/rpki-sql-setup.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + """ Automated setup of all the pesky SQL stuff we need. Prompts for MySQL root password, pulls other information from rpki.conf. diff --git a/rpkid/rpki-start-servers.py b/rpkid/rpki-start-servers.py index 722f51e6..3babfd1c 100644 --- a/rpkid/rpki-start-servers.py +++ b/rpkid/rpki-start-servers.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + """ Start servers, logging to files, looking at config file to figure out which servers the user wants started. diff --git a/rpkid/rpkic.py b/rpkid/rpkic.py index 6ef3a67b..0dd1c122 100644 --- a/rpkid/rpkic.py +++ b/rpkid/rpkic.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + """ $Id$ diff --git a/rpkid/rpkid.py b/rpkid/rpkid.py index 181fabf9..4f52040e 100644 --- a/rpkid/rpkid.py +++ b/rpkid/rpkid.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + """ $Id$ diff --git a/rpkid/setup.py b/rpkid/setup.py index eded0251..c4d0fb60 100644 --- a/rpkid/setup.py +++ b/rpkid/setup.py @@ -20,19 +20,29 @@ import os # We can't build POW without these settings, but allow them to be null # so that things like "python setup.py --help" will work. -ac_cflags = os.getenv("AC_CFLAGS", "").split() -ac_ldflags = os.getenv("AC_LDFLAGS", "").split() -ac_libs = os.getenv("AC_LIBS", "").split() -ac_scripts = os.getenv("AC_SCRIPTS", "").split() +ac_scripts = os.getenv("AC_SCRIPTS", "").split() ac_aux_scripts = os.getenv("AC_AUX_SCRIPTS", "").split() ac_data_files = os.getenv("AC_DATA_FILES", "").split() ac_conf_files = os.getenv("AC_CONF_FILES", "").split() -ac_sbindir = os.getenv("AC_SBINDIR", "").strip() -ac_abs_builddir = os.getenv("AC_ABS_BUILDDIR", "").strip() -ac_libexecdir = os.getenv("AC_LIBEXECDIR", "").strip() -ac_datarootdir = os.getenv("AC_DATAROOTDIR", "").strip() -ac_sysconfdir = os.getenv("AC_SYSCONFDIR", "").strip() +try: + import setup_autoconf + ac_cflags = setup_autoconf.CFLAGS.split() + ac_ldflags = setup_autoconf.LDFLAGS.split() + ac_libs = setup_autoconf.LIBS.split() + ac_sbindir = setup_autoconf.sbindir + ac_libexecdir = setup_autoconf.libexecdir + ac_datarootdir = os.path.join(setup_autoconf.datarootdir, "rpki") + ac_sysconfdir = os.path.join(setup_autoconf.sysconfdir, "rpki") + +except ImportError: + ac_cflags = () + ac_ldflags = () + ac_libs = () + ac_sbindir = None + ac_libexecdir = None + ac_datarootdir = None + ac_sysconfdir = None # Non-standard extension build specification: we need to force # whatever build options our top-level ./configure selected, and we @@ -52,21 +62,19 @@ pow = Extension("rpki.POW._POW", ["ext/POW.c"], # installed files. # # bdist_rpm seems to get confused by relative names for scripts, so we -# have to prefix source names here with the build directory name. +# have to prefix source names here with the build directory name. Well, +# if we care about bdist_rpm, which it now looks like we don't, but +# leave it alone for the moment. data_files = [] if ac_sbindir and ac_scripts: - data_files.append((ac_sbindir, - ["%s/%s" % (ac_abs_builddir, f) for f in ac_scripts])) + data_files.append((ac_sbindir, [os.path.abspath(f) for f in ac_scripts])) if ac_libexecdir and ac_aux_scripts: - data_files.append((ac_libexecdir, - ["%s/%s" % (ac_abs_builddir, f) for f in ac_aux_scripts])) + data_files.append((ac_libexecdir, [os.path.abspath(f) for f in ac_aux_scripts])) if ac_datarootdir and ac_data_files: - data_files.append((ac_datarootdir, - ["%s/%s" % (ac_abs_builddir, f) for f in ac_data_files])) + data_files.append((ac_datarootdir, [os.path.abspath(f) for f in ac_data_files])) if ac_sysconfdir and ac_conf_files: - data_files.append((ac_sysconfdir, - ["%s/%s" % (ac_abs_builddir, f) for f in ac_conf_files])) + data_files.append((ac_sysconfdir, [os.path.abspath(f) for f in ac_conf_files])) if not data_files: data_files = None @@ -85,4 +93,4 @@ setup(name = "rpkitoolkit", 'templatetags/*.py'], 'rpki.gui.cacheview': ['templates/*/*.html'] }, - data_files = data_files) + data_files = data_files) |