diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6b0f7eb --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +# Generated dependency files. +.deps* + +# Compiled objects/libs. +*.[oa] + +# Our project programs. +/tmpfiles +/tmpfiles_test diff --git a/.travis.yml b/.travis.yml index 4c08010..7f66e2e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ compiler: - gcc - clang +dist: xenial os: - linux diff --git a/Makefile b/Makefile index 778cbc2..5f9ba24 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,44 @@ +# Disable implicit rules. We'll specify everything. +MAKEFLAGS += -r +.SUFFIXES: + binprogs = tmpfiles bindir = /bin binmode = 0755 install = install +# Clear the default source file search path. We'll add subdirs below. +VPATH := + +# This has to come first to define the default target. all: +# The build machinery. +include ./build.mk + +# Include generated dependencies. +-include ./.deps.c +-include ./.deps.cc +.deps.c: + $(DRIVER_CC) $(CPPFLAGS) -MM $^ >$@ +.deps.cc: + $(DRIVER_CXX) $(CPPFLAGS) -MM $^ >$@ + +# The main program. +VPATH += src +include ./src/module.mk + +# The tests. +VPATH += test +include ./test/module.mk +check: tmpfiles_test + ./tmpfiles_test + install: $(install) -d $(DESTDIR)$(bindir) - $(install) -m $(binmode) $(binprogs) $(DESTDIR)$(bindir) + $(install) -m $(binmode) $(binprogs) $(binprogs).sh $(DESTDIR)$(bindir) + +clean: + rm -f tmpfiles tmpfiles_test *.o -.PHONY: all install +.PHONY: all check clean install diff --git a/build.mk b/build.mk new file mode 100644 index 0000000..f2c3b60 --- /dev/null +++ b/build.mk @@ -0,0 +1,21 @@ +# Compile flags for building the project. +DEFAULT_FLAGS = -O2 -g +COMMON_FLAGS = -Wall -fvisibility=hidden -fdiagnostics-color=auto +CFLAGS ?= $(DEFAULT_FLAGS) +CFLAGS += $(COMMON_FLAGS) -std=c11 +CXXFLAGS ?= $(DEFAULT_FLAGS) +CXXFLAGS += $(COMMON_FLAGS) -std=c++14 +CPPFLAGS += -Isrc -D_ISOC11_SOURCE -D_POSIX_C_SOURCE=201401L +LDFLAGS += -L. + +# Generic compiler invocation settings. +DRIVER_CC = $(CC) $(CFLAGS) +DRIVER_CXX = $(CXX) $(CXXFLAGS) +COMPILE_CC = $(DRIVER_CC) $(CPPFLAGS) -c -o $@ $< +COMPILE_CXX = $(DRIVER_CXX) $(CPPFLAGS) -c -o $@ $< +LINK_CC = $(DRIVER_CC) $(LDFLAGS) $(LDFLAGS-$@) -o $@ $^ $(LDLIBS) $(LDLIBS-$@) +LINK_CXX = $(DRIVER_CXX) $(LDFLAGS) $(LDFLAGS-$@) -o $@ $^ $(LDLIBS) $(LDLIBS-$@) + +# General pattern rules. +%.o: %.c ; $(COMPILE_CC) +%.o: %.cc ; $(COMPILE_CXX) diff --git a/ci/travis.sh b/ci/travis.sh index c319bdd..11bc3ea 100755 --- a/ci/travis.sh +++ b/ci/travis.sh @@ -40,6 +40,9 @@ m() { main() { m + # The CI doesn't include a usable gtest install, so bootstrap it. + m gtest + m check m install DESTDIR="${PWD}/destdir" } main "$@" diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..271ec50 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,3 @@ +# Helper for developers. +all: ; $(MAKE) -C .. all +%: ; $(MAKE) -C .. $@ diff --git a/src/cli.c b/src/cli.c new file mode 100644 index 0000000..16d0fbd --- /dev/null +++ b/src/cli.c @@ -0,0 +1,166 @@ +/* + * Copyright 2017-2019 Gentoo Foundation + * Copyright 2017-2019 The Chromium OS Authors + * Released under the 2-clause BSD license. + */ + +#include "tmpfiles.h" + +bool verbose = false; +bool dryrun = false; +bool do_default = true; +bool do_boot = false; +bool do_clean = false; +bool do_create = false; +bool do_remove = false; + +ordered_set_t cli_files = {}; +ordered_set_t rules_prefix = {}; +ordered_set_t rules_exclude_prefix = {}; + +/* Order here doesn't matter. All must have a value of 256+ though. */ +typedef enum { + OPT_BOOT = 0x100, + OPT_CLEAN, + OPT_CREATE, + OPT_DRY_RUN, + OPT_EXCLUDE_PREFIX, + OPT_PREFIX, + OPT_REMOVE, + OPT_VERBOSE, + OPT_VERSION, +} options; + +/* + * Order here reflects output order in --help output, so things are loosely + * grouped by relationship. Otherwise, it doesn't matter. + */ +#define PARSE_FLAGS "h" +#define a_argument required_argument +static struct option const opts[] = { + {"boot", no_argument, NULL, OPT_BOOT}, + {"create", no_argument, NULL, OPT_CREATE}, + {"clean", no_argument, NULL, OPT_CLEAN}, + {"remove", no_argument, NULL, OPT_REMOVE}, + {"prefix", a_argument, NULL, OPT_PREFIX}, + {"exclude-prefix", a_argument, NULL, OPT_EXCLUDE_PREFIX}, + {"dry-run", no_argument, NULL, OPT_DRY_RUN}, + {"dryrun", no_argument, NULL, OPT_DRY_RUN}, + {"verbose", no_argument, NULL, OPT_VERBOSE}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, OPT_VERSION}, + {NULL, no_argument, NULL, 0x0} +}; + +/* Order here must match opts array above. */ +static const char * const opts_help[] = { + "Process all boot entries (have a ! in the command)", + "Process all f, F, w, d, D, v, p, L, c, b, m and z, Z, t, T, a, A commands", + "All paths with an age setting will be cleaned", + "Remove directories marked with D or R, and paths marked with r or R", + "Only process entries that match the specified paths", + "Ignore all entries that match the specified paths", + "Don't make any changes; just show what would be done", + "Alias to --dry-run", + "Run in verbose mode", + "Print this help and exit", + "Print version and exit", + NULL, +}; + +attribute_noreturn +void usage(int status) +{ + /* Increase this if a new --longer-option is added. */ + const int padding = 25; + size_t i; + int ret; + FILE *fp = status == 0 ? stdout : stderr; + + fprintf(fp, + "Usage: tmpfiles [options] [files]\n" + "\n" + "If [files] are specified, only those will be processed.\n" + "Basenames are searched, while non-basenames are read directly.\n" + "\n" + "Options:\n" + ); + + for (i = 0; opts[i].name; ++i) { + if (opts[i].val > '~' || opts[i].val < ' ') + fprintf(fp, " "); + else + fprintf(fp, " -%c, ", opts[i].val); + + ret = fprintf(fp, "--%s ", opts[i].name); + fprintf(fp, "%-*s", padding - ret, + opts[i].has_arg == no_argument ? "" : ""); + fprintf(fp, " %s\n", opts_help[i]); + } + + exit(status); +} + +#ifndef VERSION +#define VERSION "git" +#endif +attribute_noreturn +static void version(void) +{ + printf("opentmpfiles %s\n", VERSION); + exit(0); +} + +void parseargs(int argc, char *argv[]) +{ + int i; + + ordered_set_init(&cli_files); + ordered_set_init(&rules_prefix); + ordered_set_init(&rules_exclude_prefix); + + while ((i = getopt_long(argc, argv, PARSE_FLAGS, opts, NULL)) != -1) { + switch (i) { + case OPT_BOOT: + do_default = false; + do_boot = true; + break; + case OPT_CLEAN: + do_default = false; + do_clean = true; + break; + case OPT_CREATE: + do_default = false; + do_create = true; + break; + case OPT_REMOVE: + do_default = false; + do_remove = true; + break; + + case OPT_EXCLUDE_PREFIX: + ordered_set_add(&rules_exclude_prefix, optarg); + break; + case OPT_PREFIX: + ordered_set_add(&rules_prefix, optarg); + break; + + case OPT_DRY_RUN: + dryrun = true; + break; + case OPT_VERBOSE: + verbose = true; + break; + case OPT_VERSION: + version(); + break; + case 'h': + usage(0); + default: + usage(1); + } + } + + for (i = optind; i < argc; ++i) + ordered_set_add(&cli_files, argv[i]); +} diff --git a/src/cli.h b/src/cli.h new file mode 100644 index 0000000..88c78cd --- /dev/null +++ b/src/cli.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017-2019 Gentoo Foundation + * Copyright 2017-2019 The Chromium OS Authors + * Released under the 2-clause BSD license. + */ + +#ifndef TMPFILES_CLI_H +#define TMPFILES_CLI_H + +#include "set.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* State variables for the program. */ +extern bool verbose; +extern bool dryrun; +extern bool do_boot; +extern bool do_default; +extern bool do_create; +extern bool do_clean; +extern bool do_remove; +extern ordered_set_t cli_files; +extern ordered_set_t rules_prefix; +extern ordered_set_t rules_exclude_prefix; + +/* Parse the command line arguments. */ +extern void parseargs(int argc, char *argv[]); + +/* Show usage details and exit. */ +attribute_noreturn void usage(int status); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/headers.h b/src/headers.h new file mode 100644 index 0000000..b0e39cf --- /dev/null +++ b/src/headers.h @@ -0,0 +1,29 @@ +/* + * Copyright 2017-2019 Gentoo Foundation + * Copyright 2017-2019 The Chromium OS Authors + * Released under the 2-clause BSD license. + */ + +/* + * We keep all the C library headers in this one place. It might mean we + * include more headers than we need to in some modules, but so be it. The + * overall build should still be "fast enough". + */ + +#ifndef TMPFILES_HEADERS_H +#define TMPFILES_HEADERS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Some compiler attributes we find useful. */ +#define attribute_noreturn __attribute__((__noreturn__)) + +#endif diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..9d95b19 --- /dev/null +++ b/src/main.c @@ -0,0 +1,66 @@ +/* + * Copyright 2017-2019 Gentoo Foundation + * Copyright 2017-2019 The Chromium OS Authors + * Released under the 2-clause BSD license. + */ + +/* + * This module should only contain the main function, and even that should be + * fairly small. Anything in this file is unable to be unittested. + */ + +#include "tmpfiles.h" + +static const char *flatten_set(ordered_set_t *set) +{ + char *ret = NULL; + size_t i; + size_t len = 0; + + for (i = 0; i < set->count; ++i) + len += strlen(set->elements[i]) + 1; + + if (len == 0) + return ""; + + char *p = ret = xmalloc(len); + for (i = 0; i < set->count; ++i) { + char *ele = set->elements[i]; + size_t len = strlen(ele); + memcpy(p, ele, len); + p[len] = ' '; + p += len + 1; + } + ret[len - 1] = '\0'; + return ret; +} + +static void reset_env(void) +{ + setenv("BOOT", do_boot ? "1" : "0", 1); + setenv("CLEAN", do_clean ? "1" : "0", 1); + setenv("CREATE", do_create ? "1" : "0", 1); + setenv("DRYRUN", dryrun ? "1" : "0", 1); + setenv("REMOVE", do_remove ? "1" : "0", 1); + setenv("VERBOSE", verbose ? "1" : "0", 1); + setenv("EXCLUDE", flatten_set(&rules_exclude_prefix), 1); + setenv("PREFIX", flatten_set(&rules_prefix), 1); + setenv("FILES", flatten_set(&cli_files), 1); +} + +int main(int argc, char *argv[]) +{ + parseargs(argc, argv); + + if (do_clean) + errx(1, "--clean is not yet implemented"); + + if (do_create && do_remove) + errx(1, "--create and --remove are mutually exclusive"); + + /* Clear out env vars the shell script expects. */ + reset_env(); + + int ret = execlp("tmpfiles.sh", "tmpfiles.sh", "--run-by-tmpfiles-wrapper", NULL); + err(ret, "Could not execute tmpfiles.sh"); +} diff --git a/src/module.mk b/src/module.mk new file mode 100644 index 0000000..487c659 --- /dev/null +++ b/src/module.mk @@ -0,0 +1,11 @@ +SRC-tmpfiles := \ + cli.c \ + main.c \ + +SRC-libtmpfiles.so := \ + set.c \ + +all: tmpfiles +tmpfiles: $(SRC-libtmpfiles.so:.c=.o) $(SRC-tmpfiles:.c=.o) + $(LINK_CC) +.deps.c: $(SRC-libtmpfiles.so) $(SRC-tmpfiles) diff --git a/src/set.c b/src/set.c new file mode 100644 index 0000000..a381ba8 --- /dev/null +++ b/src/set.c @@ -0,0 +1,43 @@ +/* + * Copyright 2017-2019 Gentoo Foundation + * Copyright 2017-2019 The Chromium OS Authors + * Released under the 2-clause BSD license. + */ + +#include "tmpfiles.h" + +void ordered_set_init(ordered_set_t *set) +{ + set->reserved = 16; + set->count = 0; + set->elements = xmalloc(sizeof(*set->elements) * set->reserved); +} + +void ordered_set_add(ordered_set_t *set, const char *element) +{ + if (set->count == set->reserved) { + set->reserved *= 2; + set->elements = xrealloc(set->elements, sizeof(*set->elements) * set->reserved); + } + + set->elements[set->count] = xstrdup(element); + set->count++; +} + +bool ordered_set_exists(ordered_set_t *set, const char *element) +{ + for (size_t i = 0; i < set->count; ++i) + if (strcmp(set->elements[i], element) == 0) + return true; + + return false; +} + +void ordered_set_free(ordered_set_t *set) +{ + for (size_t i = 0; i < set->count; ++i) + free(set->elements[i]); + + free(set->elements); + set->elements = NULL; +} diff --git a/src/set.h b/src/set.h new file mode 100644 index 0000000..382934d --- /dev/null +++ b/src/set.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017-2019 Gentoo Foundation + * Copyright 2017-2019 The Chromium OS Authors + * Released under the 2-clause BSD license. + */ + +#ifndef TMPFILES_SET_H +#define TMPFILES_SET_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + char **elements; + size_t reserved; + size_t count; +} ordered_set_t; + +/* Initialize a set. Its storage should be declared already. */ +extern void ordered_set_init(ordered_set_t *set); + +/* Add a string to the set. The string is duplicated. */ +extern void ordered_set_add(ordered_set_t *set, const char *element); + +/* Test whether the string is in the set. */ +extern bool ordered_set_exists(ordered_set_t *set, const char *element); + +/* Clear a set. Must call ordered_set_init before using again. */ +extern void ordered_set_free(ordered_set_t *set); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/tmpfiles.h b/src/tmpfiles.h new file mode 100644 index 0000000..e8eb4a6 --- /dev/null +++ b/src/tmpfiles.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017-2019 Gentoo Foundation + * Copyright 2017-2019 The Chromium OS Authors + * Released under the 2-clause BSD license. + */ + +/* + * Include all the project & dependent headers in this one place. It might mean + * we include more headers than we need to in some modules, but so be it. The + * overall build should still be "fast enough". + * + * This should be the only header that tmpfiles modules need to include. + */ + +#ifndef TMPFILES_TMPFILES_H +#define TMPFILES_TMPFILES_H + +/* This needs to come first as it provides C library & compiler details. */ +#include "headers.h" + +#include "xfuncs.h" +#include "set.h" +#include "cli.h" + +#endif diff --git a/src/xfuncs.h b/src/xfuncs.h new file mode 100644 index 0000000..1884c2a --- /dev/null +++ b/src/xfuncs.h @@ -0,0 +1,48 @@ +/* + * Copyright 2017-2019 Gentoo Foundation + * Copyright 2017-2019 The Chromium OS Authors + * Released under the 2-clause BSD license. + */ + +#ifndef TMPFILES_XFUNCS_H +#define TMPFILES_XFUNCS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define xasprintf(...) \ + do { \ + if (asprintf(__VA_ARGS__) < 0) \ + err(1, "asprintf"); \ + } while (0) + +static inline void *xmalloc(size_t size) +{ + void *ret = malloc(size); + if (ret == NULL) + err(1, "malloc"); + return ret; +} + +static inline void *xrealloc(void *ptr, size_t size) +{ + void *ret = realloc(ptr, size); + if (ret == NULL) + err(1, "realloc"); + return ret; +} + +static inline char *xstrdup(const char *str) +{ + char *ret = strdup(str); + if (ret == NULL) + err(1, "strdup"); + return ret; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 0000000..c963b2a --- /dev/null +++ b/test/.gitignore @@ -0,0 +1 @@ +/googletest-release-* diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..ba0026c --- /dev/null +++ b/test/Makefile @@ -0,0 +1,3 @@ +# Helper for developers. +all: ; $(MAKE) -C .. tmpfiles_test +%: ; $(MAKE) -C .. $@ diff --git a/test/cli_test.cc b/test/cli_test.cc new file mode 100644 index 0000000..4205b90 --- /dev/null +++ b/test/cli_test.cc @@ -0,0 +1,9 @@ +/* + * Copyright 2017-2019 Gentoo Foundation + * Copyright 2017-2019 The Chromium OS Authors + * Released under the 2-clause BSD license. + */ + +/* Tests for the cli module. */ + +#include "test.h" diff --git a/test/module.mk b/test/module.mk new file mode 100644 index 0000000..eba6518 --- /dev/null +++ b/test/module.mk @@ -0,0 +1,38 @@ +# The unittests. +LDFLAGS-tmpfiles_test = -pthread +LDLIBS-tmpfiles_test = -lgtest +SRC-tmpfiles_test := \ + cli_test.cc \ + set_test.cc \ + xfuncs_test.cc \ + +OBJ-tmpfiles_test := $(SRC-tmpfiles_test:.cc=.o) +tmpfiles_test: $(OBJ-tmpfiles_test) $(SRC-libtmpfiles.so:.c=.o) + $(LINK_CXX) +.deps.cc: $(SRC-tmpfiles_test) + +# Helper settings for local build of googletest in case the distro doesn't +# support system installs. People can run `make gtest`. +GTEST_VER := 1.8.1 +GTEST := test/googletest-release-$(GTEST_VER) +GTEST_TAR := $(GTEST).tar.gz +.PHONY: gtest +gtest: libgtest.a +libgtest.a: $(GTEST)/gtest-all.o $(GTEST)/gtest_main.o + $(AR) rc $@ $^ +$(GTEST)/gtest-all.o: $(GTEST_TAR) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -pthread \ + -isystem $(GTEST)/googletest/include/ -I$(GTEST)/googletest/ \ + $(GTEST)/googletest/src/gtest-all.cc -c -o $@ +$(GTEST)/gtest_main.o: $(GTEST_TAR) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -pthread \ + -isystem $(GTEST)/googletest/include/ -I$(GTEST)/googletest/ \ + $(GTEST)/googletest/src/gtest_main.cc -c -o $@ +$(GTEST_TAR): + wget -nv \ + "https://github.com/google/googletest/archive/release-${GTEST_VER}.tar.gz" \ + -O "$(GTEST_TAR).tmp" && \ + mv "$(GTEST_TAR).tmp" "$(GTEST_TAR)" + tar -zxf "$(GTEST_TAR)" -C test + +$(OBJ-tmpfiles_test): CPPFLAGS += -I$(GTEST)/googletest/include diff --git a/test/set_test.cc b/test/set_test.cc new file mode 100644 index 0000000..09f4079 --- /dev/null +++ b/test/set_test.cc @@ -0,0 +1,32 @@ +/* + * Copyright 2017-2019 Gentoo Foundation + * Copyright 2017-2019 The Chromium OS Authors + * Released under the 2-clause BSD license. + */ + +/* Tests for the set module. */ + +#include "test.h" + +/* Make sure we can reinit things. */ +TEST(Set, Reinit) { + ordered_set_t set; + ordered_set_init(&set); + ordered_set_free(&set); + ordered_set_init(&set); + ordered_set_free(&set); + ordered_set_init(&set); + ordered_set_free(&set); +} + +/* Smoke test for the API. */ +TEST(Set, Smoke) { + ordered_set_t set; + ordered_set_init(&set); + ASSERT_FALSE(ordered_set_exists(&set, "foo")); + ASSERT_FALSE(ordered_set_exists(&set, "bar")); + ordered_set_add(&set, "foo"); + ASSERT_TRUE(ordered_set_exists(&set, "foo")); + ASSERT_FALSE(ordered_set_exists(&set, "bar")); + ordered_set_free(&set); +} diff --git a/test/test.h b/test/test.h new file mode 100644 index 0000000..5fa7c9f --- /dev/null +++ b/test/test.h @@ -0,0 +1,16 @@ +/* + * Copyright 2017-2019 Gentoo Foundation + * Copyright 2017-2019 The Chromium OS Authors + * Released under the 2-clause BSD license. + */ + +/* Common header for all tests to include. */ + +#ifndef TMPFILES_TEST_H +#define TMPFILES_TEST_H + +#include "tmpfiles.h" + +#include + +#endif diff --git a/test/xfuncs_test.cc b/test/xfuncs_test.cc new file mode 100644 index 0000000..220a4ab --- /dev/null +++ b/test/xfuncs_test.cc @@ -0,0 +1,39 @@ +/* + * Copyright 2017-2019 Gentoo Foundation + * Copyright 2017-2019 The Chromium OS Authors + * Released under the 2-clause BSD license. + */ + +/* Tests for the xfuncs module. */ + +#include "test.h" + +TEST(xfuncs, asprintf) { + char *s; + xasprintf(&s, "a %i %c %s", 12, 'f', "bar"); + ASSERT_STREQ(s, "a 12 f bar"); + free(s); +} + +TEST(xfuncs, xmalloc) { + char *s = static_cast(xmalloc(5)); + memset(s, 'a', 4); + s[4] = '\0'; + ASSERT_STREQ(s, "aaaa"); + free(s); +} + +TEST(xfuncs, xrealloc) { + char *s = static_cast(xmalloc(1)); + s = static_cast(xrealloc(s, 5)); + memset(s, 'a', 4); + s[4] = '\0'; + ASSERT_STREQ(s, "aaaa"); + free(s); +} + +TEST(xfuncs, xstrdup) { + char *s = xstrdup("foo"); + ASSERT_STREQ(s, "foo"); + free(s); +} diff --git a/tmpfiles b/tmpfiles.sh similarity index 92% rename from tmpfiles rename to tmpfiles.sh index 3619b1f..56e5c5c 100755 --- a/tmpfiles +++ b/tmpfiles.sh @@ -16,7 +16,16 @@ # as of 2012/03/12 and also implements some more recent features # -DRYRUN=0 +# Any errors we've accumulated from processing. +error=0 +# XXX: No idea why this is here. +LINENO=0 + +# Make sure we aren't run directly anymore. +if [ $# -ne 1 ] || [ "$1" != "--run-by-tmpfiles-wrapper" ]; then + echo "tmpfiles.sh: this must not be run directly; use tmpfiles instead" >&2 + exit 1 +fi checkprefix() { n=$1 @@ -34,11 +43,6 @@ warninvalid() { error=$(( error+1 )) } >&2 -invalid_option() { - printf "tmpfiles: invalid option '%s'\n" "$1" >&2 - exit 1 -} - dryrun_or_real() { local dryrun= if [ $DRYRUN -eq 1 ]; then @@ -429,49 +433,6 @@ _Z() { CHOPTS=-R relabel "$@" } -usage() { - printf 'usage: %s [--exclude-prefix=path] [--prefix=path] [--boot] [--create] [--remove] [--clean] [--verbose] [--dry-run]\n' "${0##*/}" - exit ${1:-0} -} - -version() { - # We don't record the version info anywhere currently. - echo "opentmpfiles" - exit 0 -} - -BOOT=0 CREATE=0 REMOVE=0 CLEAN=0 VERBOSE=0 DRYRUN=0 error=0 LINENO=0 -EXCLUDE= -PREFIX= -FILES= - -while [ $# -gt 0 ]; do - case $1 in - --boot) BOOT=1 ;; - --create) CREATE=1 ;; - --remove) REMOVE=1 ;; - --clean) CLEAN=1 ;; # TODO: Not implemented - --verbose) VERBOSE=1 ;; - --dryrun|--dry-run) DRYRUN=1 ;; - --exclude-prefix=*) EXCLUDE="${EXCLUDE}${1##--exclude-prefix=} " ;; - --prefix=*) PREFIX="${PREFIX}${1##--prefix=} " ;; - -h|--help) usage ;; - --version) version ;; - -*) invalid_option "$1" ;; - *) FILES="${FILES} $1" - esac - shift -done - -if [ $(( CLEAN )) -eq 1 ] ; then - printf '%s clean mode is not implemented\n' "${0##*/}" - exit 1 -fi - -if [ "$CREATE$REMOVE" = '00' ]; then - usage 1 >&2 -fi - # XXX: The harcoding of /usr/lib/ is an explicit choice by upstream tmpfiles_dirs='/usr/lib/tmpfiles.d /run/tmpfiles.d /etc/tmpfiles.d' tmpfiles_basenames='' @@ -510,8 +471,6 @@ for b in ${FILES} ; do fi done -error=0 - # loop through the gathered fragments, sorted globally by filename. # `/run/tmpfiles/foo.conf' will always be read after `/etc/tmpfiles.d/bar.conf' FILE=