tmpfiles.c revision bb29785e0df6a7cf07db0259a60bc1f3b4814cb4
3488e51e244adfc756837287fbfbcc03eca8bf7avboxsync/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync/***
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync This file is part of systemd.
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync Copyright 2010 Lennart Poettering, Kay Sievers
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync systemd is free software; you can redistribute it and/or modify it
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync under the terms of the GNU General Public License as published by
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync the Free Software Foundation; either version 2 of the License, or
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync (at your option) any later version.
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync systemd is distributed in the hope that it will be useful, but
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync WITHOUT ANY WARRANTY; without even the implied warranty of
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync General Public License for more details.
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync You should have received a copy of the GNU General Public License
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync along with systemd; If not, see <http://www.gnu.org/licenses/>.
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync***/
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync#include <unistd.h>
cab65d7f7f5418e157d6e02eb812d1cb43bce2f5vboxsync#include <fcntl.h>
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync#include <errno.h>
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync#include <string.h>
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync#include <sys/stat.h>
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync#include <limits.h>
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync#include <dirent.h>
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync#include <grp.h>
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync#include <pwd.h>
04e845ee9ef813501cd2570a4188cb852d170408vboxsync#include <stdio.h>
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync#include <stdlib.h>
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync#include <stddef.h>
346af0930020342df40a1ca8d13eb185ad48067evboxsync#include <getopt.h>
ddfcbd0a2ee61ce75ecc10a6001d5d834893bf8fvboxsync#include <stdbool.h>
ddfcbd0a2ee61ce75ecc10a6001d5d834893bf8fvboxsync#include <time.h>
e2dc4bbc78bc404ecef43e8c1a2dbe0aad6d3a21vboxsync#include <sys/types.h>
ddfcbd0a2ee61ce75ecc10a6001d5d834893bf8fvboxsync#include <sys/param.h>
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync#include <glob.h>
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync#include <fnmatch.h>
3d5404387e8427a7d05722ff9988620ac872f434vboxsync
3d5404387e8427a7d05722ff9988620ac872f434vboxsync#include "log.h"
3d5404387e8427a7d05722ff9988620ac872f434vboxsync#include "util.h"
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync#include "strv.h"
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync#include "label.h"
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync#include "set.h"
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync/* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
7e77c8f54449be6f28ccbf32f7e651554d9f4060vboxsync * them in the file system. This is intended to be used to create
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync * properly owned directories beneath /tmp, /var/tmp, /run and
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync * /var/lock which are volatile and hence need to be recreated on
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync * bootup. */
7e77c8f54449be6f28ccbf32f7e651554d9f4060vboxsync
04e845ee9ef813501cd2570a4188cb852d170408vboxsyncenum {
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync /* These ones take file names */
72bb582308f9b6953c65b8b8807597dbef848b16vboxsync CREATE_FILE = 'f',
72bb582308f9b6953c65b8b8807597dbef848b16vboxsync TRUNCATE_FILE = 'F',
72bb582308f9b6953c65b8b8807597dbef848b16vboxsync CREATE_DIRECTORY = 'd',
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync TRUNCATE_DIRECTORY = 'D',
bcb837ec8269b7ed260be79053941b4c39c2b59evboxsync
bcb837ec8269b7ed260be79053941b4c39c2b59evboxsync /* These ones take globs */
bcb837ec8269b7ed260be79053941b4c39c2b59evboxsync IGNORE_PATH = 'x',
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync REMOVE_PATH = 'r',
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync RECURSIVE_REMOVE_PATH = 'R'
00c120c036112e6430a84cb41ddc3e847ba1e9e2vboxsync};
3b70225182d72cd205cc25dd310e724773d576c8vboxsync
83ee0b9fd6aa227bf4276f9d41af7ef59c03e8eevboxsynctypedef struct Item {
6361862f262bb5f90ed82f2a6e926c35bfa9cf18vboxsync char type;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0229ec87789aab83ed0595b9ad5151351778e2cfvboxsync char *path;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync uid_t uid;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync gid_t gid;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync mode_t mode;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync usec_t age;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync bool uid_set:1;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync bool gid_set:1;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync bool mode_set:1;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync bool age_set:1;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync} Item;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsyncstatic Hashmap *items = NULL, *globs = NULL;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsyncstatic Set *unix_sockets = NULL;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
08640b1dc58f26140fca6525ced3dbdef4ce45f7vboxsyncstatic bool arg_create = false;
770da3dbb247278c98d1b21d2e11a0a7769131a4vboxsyncstatic bool arg_clean = false;
085bc29163eb87e345acaae02789e4c233d51f3bvboxsyncstatic bool arg_remove = false;
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsyncstatic const char *arg_prefix = NULL;
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync#define MAX_DEPTH 256
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsyncstatic bool needs_glob(int t) {
346af0930020342df40a1ca8d13eb185ad48067evboxsync return t == IGNORE_PATH || t == REMOVE_PATH || t == RECURSIVE_REMOVE_PATH;
346af0930020342df40a1ca8d13eb185ad48067evboxsync}
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsyncstatic struct Item* find_glob(Hashmap *h, const char *match) {
346af0930020342df40a1ca8d13eb185ad48067evboxsync Item *j;
346af0930020342df40a1ca8d13eb185ad48067evboxsync Iterator i;
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync HASHMAP_FOREACH(j, h, i)
346af0930020342df40a1ca8d13eb185ad48067evboxsync if (fnmatch(j->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
346af0930020342df40a1ca8d13eb185ad48067evboxsync return j;
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync return NULL;
346af0930020342df40a1ca8d13eb185ad48067evboxsync}
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsyncstatic void load_unix_sockets(void) {
346af0930020342df40a1ca8d13eb185ad48067evboxsync FILE *f = NULL;
346af0930020342df40a1ca8d13eb185ad48067evboxsync char line[LINE_MAX];
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync if (unix_sockets)
346af0930020342df40a1ca8d13eb185ad48067evboxsync return;
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync /* We maintain a cache of the sockets we found in
346af0930020342df40a1ca8d13eb185ad48067evboxsync * /proc/net/unix to speed things up a little. */
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync if (!(unix_sockets = set_new(string_hash_func, string_compare_func)))
9a0c48116de3ffe1123a662b0c72fb1029a3b587vboxsync return;
bf36f854dfba1d903fb1b3b8820a00da8819049avboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync if (!(f = fopen("/proc/net/unix", "re")))
346af0930020342df40a1ca8d13eb185ad48067evboxsync return;
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync if (!(fgets(line, sizeof(line), f)))
346af0930020342df40a1ca8d13eb185ad48067evboxsync goto fail;
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync for (;;) {
346af0930020342df40a1ca8d13eb185ad48067evboxsync char *p, *s;
346af0930020342df40a1ca8d13eb185ad48067evboxsync int k;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync if (!(fgets(line, sizeof(line), f)))
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync break;
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync
7e77c8f54449be6f28ccbf32f7e651554d9f4060vboxsync truncate_nl(line);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync if (strlen(line) < 53)
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync continue;
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync p = line + 53;
7e77c8f54449be6f28ccbf32f7e651554d9f4060vboxsync p += strspn(p, WHITESPACE);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync p += strcspn(p, WHITESPACE);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync p += strspn(p, WHITESPACE);
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync if (*p != '/')
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync continue;
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync if (!(s = strdup(p)))
ca04977659aed9435519a9aa8fdda2caba315fabvboxsync goto fail;
ca04977659aed9435519a9aa8fdda2caba315fabvboxsync
ca04977659aed9435519a9aa8fdda2caba315fabvboxsync path_kill_slashes(s);
ca04977659aed9435519a9aa8fdda2caba315fabvboxsync
ca04977659aed9435519a9aa8fdda2caba315fabvboxsync if ((k = set_put(unix_sockets, s)) < 0) {
ca04977659aed9435519a9aa8fdda2caba315fabvboxsync free(s);
e2dc4bbc78bc404ecef43e8c1a2dbe0aad6d3a21vboxsync
e2dc4bbc78bc404ecef43e8c1a2dbe0aad6d3a21vboxsync if (k != -EEXIST)
e2dc4bbc78bc404ecef43e8c1a2dbe0aad6d3a21vboxsync goto fail;
e2dc4bbc78bc404ecef43e8c1a2dbe0aad6d3a21vboxsync }
e2dc4bbc78bc404ecef43e8c1a2dbe0aad6d3a21vboxsync }
e2dc4bbc78bc404ecef43e8c1a2dbe0aad6d3a21vboxsync
e2dc4bbc78bc404ecef43e8c1a2dbe0aad6d3a21vboxsync return;
e2dc4bbc78bc404ecef43e8c1a2dbe0aad6d3a21vboxsync
e2dc4bbc78bc404ecef43e8c1a2dbe0aad6d3a21vboxsyncfail:
e2dc4bbc78bc404ecef43e8c1a2dbe0aad6d3a21vboxsync set_free_free(unix_sockets);
e2dc4bbc78bc404ecef43e8c1a2dbe0aad6d3a21vboxsync unix_sockets = NULL;
e2dc4bbc78bc404ecef43e8c1a2dbe0aad6d3a21vboxsync
e2dc4bbc78bc404ecef43e8c1a2dbe0aad6d3a21vboxsync if (f)
e2dc4bbc78bc404ecef43e8c1a2dbe0aad6d3a21vboxsync fclose(f);
e2dc4bbc78bc404ecef43e8c1a2dbe0aad6d3a21vboxsync}
e2dc4bbc78bc404ecef43e8c1a2dbe0aad6d3a21vboxsync
e2dc4bbc78bc404ecef43e8c1a2dbe0aad6d3a21vboxsyncstatic bool unix_socket_alive(const char *fn) {
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync assert(fn);
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync load_unix_sockets();
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync if (unix_sockets)
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync return !!set_get(unix_sockets, (char*) fn);
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync /* We don't know, so assume yes */
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync return true;
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync}
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsyncstatic int dir_cleanup(
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync const char *p,
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync DIR *d,
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync const struct stat *ds,
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync usec_t cutoff,
fa58910f39602536e939414b8862501ca58a6dcavboxsync dev_t rootdev,
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync bool mountpoint,
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync int maxdepth)
cab65d7f7f5418e157d6e02eb812d1cb43bce2f5vboxsync{
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync struct dirent *dent;
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync struct timespec times[2];
cab65d7f7f5418e157d6e02eb812d1cb43bce2f5vboxsync bool deleted = false;
cab65d7f7f5418e157d6e02eb812d1cb43bce2f5vboxsync char *sub_path = NULL;
cab65d7f7f5418e157d6e02eb812d1cb43bce2f5vboxsync int r = 0;
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync while ((dent = readdir(d))) {
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync struct stat s;
13e92d2849569726167f09e34811844eb29fd75bvboxsync usec_t age;
13e92d2849569726167f09e34811844eb29fd75bvboxsync
13e92d2849569726167f09e34811844eb29fd75bvboxsync if (streq(dent->d_name, ".") ||
13e92d2849569726167f09e34811844eb29fd75bvboxsync streq(dent->d_name, ".."))
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync continue;
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync if (errno != ENOENT) {
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync log_error("stat(%s/%s) failed: %m", p, dent->d_name);
13e92d2849569726167f09e34811844eb29fd75bvboxsync r = -errno;
13e92d2849569726167f09e34811844eb29fd75bvboxsync }
13e92d2849569726167f09e34811844eb29fd75bvboxsync
13e92d2849569726167f09e34811844eb29fd75bvboxsync continue;
cab65d7f7f5418e157d6e02eb812d1cb43bce2f5vboxsync }
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync /* Stay on the same filesystem */
cab65d7f7f5418e157d6e02eb812d1cb43bce2f5vboxsync if (s.st_dev != rootdev)
cab65d7f7f5418e157d6e02eb812d1cb43bce2f5vboxsync continue;
cab65d7f7f5418e157d6e02eb812d1cb43bce2f5vboxsync
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync /* Do not delete read-only files owned by root */
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync if (s.st_uid == 0 && !(s.st_mode & S_IWUSR))
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync continue;
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync
cab65d7f7f5418e157d6e02eb812d1cb43bce2f5vboxsync free(sub_path);
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync sub_path = NULL;
cab65d7f7f5418e157d6e02eb812d1cb43bce2f5vboxsync
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync if (asprintf(&sub_path, "%s/%s", p, dent->d_name) < 0) {
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync log_error("Out of memory");
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync r = -ENOMEM;
de3518a42830a03b8ae77186324815046435ab64vboxsync goto finish;
de3518a42830a03b8ae77186324815046435ab64vboxsync }
de3518a42830a03b8ae77186324815046435ab64vboxsync
de3518a42830a03b8ae77186324815046435ab64vboxsync /* Is there an item configured for this path? */
de3518a42830a03b8ae77186324815046435ab64vboxsync if (hashmap_get(items, sub_path))
bc5539d8b4a93e1b4a86033a4c00a6286dc66783vboxsync continue;
de3518a42830a03b8ae77186324815046435ab64vboxsync
de3518a42830a03b8ae77186324815046435ab64vboxsync if (find_glob(globs, sub_path))
de3518a42830a03b8ae77186324815046435ab64vboxsync continue;
de3518a42830a03b8ae77186324815046435ab64vboxsync
de3518a42830a03b8ae77186324815046435ab64vboxsync if (S_ISDIR(s.st_mode)) {
de3518a42830a03b8ae77186324815046435ab64vboxsync
de3518a42830a03b8ae77186324815046435ab64vboxsync if (mountpoint &&
de3518a42830a03b8ae77186324815046435ab64vboxsync streq(dent->d_name, "lost+found") &&
de3518a42830a03b8ae77186324815046435ab64vboxsync s.st_uid == 0)
de3518a42830a03b8ae77186324815046435ab64vboxsync continue;
de3518a42830a03b8ae77186324815046435ab64vboxsync
de3518a42830a03b8ae77186324815046435ab64vboxsync if (maxdepth <= 0)
de3518a42830a03b8ae77186324815046435ab64vboxsync log_warning("Reached max depth on %s.", sub_path);
de3518a42830a03b8ae77186324815046435ab64vboxsync else {
de3518a42830a03b8ae77186324815046435ab64vboxsync DIR *sub_dir;
de3518a42830a03b8ae77186324815046435ab64vboxsync int q;
de3518a42830a03b8ae77186324815046435ab64vboxsync
de3518a42830a03b8ae77186324815046435ab64vboxsync sub_dir = xopendirat(dirfd(d), dent->d_name, O_NOFOLLOW);
de3518a42830a03b8ae77186324815046435ab64vboxsync if (sub_dir == NULL) {
de3518a42830a03b8ae77186324815046435ab64vboxsync if (errno != ENOENT) {
de3518a42830a03b8ae77186324815046435ab64vboxsync log_error("opendir(%s/%s) failed: %m", p, dent->d_name);
de3518a42830a03b8ae77186324815046435ab64vboxsync r = -errno;
de3518a42830a03b8ae77186324815046435ab64vboxsync }
de3518a42830a03b8ae77186324815046435ab64vboxsync
de3518a42830a03b8ae77186324815046435ab64vboxsync continue;
de3518a42830a03b8ae77186324815046435ab64vboxsync }
de3518a42830a03b8ae77186324815046435ab64vboxsync
de3518a42830a03b8ae77186324815046435ab64vboxsync q = dir_cleanup(sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1);
de3518a42830a03b8ae77186324815046435ab64vboxsync closedir(sub_dir);
de3518a42830a03b8ae77186324815046435ab64vboxsync
de3518a42830a03b8ae77186324815046435ab64vboxsync if (q < 0)
de3518a42830a03b8ae77186324815046435ab64vboxsync r = q;
de3518a42830a03b8ae77186324815046435ab64vboxsync }
de3518a42830a03b8ae77186324815046435ab64vboxsync
de3518a42830a03b8ae77186324815046435ab64vboxsync /* Ignore ctime, we change it when deleting */
de3518a42830a03b8ae77186324815046435ab64vboxsync age = MAX(timespec_load(&s.st_mtim),
de3518a42830a03b8ae77186324815046435ab64vboxsync timespec_load(&s.st_atim));
de3518a42830a03b8ae77186324815046435ab64vboxsync if (age >= cutoff)
de3518a42830a03b8ae77186324815046435ab64vboxsync continue;
de3518a42830a03b8ae77186324815046435ab64vboxsync
de3518a42830a03b8ae77186324815046435ab64vboxsync log_debug("rmdir '%s'\n", sub_path);
de3518a42830a03b8ae77186324815046435ab64vboxsync
579bade2e306536e128d4c10a9d90e9a30cb995cvboxsync if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) {
0b6c8d1aa8bcb0cd60905b030114a212fab949b9vboxsync if (errno != ENOENT && errno != ENOTEMPTY) {
0b6c8d1aa8bcb0cd60905b030114a212fab949b9vboxsync log_error("rmdir(%s): %m", sub_path);
0b6c8d1aa8bcb0cd60905b030114a212fab949b9vboxsync r = -errno;
0b6c8d1aa8bcb0cd60905b030114a212fab949b9vboxsync }
579bade2e306536e128d4c10a9d90e9a30cb995cvboxsync }
0b6c8d1aa8bcb0cd60905b030114a212fab949b9vboxsync
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync } else {
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync /* Skip files for which the sticky bit is
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync * set. These are semantics we define, and are
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync * unknown elsewhere. See XDG_RUNTIME_DIR
04e845ee9ef813501cd2570a4188cb852d170408vboxsync * specification for details. */
04e845ee9ef813501cd2570a4188cb852d170408vboxsync if (s.st_mode & S_ISVTX)
04e845ee9ef813501cd2570a4188cb852d170408vboxsync continue;
04e845ee9ef813501cd2570a4188cb852d170408vboxsync
04e845ee9ef813501cd2570a4188cb852d170408vboxsync if (mountpoint && S_ISREG(s.st_mode)) {
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync if (streq(dent->d_name, ".journal") &&
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync s.st_uid == 0)
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync continue;
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync if (streq(dent->d_name, "aquota.user") ||
9161d9a8318db73b2848c1feaef3880980474e64vboxsync streq(dent->d_name, "aquota.group"))
9161d9a8318db73b2848c1feaef3880980474e64vboxsync continue;
9161d9a8318db73b2848c1feaef3880980474e64vboxsync }
9161d9a8318db73b2848c1feaef3880980474e64vboxsync
9161d9a8318db73b2848c1feaef3880980474e64vboxsync /* Ignore sockets that are listed in /proc/net/unix */
af62929dce3cc5e14c75438cd2b893f82ae6dbc8vboxsync if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path))
04e845ee9ef813501cd2570a4188cb852d170408vboxsync continue;
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync
af62929dce3cc5e14c75438cd2b893f82ae6dbc8vboxsync /* Ignore device nodes */
04e845ee9ef813501cd2570a4188cb852d170408vboxsync if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode))
93971f18ac180cbff517c8a86f634dd904a62e2avboxsync continue;
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync
04e845ee9ef813501cd2570a4188cb852d170408vboxsync age = MAX3(timespec_load(&s.st_mtim),
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync timespec_load(&s.st_atim),
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync timespec_load(&s.st_ctim));
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync
04e845ee9ef813501cd2570a4188cb852d170408vboxsync if (age >= cutoff)
af62929dce3cc5e14c75438cd2b893f82ae6dbc8vboxsync continue;
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync log_debug("unlink '%s'\n", sub_path);
af62929dce3cc5e14c75438cd2b893f82ae6dbc8vboxsync
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync if (unlinkat(dirfd(d), dent->d_name, 0) < 0) {
93971f18ac180cbff517c8a86f634dd904a62e2avboxsync if (errno != ENOENT) {
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync log_error("unlink(%s): %m", sub_path);
04e845ee9ef813501cd2570a4188cb852d170408vboxsync r = -errno;
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync }
04e845ee9ef813501cd2570a4188cb852d170408vboxsync }
04e845ee9ef813501cd2570a4188cb852d170408vboxsync
04e845ee9ef813501cd2570a4188cb852d170408vboxsync deleted = true;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync }
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync }
6ee54d76da1437d7dcaf42a0a359de75762fa8bevboxsync
6ee54d76da1437d7dcaf42a0a359de75762fa8bevboxsyncfinish:
6ee54d76da1437d7dcaf42a0a359de75762fa8bevboxsync if (deleted) {
6ee54d76da1437d7dcaf42a0a359de75762fa8bevboxsync /* Restore original directory timestamps */
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync times[0] = ds->st_atim;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync times[1] = ds->st_mtim;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (futimens(dirfd(d), times) < 0)
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync log_error("utimensat(%s): %m", p);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync }
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync free(sub_path);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync return r;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync}
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsyncstatic int clean_item(Item *i) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync DIR *d;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync struct stat s, ps;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync bool mountpoint;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync int r;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync usec_t cutoff, n;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync assert(i);
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync if (i->type != CREATE_DIRECTORY &&
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync i->type != TRUNCATE_DIRECTORY &&
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync i->type != IGNORE_PATH)
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync return 0;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync if (!i->age_set || i->age <= 0)
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync return 0;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync n = now(CLOCK_REALTIME);
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync if (n < i->age)
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync return 0;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync cutoff = n - i->age;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync d = opendir(i->path);
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync if (!d) {
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync if (errno == ENOENT)
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync return 0;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync log_error("Failed to open directory %s: %m", i->path);
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync return -errno;
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync }
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync if (fstat(dirfd(d), &s) < 0) {
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync log_error("stat(%s) failed: %m", i->path);
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync r = -errno;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync goto finish;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync }
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync if (!S_ISDIR(s.st_mode)) {
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync log_error("%s is not a directory.", i->path);
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync r = -ENOTDIR;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync goto finish;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync }
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0) {
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync log_error("stat(%s/..) failed: %m", i->path);
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync r = -errno;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync goto finish;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync }
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync mountpoint = s.st_dev != ps.st_dev ||
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync r = dir_cleanup(i->path, d, &s, cutoff, s.st_dev, mountpoint, MAX_DEPTH);
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsyncfinish:
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync if (d)
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync closedir(d);
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync return r;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync}
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsyncstatic int create_item(Item *i) {
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync int fd = -1, r;
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync mode_t u;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync struct stat st;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync assert(i);
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync switch (i->type) {
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync case IGNORE_PATH:
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync case REMOVE_PATH:
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync case RECURSIVE_REMOVE_PATH:
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync return 0;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync case CREATE_FILE:
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync case TRUNCATE_FILE:
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync u = umask(0);
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync fd = open(i->path, O_CREAT|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY|O_NOFOLLOW|
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync (i->type == TRUNCATE_FILE ? O_TRUNC : 0), i->mode);
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync umask(u);
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync if (fd < 0) {
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync log_error("Failed to create file %s: %m", i->path);
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync r = -errno;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync goto finish;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync }
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync if (fstat(fd, &st) < 0) {
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync log_error("stat(%s) failed: %m", i->path);
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync r = -errno;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync goto finish;
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync }
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync if (!S_ISREG(st.st_mode)) {
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync log_error("%s is not a file.", i->path);
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync r = -EEXIST;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync goto finish;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync }
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync if (i->mode_set)
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync if (fchmod(fd, i->mode) < 0) {
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync log_error("chmod(%s) failed: %m", i->path);
d107911787df36a78788a841b73d24da896d02f6vboxsync r = -errno;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync goto finish;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync }
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync if (i->uid_set || i->gid_set)
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync if (fchown(fd,
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync i->uid_set ? i->uid : (uid_t) -1,
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync i->gid_set ? i->gid : (gid_t) -1) < 0) {
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync log_error("chown(%s) failed: %m", i->path);
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync r = -errno;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync goto finish;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync }
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync break;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync case TRUNCATE_DIRECTORY:
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync case CREATE_DIRECTORY:
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync u = umask(0);
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync r = mkdir(i->path, i->mode);
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync umask(u);
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync if (r < 0 && errno != EEXIST) {
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync log_error("Failed to create directory %s: %m", i->path);
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync r = -errno;
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync goto finish;
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync }
0019a5195e700f7380e64717fcb10e1ce0fcfd91vboxsync
7e77c8f54449be6f28ccbf32f7e651554d9f4060vboxsync if (stat(i->path, &st) < 0) {
7e77c8f54449be6f28ccbf32f7e651554d9f4060vboxsync log_error("stat(%s) failed: %m", i->path);
10be49ac5a81e00a1b1ae8c4a8a9839321ce19dbvboxsync r = -errno;
8989e4f2be9edbf7fe2bcbe8fe936f0b1f3458bdvboxsync goto finish;
8989e4f2be9edbf7fe2bcbe8fe936f0b1f3458bdvboxsync }
8989e4f2be9edbf7fe2bcbe8fe936f0b1f3458bdvboxsync
8989e4f2be9edbf7fe2bcbe8fe936f0b1f3458bdvboxsync if (!S_ISDIR(st.st_mode)) {
8989e4f2be9edbf7fe2bcbe8fe936f0b1f3458bdvboxsync log_error("%s is not a directory.", i->path);
8989e4f2be9edbf7fe2bcbe8fe936f0b1f3458bdvboxsync r = -EEXIST;
8989e4f2be9edbf7fe2bcbe8fe936f0b1f3458bdvboxsync goto finish;
8989e4f2be9edbf7fe2bcbe8fe936f0b1f3458bdvboxsync }
8989e4f2be9edbf7fe2bcbe8fe936f0b1f3458bdvboxsync
8989e4f2be9edbf7fe2bcbe8fe936f0b1f3458bdvboxsync if (i->mode_set)
10be49ac5a81e00a1b1ae8c4a8a9839321ce19dbvboxsync if (chmod(i->path, i->mode) < 0) {
10be49ac5a81e00a1b1ae8c4a8a9839321ce19dbvboxsync log_error("chmod(%s) failed: %m", i->path);
10be49ac5a81e00a1b1ae8c4a8a9839321ce19dbvboxsync r = -errno;
10be49ac5a81e00a1b1ae8c4a8a9839321ce19dbvboxsync goto finish;
b35e3948f1287430503b6b432945b8cf4bfd3a23vboxsync }
10be49ac5a81e00a1b1ae8c4a8a9839321ce19dbvboxsync
10be49ac5a81e00a1b1ae8c4a8a9839321ce19dbvboxsync if (i->uid_set || i->gid_set)
10be49ac5a81e00a1b1ae8c4a8a9839321ce19dbvboxsync if (chown(i->path,
10be49ac5a81e00a1b1ae8c4a8a9839321ce19dbvboxsync i->uid_set ? i->uid : (uid_t) -1,
10be49ac5a81e00a1b1ae8c4a8a9839321ce19dbvboxsync i->gid_set ? i->gid : (gid_t) -1) < 0) {
10be49ac5a81e00a1b1ae8c4a8a9839321ce19dbvboxsync
7e77c8f54449be6f28ccbf32f7e651554d9f4060vboxsync log_error("chown(%s) failed: %m", i->path);
7e77c8f54449be6f28ccbf32f7e651554d9f4060vboxsync r = -errno;
346af0930020342df40a1ca8d13eb185ad48067evboxsync goto finish;
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync }
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync break;
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync }
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync if ((r = label_fix(i->path, false)) < 0)
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync goto finish;
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync log_debug("%s created successfully.", i->path);
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsyncfinish:
346af0930020342df40a1ca8d13eb185ad48067evboxsync if (fd >= 0)
346af0930020342df40a1ca8d13eb185ad48067evboxsync close_nointr_nofail(fd);
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync return r;
346af0930020342df40a1ca8d13eb185ad48067evboxsync}
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsyncstatic int remove_item(Item *i, const char *instance) {
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync int r;
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync assert(i);
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync switch (i->type) {
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync case CREATE_FILE:
346af0930020342df40a1ca8d13eb185ad48067evboxsync case TRUNCATE_FILE:
346af0930020342df40a1ca8d13eb185ad48067evboxsync case CREATE_DIRECTORY:
346af0930020342df40a1ca8d13eb185ad48067evboxsync case IGNORE_PATH:
346af0930020342df40a1ca8d13eb185ad48067evboxsync break;
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync case REMOVE_PATH:
346af0930020342df40a1ca8d13eb185ad48067evboxsync if (remove(instance) < 0 && errno != ENOENT) {
346af0930020342df40a1ca8d13eb185ad48067evboxsync log_error("remove(%s): %m", instance);
346af0930020342df40a1ca8d13eb185ad48067evboxsync return -errno;
346af0930020342df40a1ca8d13eb185ad48067evboxsync }
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync break;
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync case TRUNCATE_DIRECTORY:
346af0930020342df40a1ca8d13eb185ad48067evboxsync case RECURSIVE_REMOVE_PATH:
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync if ((r = rm_rf(instance, false, i->type == RECURSIVE_REMOVE_PATH)) < 0 &&
346af0930020342df40a1ca8d13eb185ad48067evboxsync r != -ENOENT) {
346af0930020342df40a1ca8d13eb185ad48067evboxsync log_error("rm_rf(%s): %s", instance, strerror(-r));
346af0930020342df40a1ca8d13eb185ad48067evboxsync return r;
346af0930020342df40a1ca8d13eb185ad48067evboxsync }
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync break;
346af0930020342df40a1ca8d13eb185ad48067evboxsync }
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync return 0;
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync}
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsyncstatic int remove_item_glob(Item *i) {
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync assert(i);
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync switch (i->type) {
346af0930020342df40a1ca8d13eb185ad48067evboxsync
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync case CREATE_FILE:
346af0930020342df40a1ca8d13eb185ad48067evboxsync case TRUNCATE_FILE:
346af0930020342df40a1ca8d13eb185ad48067evboxsync case CREATE_DIRECTORY:
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync case IGNORE_PATH:
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync break;
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync case REMOVE_PATH:
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync case TRUNCATE_DIRECTORY:
346af0930020342df40a1ca8d13eb185ad48067evboxsync case RECURSIVE_REMOVE_PATH: {
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync int r = 0, k;
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync glob_t g;
346af0930020342df40a1ca8d13eb185ad48067evboxsync char **fn;
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync zero(g);
346af0930020342df40a1ca8d13eb185ad48067evboxsync
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync errno = 0;
346af0930020342df40a1ca8d13eb185ad48067evboxsync if ((k = glob(i->path, GLOB_NOSORT|GLOB_BRACE, NULL, &g)) != 0) {
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync if (k != GLOB_NOMATCH) {
346af0930020342df40a1ca8d13eb185ad48067evboxsync if (errno != 0)
346af0930020342df40a1ca8d13eb185ad48067evboxsync errno = EIO;
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync log_error("glob(%s) failed: %m", i->path);
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync return -errno;
346af0930020342df40a1ca8d13eb185ad48067evboxsync }
346af0930020342df40a1ca8d13eb185ad48067evboxsync }
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync STRV_FOREACH(fn, g.gl_pathv)
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync if ((k = remove_item(i, *fn)) < 0)
346af0930020342df40a1ca8d13eb185ad48067evboxsync r = k;
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync globfree(&g);
346af0930020342df40a1ca8d13eb185ad48067evboxsync return r;
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync }
346af0930020342df40a1ca8d13eb185ad48067evboxsync }
0229ec87789aab83ed0595b9ad5151351778e2cfvboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync return 0;
346af0930020342df40a1ca8d13eb185ad48067evboxsync}
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsyncstatic int process_item(Item *i) {
0229ec87789aab83ed0595b9ad5151351778e2cfvboxsync int r, q, p;
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync assert(i);
346af0930020342df40a1ca8d13eb185ad48067evboxsync
346af0930020342df40a1ca8d13eb185ad48067evboxsync r = arg_create ? create_item(i) : 0;
0229ec87789aab83ed0595b9ad5151351778e2cfvboxsync q = arg_remove ? remove_item_glob(i) : 0;
346af0930020342df40a1ca8d13eb185ad48067evboxsync p = arg_clean ? clean_item(i) : 0;
346af0930020342df40a1ca8d13eb185ad48067evboxsync
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync if (r < 0)
346af0930020342df40a1ca8d13eb185ad48067evboxsync return r;
346af0930020342df40a1ca8d13eb185ad48067evboxsync
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync if (q < 0)
346af0930020342df40a1ca8d13eb185ad48067evboxsync return q;
346af0930020342df40a1ca8d13eb185ad48067evboxsync
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync return p;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync}
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsyncstatic void item_free(Item *i) {
04e845ee9ef813501cd2570a4188cb852d170408vboxsync assert(i);
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync free(i->path);
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync free(i);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync}
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsyncstatic int parse_line(const char *fname, unsigned line, const char *buffer) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync Item *i;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync char *mode = NULL, *user = NULL, *group = NULL, *age = NULL;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync int r;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync assert(fname);
3933885bc0c2c93436d858a14564c6179ec72872vboxsync assert(line >= 1);
3933885bc0c2c93436d858a14564c6179ec72872vboxsync assert(buffer);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
bc4a29896b294cac2f21a3f0a5e325c0b36336a5vboxsync if (!(i = new0(Item, 1))) {
bc4a29896b294cac2f21a3f0a5e325c0b36336a5vboxsync log_error("Out of memory");
3933885bc0c2c93436d858a14564c6179ec72872vboxsync return -ENOMEM;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync }
bc4a29896b294cac2f21a3f0a5e325c0b36336a5vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (sscanf(buffer,
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync "%c "
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync "%ms "
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync "%ms "
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync "%ms "
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync "%ms "
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync "%ms",
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync &i->type,
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync &i->path,
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync &mode,
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync &user,
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync &group,
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync &age) < 2) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync log_error("[%s:%u] Syntax error.", fname, line);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync r = -EIO;
00c120c036112e6430a84cb41ddc3e847ba1e9e2vboxsync goto finish;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync }
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (i->type != CREATE_FILE &&
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync i->type != TRUNCATE_FILE &&
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync i->type != CREATE_DIRECTORY &&
1ffcba1fe37addee8c8dad3d0f38e84370dcaad3vboxsync i->type != TRUNCATE_DIRECTORY &&
e02cba90793fdee158a64297f91d29c7738d8abdvboxsync i->type != IGNORE_PATH &&
e02cba90793fdee158a64297f91d29c7738d8abdvboxsync i->type != REMOVE_PATH &&
1ffcba1fe37addee8c8dad3d0f38e84370dcaad3vboxsync i->type != RECURSIVE_REMOVE_PATH) {
1ffcba1fe37addee8c8dad3d0f38e84370dcaad3vboxsync log_error("[%s:%u] Unknown file type '%c'.", fname, line, i->type);
1ffcba1fe37addee8c8dad3d0f38e84370dcaad3vboxsync r = -EBADMSG;
e02cba90793fdee158a64297f91d29c7738d8abdvboxsync goto finish;
e02cba90793fdee158a64297f91d29c7738d8abdvboxsync }
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (!path_is_absolute(i->path)) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync log_error("[%s:%u] Path '%s' not absolute.", fname, line, i->path);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync r = -EBADMSG;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync goto finish;
7e77c8f54449be6f28ccbf32f7e651554d9f4060vboxsync }
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync path_kill_slashes(i->path);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (arg_prefix && !path_startswith(i->path, arg_prefix)) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync r = 0;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync goto finish;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync }
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (user && !streq(user, "-")) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync unsigned long lu;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync struct passwd *p;
1ffcba1fe37addee8c8dad3d0f38e84370dcaad3vboxsync
e02cba90793fdee158a64297f91d29c7738d8abdvboxsync if (streq(user, "root") || streq(user, "0"))
e02cba90793fdee158a64297f91d29c7738d8abdvboxsync i->uid = 0;
1ffcba1fe37addee8c8dad3d0f38e84370dcaad3vboxsync else if (safe_atolu(user, &lu) >= 0)
1ffcba1fe37addee8c8dad3d0f38e84370dcaad3vboxsync i->uid = (uid_t) lu;
e02cba90793fdee158a64297f91d29c7738d8abdvboxsync else if ((p = getpwnam(user)))
e02cba90793fdee158a64297f91d29c7738d8abdvboxsync i->uid = p->pw_uid;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync else {
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
04e845ee9ef813501cd2570a4188cb852d170408vboxsync r = -ENOENT;
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync goto finish;
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync }
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync i->uid_set = true;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync }
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
224edf755dff839a1896d3930ea7627f69eb0d9fvboxsync if (group && !streq(group, "-")) {
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync unsigned long lu;
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync struct group *g;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (streq(group, "root") || streq(group, "0"))
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync i->gid = 0;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync else if (safe_atolu(group, &lu) >= 0)
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync i->gid = (gid_t) lu;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync else if ((g = getgrnam(group)))
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync i->gid = g->gr_gid;
08640b1dc58f26140fca6525ced3dbdef4ce45f7vboxsync else {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync r = -ENOENT;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync goto finish;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync }
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync i->gid_set = true;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync }
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (mode && !streq(mode, "-")) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync unsigned m;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (sscanf(mode, "%o", &m) != 1) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync r = -ENOENT;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync goto finish;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync }
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync i->mode = m;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync i->mode_set = true;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync } else
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync i->mode = i->type == CREATE_DIRECTORY ? 0755 : 0644;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (age && !streq(age, "-")) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (parse_usec(age, &i->age) < 0) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync r = -EBADMSG;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync goto finish;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync }
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync i->age_set = true;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync }
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if ((r = hashmap_put(needs_glob(i->type) ? globs : items, i->path, i)) < 0) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (r == -EEXIST) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync log_warning("Two or more conflicting lines for %s configured, ignoring.", i->path);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync r = 0;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync goto finish;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync }
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync log_error("Failed to insert item %s: %s", i->path, strerror(-r));
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync goto finish;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync }
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync i = NULL;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync r = 0;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsyncfinish:
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync free(user);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync free(group);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync free(mode);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync free(age);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (i)
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync item_free(i);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync return r;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync}
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsyncstatic int scandir_filter(const struct dirent *d) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync assert(d);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (ignore_file(d->d_name))
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync return 0;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (d->d_type != DT_REG &&
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync d->d_type != DT_LNK &&
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync d->d_type != DT_UNKNOWN)
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync return 0;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync return endswith(d->d_name, ".conf");
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync}
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsyncstatic int help(void) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync " -h --help Show this help\n"
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync " --create Create marked files/directories\n"
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync " --clean Clean up marked directories\n"
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync " --remove Remove marked files/directories\n"
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync " --prefix=PATH Only apply rules that apply to paths with the specified prefix\n",
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync program_invocation_short_name);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync return 0;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync}
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsyncstatic int parse_argv(int argc, char *argv[]) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync enum {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync ARG_CREATE,
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync ARG_CLEAN,
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync ARG_REMOVE,
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync ARG_PREFIX
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync };
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync static const struct option options[] = {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync { "help", no_argument, NULL, 'h' },
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync { "create", no_argument, NULL, ARG_CREATE },
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync { "clean", no_argument, NULL, ARG_CLEAN },
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync { "remove", no_argument, NULL, ARG_REMOVE },
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync { "prefix", required_argument, NULL, ARG_PREFIX },
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync { NULL, 0, NULL, 0 }
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync };
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync int c;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync assert(argc >= 0);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync assert(argv);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync switch (c) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync case 'h':
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync help();
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync return 0;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync case ARG_CREATE:
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync arg_create = true;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync break;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync case ARG_CLEAN:
08640b1dc58f26140fca6525ced3dbdef4ce45f7vboxsync arg_clean = true;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync break;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync case ARG_REMOVE:
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync arg_remove = true;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync break;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync case ARG_PREFIX:
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync arg_prefix = optarg;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync break;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync case '?':
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync return -EINVAL;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync default:
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync log_error("Unknown option code %c", c);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync return -EINVAL;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync }
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync }
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (!arg_clean && !arg_create && !arg_remove) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync log_error("You need to specify at least one of --clean, --create or --remove.");
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync return -EINVAL;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync }
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync return 1;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync}
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsyncstatic int read_config_file(const char *fn, bool ignore_enoent) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync FILE *f;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync unsigned v = 0;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync int r = 0;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync assert(fn);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (!(f = fopen(fn, "re"))) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (ignore_enoent && errno == ENOENT)
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync return 0;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync log_error("Failed to open %s: %m", fn);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync return -errno;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync }
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync for (;;) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync char line[LINE_MAX], *l;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync int k;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (!(fgets(line, sizeof(line), f)))
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync break;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync v++;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync l = strstrip(line);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (*l == '#' || *l == 0)
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync continue;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
08640b1dc58f26140fca6525ced3dbdef4ce45f7vboxsync if ((k = parse_line(fn, v, l)) < 0)
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (r == 0)
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync r = k;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync }
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (ferror(f)) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync log_error("Failed to read from file %s: %m", fn);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (r == 0)
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync r = -EIO;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync }
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync fclose(f);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync return r;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync}
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsyncint main(int argc, char *argv[]) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync int r;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync Item *i;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync Iterator iterator;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if ((r = parse_argv(argc, argv)) <= 0)
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync log_set_target(LOG_TARGET_AUTO);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync log_parse_environment();
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync log_open();
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync label_init();
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync items = hashmap_new(string_hash_func, string_compare_func);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync globs = hashmap_new(string_hash_func, string_compare_func);
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (!items || !globs) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync log_error("Out of memory");
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync r = EXIT_FAILURE;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync goto finish;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync }
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
3d5255f19648dff685a8fe0c6cd3f408f37831a6vboxsync r = EXIT_SUCCESS;
08640b1dc58f26140fca6525ced3dbdef4ce45f7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (optind < argc) {
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync int j;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync for (j = optind; j < argc; j++)
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync if (read_config_file(argv[j], false) < 0)
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync r = EXIT_FAILURE;
0de1998ac52682bb5322df476e45f237265ea9b7vboxsync
085bc29163eb87e345acaae02789e4c233d51f3bvboxsync } else {
3488e51e244adfc756837287fbfbcc03eca8bf7avboxsync int n, j;
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync struct dirent **de = NULL;
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync if ((n = scandir("/etc/tmpfiles.d/", &de, scandir_filter, alphasort)) < 0) {
ff5245daf827201fb36f05d113c677bf33ce02bevboxsync
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync if (errno != ENOENT) {
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync log_error("Failed to enumerate /etc/tmpfiles.d/ files: %m");
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync r = EXIT_FAILURE;
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync }
ff5245daf827201fb36f05d113c677bf33ce02bevboxsync
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync goto finish;
ff5245daf827201fb36f05d113c677bf33ce02bevboxsync }
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync for (j = 0; j < n; j++) {
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync int k;
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync char *fn;
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync k = asprintf(&fn, "/etc/tmpfiles.d/%s", de[j]->d_name);
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync free(de[j]);
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync if (k < 0) {
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync log_error("Failed to allocate file name.");
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync r = EXIT_FAILURE;
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync continue;
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync }
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync if (read_config_file(fn, true) < 0)
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync r = EXIT_FAILURE;
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync free(fn);
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync }
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync free(de);
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync }
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync HASHMAP_FOREACH(i, globs, iterator)
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync if (process_item(i) < 0)
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync r = EXIT_FAILURE;
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync HASHMAP_FOREACH(i, items, iterator)
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync if (process_item(i) < 0)
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync r = EXIT_FAILURE;
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsyncfinish:
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync while ((i = hashmap_steal_first(items)))
83fd17a3a00dc7bf6a36e23bbd2393dfc953da06vboxsync item_free(i);
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync while ((i = hashmap_steal_first(globs)))
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync item_free(i);
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync hashmap_free(items);
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync hashmap_free(globs);
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync set_free_free(unix_sockets);
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync label_finish();
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync
d9d070cfd2c99624fe6974842b7ad4a30d5b71e7vboxsync return r;
dd7ab8b5e81f0040ea80740f902294e19fc4ccf4vboxsync}
dd7ab8b5e81f0040ea80740f902294e19fc4ccf4vboxsync