1#!/usr/bin/env bash 2# SPDX-License-Identifier: LGPL-2.1-or-later 3# 4# Test the "Age" parameter (with age-by) for systemd-tmpfiles. 5set -e 6set -x 7 8# Test directory structure looks like this: 9# /tmp/ageby/ 10# ├── d1 11# │ ├── f1 12# │ ├── f2 13# │ ├── f3 14# │ └── f4 15# ├── d2 16# │ ├── f1 17# │ ├── f2 18# ... 19 20export SYSTEMD_LOG_LEVEL="debug" 21 22rm -rf /tmp/ageby 23mkdir -p /tmp/ageby/d{1..4} 24 25# TODO: There is probably a better way to figure this out. 26# Test for [bB] age-by arguments only on filesystems that expose 27# the creation time. Note that this is _not_ an accurate way to 28# check if the filesystem or kernel version don't provide the 29# timestamp. But, if the timestamp is visible in "stat" it is a 30# good indicator that the test can be run. 31TEST_TMPFILES_AGEBY_BTIME=${TEST_TMPFILES_AGEBY_BTIME:-0} 32if stat --format "%w" /tmp/ageby 2>/dev/null | grep -qv '^[\?\-]$'; then 33 TEST_TMPFILES_AGEBY_BTIME=1 34fi 35 36touch -a --date "2 minutes ago" /tmp/ageby/d1/f1 37touch -m --date "4 minutes ago" /tmp/ageby/d2/f1 38 39# Create a bunch of other files. 40touch /tmp/ageby/d{1,2}/f{2..4} 41 42# For "ctime". 43touch /tmp/ageby/d3/f1 44chmod +x /tmp/ageby/d3/f1 45sleep 1 46 47# For "btime". 48touch /tmp/ageby/d4/f1 49sleep 1 50 51# More files with recent "{a,b}time" values. 52touch /tmp/ageby/d{3,4}/f{2..4} 53 54# Check for cleanup of "f1" in each of "/tmp/d{1..4}". 55systemd-tmpfiles --clean - <<-EOF 56d /tmp/ageby/d1 - - - a:1m - 57e /tmp/ageby/d2 - - - m:3m - 58D /tmp/ageby/d3 - - - c:2s - 59EOF 60 61for d in d{1..3}; do 62 test ! -f "/tmp/ageby/${d}/f1" 63done 64 65if [[ $TEST_TMPFILES_AGEBY_BTIME -gt 0 ]]; then 66 systemd-tmpfiles --clean - <<-EOF 67d /tmp/ageby/d4 - - - b:1s - 68EOF 69 70 test ! -f "/tmp/ageby/d4/f1" 71else 72 # Remove the file manually. 73 rm "/tmp/ageby/d4/f1" 74fi 75 76# Check for an invalid "age" and "age-by" arguments. 77for a in ':' ':1s' '2:1h' 'nope:42h' '" :7m"' 'm:' '::' '"+r^w-x:2/h"' 'b ar::64'; do 78 systemd-tmpfiles --clean - <<EOF 2>&1 | grep -q -F 'Invalid age' 79d /tmp/ageby - - - ${a} - 80EOF 81done 82 83for d in d{1..4}; do 84 for f in f{2..4}; do 85 test -f "/tmp/ageby/${d}/${f}" 86 done 87done 88 89# Check for parsing with whitespace, repeated values 90# for "age-by" (valid arguments). 91for a in '" a:24h"' 'cccaab:2h' '" aa : 4h"' '" a A B C c:1h"'; do 92 systemd-tmpfiles --clean - <<EOF 93d /tmp/ageby - - - ${a} - 94EOF 95done 96 97for d in d{1..4}; do 98 for f in f{2..4}; do 99 test -f "/tmp/ageby/${d}/${f}" 100 done 101done 102 103# Check that all files are removed if the "Age" is 104# set to "0" (regardless of "age-by" argument). 105systemd-tmpfiles --clean - <<-EOF 106d /tmp/ageby/d1 - - - abc:0 - 107e /tmp/ageby/d2 - - - cmb:0 - 108EOF 109 110for d in d{1,2}; do 111 for f in f{2..4}; do 112 test ! -f "/tmp/ageby/${d}/${f}" 113 done 114done 115 116# Check for combinations: 117# - "/tmp/ageby/d3/f2" has file timestamps that 118# are older than the specified age, it will be 119# removed 120# - "/tmp/ageby/d4/f2", has not aged for the given 121# timestamp combination, it will not be removed 122touch -a -m --date "4 minutes ago" /tmp/ageby/d3/f2 123touch -a -m --date "8 minutes ago" /tmp/ageby/d4/f2 124systemd-tmpfiles --clean - <<-EOF 125e /tmp/ageby/d3 - - - am:3m - 126D /tmp/ageby/d4 - - - mc:7m - 127EOF 128 129test ! -f "/tmp/ageby/d3/f2" 130test -f "/tmp/ageby/d4/f2" 131 132# Check that all files are removed if only "Age" is set to 0. 133systemd-tmpfiles --clean - <<-EOF 134e /tmp/ageby/d3 - - - 0s 135d /tmp/ageby/d4 - - - 0s 136EOF 137 138for d in d{3,4}; do 139 for f in f{2..4}; do 140 test ! -f "/tmp/ageby/$d/${f}" 141 done 142done 143 144# Check "age-by" argument for sub-directories in "/tmp/ageby". 145systemd-tmpfiles --clean - <<-EOF 146d /tmp/ageby/ - - - A:1m - 147EOF 148 149for d in d{1..4}; do 150 test -d "/tmp/ageby/${d}" 151done 152 153# Check for combinations. 154touch -a -m --date "5 seconds ago" /tmp/ageby/d{1,2} 155systemd-tmpfiles --clean - <<-EOF 156e /tmp/ageby/ - - - AM:4s - 157EOF 158 159for d in d{1,2}; do 160 test ! -d "/tmp/ageby/${d}" 161done 162 163for d in d{3,4}; do 164 test -d "/tmp/ageby/${d}" 165done 166 167# Check "btime" for directories. 168if [[ $TEST_TMPFILES_AGEBY_BTIME -gt 0 ]]; then 169 systemd-tmpfiles --clean - <<-EOF 170d /tmp/ageby/ - - - B:8s - 171EOF 172 173 for d in d{3,4}; do 174 test -d "/tmp/ageby/${d}" 175 done 176fi 177 178# To bump "atime". 179touch -a --date "1 second ago" /tmp/ageby/d3 180systemd-tmpfiles --clean - <<-EOF 181d /tmp/ageby/ - - - A:2s - 182EOF 183 184test -d /tmp/ageby/d3 185test ! -d /tmp/ageby/d4 186 187# Check if sub-directories are removed regardless 188# of "age-by", when "Age" is set to "0". 189systemd-tmpfiles --clean - <<-EOF 190D /tmp/ageby/ - - - AM:0 - 191EOF 192 193test ! -d /tmp/ageby/d3 194 195# Cleanup the test directory (fail if not empty). 196rmdir /tmp/ageby 197