Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] start converting tmpfiles from shell to C #10

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Generated dependency files.
.deps*

# Compiled objects/libs.
*.[oa]

# Our project programs.
/tmpfiles
/tmpfiles_test
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ compiler:
- gcc
- clang

dist: xenial
os:
- linux

Expand Down
36 changes: 34 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -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
21 changes: 21 additions & 0 deletions build.mk
Original file line number Diff line number Diff line change
@@ -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)
3 changes: 3 additions & 0 deletions ci/travis.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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 "$@"
3 changes: 3 additions & 0 deletions src/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Helper for developers.
all: ; $(MAKE) -C .. all
%: ; $(MAKE) -C .. $@
166 changes: 166 additions & 0 deletions src/cli.c
Original file line number Diff line number Diff line change
@@ -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 ? "" : "<arg>");
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]);
}
38 changes: 38 additions & 0 deletions src/cli.h
Original file line number Diff line number Diff line change
@@ -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
29 changes: 29 additions & 0 deletions src/headers.h
Original file line number Diff line number Diff line change
@@ -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 <err.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

/* Some compiler attributes we find useful. */
#define attribute_noreturn __attribute__((__noreturn__))

#endif
Loading