repo: Make summary and signature mtime match
authorDan Nicholson <dbn@endlessos.org>
Thu, 25 Apr 2024 03:37:13 +0000 (21:37 -0600)
committerDan Nicholson <dbn@endlessos.org>
Thu, 25 Apr 2024 15:38:50 +0000 (09:38 -0600)
HTTP servers derive Last-Modified from the modification time of the
file. When used in combination with a Cache-Control max-age value,
having the modification times match means that caches will consider them
expired at the same time. This helps make it more likely that clients
won't receive a cached summary and fresh signature or vice versa.

This makes more sense to do now that the summary and signature are
created in a temporary directory and renamed into place. In the old days
where they were created directly in the repo root, it would be strange
to change the summary mtime when it wasn't actually modified.

src/libostree/ostree-repo.c
tests/test-summary-update.sh

index 04a540296d210b2b8643799e222e61598f8a77f2..2f4e836c6559a08943ffa13f5b6113f063bca31a 100644 (file)
@@ -6092,6 +6092,23 @@ regenerate_metadata (OstreeRepo *self, gboolean do_metadata_commit, GVariant *ad
       && !_ostree_sign_summary_at (sign, self, summary_tmpdir.fd, sign_keys, cancellable, error))
     return FALSE;
 
+  /* If a signature was made, sync the summary times to it. This way an
+   * HTTP client will consider the files expired at the same time.
+   */
+  if (gpg_key_ids != NULL || sign_keys != NULL)
+    {
+      struct stat stbuf;
+      if (!glnx_fstatat (summary_tmpdir.fd, "summary.sig", &stbuf, AT_SYMLINK_NOFOLLOW, error))
+        return glnx_prefix_error (error, "Unable to get summary.sig status");
+
+      struct timespec ts[2];
+      ts[0] = stbuf.st_atim;
+      ts[1] = stbuf.st_mtim;
+      if (TEMP_FAILURE_RETRY (utimensat (summary_tmpdir.fd, "summary", ts, AT_SYMLINK_NOFOLLOW))
+          != 0)
+        return glnx_throw_errno_prefix (error, "Unable to change summary timestamps");
+    }
+
   /* Rename them into place */
   if (!glnx_renameat (summary_tmpdir.fd, "summary", self->repo_dir_fd, "summary", error))
     return glnx_prefix_error (error, "Unable to rename summary file: ");
index 6cf5fccbc845501ec35ca13f3b70d4a77d05c5a1..643502cdfdf9713364ee3d99fb16fad7cab73653 100755 (executable)
@@ -51,6 +51,14 @@ ${CMD_PREFIX} ostree --repo=repo summary --update
 # Generate a signed summary file.
 ${CMD_PREFIX} ostree --repo=repo summary --update ${COMMIT_SIGN}
 
+# If the signature file was created, it should have the same
+# modification time as the summary file.
+if [ -n "${COMMIT_SIGN}" ]; then
+    stat -c '%y' repo/summary > summary-mtime
+    stat -c '%y' repo/summary.sig > summary.sig-mtime
+    assert_files_equal summary-mtime summary.sig-mtime
+fi
+
 # Try various ways of adding additional data.
 ${CMD_PREFIX} ostree --repo=repo summary --update --add-metadata key="'value'" --add-metadata=key2=true
 ${CMD_PREFIX} ostree --repo=repo summary --update -m some-int='@t 123'
@@ -87,6 +95,14 @@ ${CMD_PREFIX} ostree --repo=repo summary --update
 # Generate a signed summary file.
 ${CMD_PREFIX} ostree --repo=repo summary --update ${COMMIT_SIGN}
 
+# If the signature file was created, it should have the same
+# modification time as the summary file.
+if [ -n "${COMMIT_SIGN}" ]; then
+    stat -c '%y' repo/summary > summary-mtime
+    stat -c '%y' repo/summary.sig > summary.sig-mtime
+    assert_files_equal summary-mtime summary.sig-mtime
+fi
+
 # Try various ways of adding additional data.
 ${CMD_PREFIX} ostree --repo=repo summary --update --add-metadata key="'value'" --add-metadata=key2=true
 ${CMD_PREFIX} ostree --repo=repo summary --update -m some-int='@t 123'