]>
Commit | Line | Data |
---|---|---|
8ea48dfc LP |
1 | /*** |
2 | This file is part of systemd. | |
3 | ||
4 | Copyright 2014 Lennart Poettering | |
5 | ||
6 | systemd is free software; you can redistribute it and/or modify it | |
7 | under the terms of the GNU Lesser General Public License as published by | |
8 | the Free Software Foundation; either version 2.1 of the License, or | |
9 | (at your option) any later version. | |
10 | ||
11 | systemd is distributed in the hope that it will be useful, but | |
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | Lesser General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU Lesser General Public License | |
17 | along with systemd; If not, see <http://www.gnu.org/licenses/>. | |
18 | ***/ | |
19 | ||
3ffd4af2 | 20 | #include "fd-util.h" |
ec2ebfd5 | 21 | #include "fileio.h" |
c004493c | 22 | #include "io-util.h" |
d7b8eec7 | 23 | #include "selinux-util.h" |
3ffd4af2 | 24 | #include "util.h" |
8ea48dfc | 25 | |
4aa4d2ae | 26 | #define MESSAGE \ |
fb8b0869 IS |
27 | "# This file was created by systemd-update-done. Its only \n" \ |
28 | "# purpose is to hold a timestamp of the time this directory\n" \ | |
29 | "# was updated. See systemd-update-done.service(8).\n" | |
4aa4d2ae | 30 | |
8ea48dfc | 31 | static int apply_timestamp(const char *path, struct timespec *ts) { |
0a2f9085 LP |
32 | struct timespec twice[2] = { |
33 | *ts, | |
34 | *ts | |
35 | }; | |
fb8b0869 | 36 | _cleanup_fclose_ FILE *f = NULL; |
ec2ebfd5 | 37 | int fd = -1; |
fb8b0869 | 38 | int r; |
8ea48dfc LP |
39 | |
40 | assert(path); | |
41 | assert(ts); | |
42 | ||
fb8b0869 IS |
43 | /* |
44 | * We store the timestamp both as mtime of the file and in the file itself, | |
45 | * to support filesystems which cannot store nanosecond-precision timestamps. | |
46 | * Hence, don't bother updating the file, let's just rewrite it. | |
47 | */ | |
8ea48dfc | 48 | |
fb8b0869 IS |
49 | r = mac_selinux_create_file_prepare(path, S_IFREG); |
50 | if (r < 0) | |
51 | return log_error_errno(r, "Failed to set SELinux context for %s: %m", path); | |
8ea48dfc | 52 | |
fb8b0869 IS |
53 | fd = open(path, O_CREAT|O_WRONLY|O_TRUNC|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644); |
54 | mac_selinux_create_file_clear(); | |
8ea48dfc | 55 | |
fb8b0869 IS |
56 | if (fd < 0) { |
57 | if (errno == EROFS) | |
58 | return log_debug("Can't create timestamp file %s, file system is read-only.", path); | |
8ea48dfc | 59 | |
fb8b0869 IS |
60 | return log_error_errno(errno, "Failed to create/open timestamp file %s: %m", path); |
61 | } | |
7dbb1d08 | 62 | |
ec2ebfd5 | 63 | f = fdopen(fd, "we"); |
fb8b0869 IS |
64 | if (!f) { |
65 | safe_close(fd); | |
66 | return log_error_errno(errno, "Failed to fdopen() timestamp file %s: %m", path); | |
67 | } | |
8ea48dfc | 68 | |
fb8b0869 | 69 | (void) fprintf(f, |
ec2ebfd5 LP |
70 | MESSAGE |
71 | "TIMESTAMP_NSEC=" NSEC_FMT "\n", | |
72 | timespec_load_nsec(ts)); | |
8ea48dfc | 73 | |
ec2ebfd5 LP |
74 | r = fflush_and_check(f); |
75 | if (r < 0) | |
76 | return log_error_errno(r, "Failed to write timestamp file: %m"); | |
4aa4d2ae | 77 | |
fb8b0869 IS |
78 | if (futimens(fd, twice) < 0) |
79 | return log_error_errno(errno, "Failed to update timestamp on %s: %m", path); | |
8ea48dfc LP |
80 | |
81 | return 0; | |
82 | } | |
83 | ||
84 | int main(int argc, char *argv[]) { | |
85 | struct stat st; | |
7dbb1d08 | 86 | int r, q = 0; |
8ea48dfc LP |
87 | |
88 | log_set_target(LOG_TARGET_AUTO); | |
89 | log_parse_environment(); | |
90 | log_open(); | |
91 | ||
92 | if (stat("/usr", &st) < 0) { | |
755bde37 | 93 | log_error_errno(errno, "Failed to stat /usr: %m"); |
8ea48dfc LP |
94 | return EXIT_FAILURE; |
95 | } | |
96 | ||
c3dacc8b | 97 | r = mac_selinux_init(); |
7dbb1d08 | 98 | if (r < 0) { |
da927ba9 | 99 | log_error_errno(r, "SELinux setup failed: %m"); |
7dbb1d08 ZJS |
100 | goto finish; |
101 | } | |
8ea48dfc | 102 | |
7dbb1d08 | 103 | r = apply_timestamp("/etc/.updated", &st.st_mtim); |
8ea48dfc | 104 | q = apply_timestamp("/var/.updated", &st.st_mtim); |
8ea48dfc | 105 | |
7dbb1d08 ZJS |
106 | finish: |
107 | return r < 0 || q < 0 ? EXIT_FAILURE : EXIT_SUCCESS; | |
8ea48dfc | 108 | } |