update-done.c revision 8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4b
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering/***
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering This file is part of systemd.
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering Copyright 2014 Lennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering systemd is free software; you can redistribute it and/or modify it
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering under the terms of the GNU Lesser General Public License as published by
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering (at your option) any later version.
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering systemd is distributed in the hope that it will be useful, but
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering Lesser General Public License for more details.
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering You should have received a copy of the GNU Lesser General Public License
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering***/
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering#include "util.h"
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poetteringstatic int apply_timestamp(const char *path, struct timespec *ts) {
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering struct timespec twice[2];
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering struct stat st;
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering assert(path);
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering assert(ts);
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering if (stat(path, &st) >= 0) {
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering /* Is the timestamp file already newer than the OS? If so, there's nothing to do. */
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering if (st.st_mtim.tv_sec > ts->tv_sec ||
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering (st.st_mtim.tv_sec == ts->tv_sec && st.st_mtim.tv_nsec >= ts->tv_nsec))
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering return 0;
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering /* It is older? Then let's update it */
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering twice[0] = *ts;
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering twice[1] = *ts;
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering if (utimensat(AT_FDCWD, path, twice, AT_SYMLINK_NOFOLLOW) < 0) {
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering if (errno == EROFS) {
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering log_debug("Can't update timestamp file %s, file system is read-only.", path);
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering return 0;
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering }
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering log_error("Failed to update timestamp on %s: %m", path);
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering return -errno;
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering }
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering } else if (errno == ENOENT) {
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering _cleanup_close_ int fd = -1;
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering /* The timestamp file doesn't exist yet? Then let's create it. */
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering fd = open(path, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644);
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering if (fd < 0) {
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering if (errno == EROFS) {
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering log_debug("Can't create timestamp file %s, file system is read-only.", path);
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering return 0;
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering }
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering log_error("Failed to create timestamp file %s: %m", path);
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering return -errno;
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering }
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering twice[0] = *ts;
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering twice[1] = *ts;
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering if (futimens(fd, twice) < 0) {
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering log_error("Failed to update timestamp on %s: %m", path);
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering return -errno;
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering }
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering } else {
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering log_error("Failed to stat() timestamp file %s: %m", path);
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering return -errno;
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering }
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering return 0;
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering}
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poetteringint main(int argc, char *argv[]) {
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering struct stat st;
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering int r, q;
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering log_set_target(LOG_TARGET_AUTO);
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering log_parse_environment();
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering log_open();
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering if (stat("/usr", &st) < 0) {
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering log_error("Failed to stat /usr: %m");
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering return EXIT_FAILURE;
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering }
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering r = apply_timestamp("/etc/.updated", &st.st_mtim);
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering q = apply_timestamp("/var/.updated", &st.st_mtim);
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering if (q < 0 && r == 0)
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering r = q;
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
8ea48dfcd33e8db0c01bf8c57c3bbcfdc3c86d4bLennart Poettering}