summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <pwithnall@endlessos.org>2022-11-03 15:41:39 +0000
committerSimon McVittie <smcv@debian.org>2022-11-16 18:46:01 +0000
commit9ec783f029a4bd41fb41d8472796c2b10d97ec4c (patch)
tree8d9c9020b9573fb82fab0246c1f14ac58e371b54
parent6c7eb34dd641f1bca29d1e44ac3954898f2ee57c (diff)
downloadflatpak-9ec783f029a4bd41fb41d8472796c2b10d97ec4c.tar.gz
flatpak-dir: Clean up old leaked deploy dirs at start of deploy
Following on from commit 85a83a06f95, add some code to clean up old leaked deploy tmpdirs when we next try to deploy the same app (successfully or not). This should free up disk space leaked by failed deploys pre-85a83a06f95. Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
-rw-r--r--common/flatpak-dir.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c
index 1508ebf2..01362a2b 100644
--- a/common/flatpak-dir.c
+++ b/common/flatpak-dir.c
@@ -4559,6 +4559,66 @@ remove_old_appstream_tmpdirs (GFile *dir)
}
}
+/* Like the function above, this looks for old temporary directories created by
+ * previous versions of flatpak_dir_deploy().
+ * These are all directories starting with a dot. Such directories can be from a
+ * concurrent deploy, so we only remove directories older than a day to avoid
+ * races.
+*/
+static void
+remove_old_deploy_tmpdirs (GFile *dir)
+{
+ g_auto(GLnxDirFdIterator) dir_iter = { 0 };
+ time_t now = time (NULL);
+
+ if (!glnx_dirfd_iterator_init_at (AT_FDCWD, flatpak_file_get_path_cached (dir),
+ FALSE, &dir_iter, NULL))
+ return;
+
+ while (TRUE)
+ {
+ struct stat stbuf;
+ struct dirent *dent;
+ g_autoptr(GFile) tmp = NULL;
+
+ if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dir_iter, &dent, NULL, NULL))
+ break;
+
+ if (dent == NULL)
+ break;
+
+ /* We ignore non-dotfiles and .timestamps as they are not tempfiles */
+ if (dent->d_name[0] != '.' ||
+ strcmp (dent->d_name, ".timestamp") == 0)
+ continue;
+
+ /* Check for right types and names. The format we’re looking for is:
+ * .[0-9a-f]{64}-[0-9A-Z]{6} */
+ if (dent->d_type == DT_DIR)
+ {
+ if (strlen (dent->d_name) != 72 ||
+ dent->d_name[65] != '-')
+ continue;
+ }
+ else
+ continue;
+
+ /* Check that the file is at least a day old to avoid races */
+ if (!glnx_fstatat (dir_iter.fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW, NULL))
+ continue;
+
+ if (stbuf.st_mtime >= now ||
+ now - stbuf.st_mtime < SECS_PER_DAY)
+ continue;
+
+ tmp = g_file_get_child (dir, dent->d_name);
+
+ /* We ignore errors here, no need to worry anyone */
+ g_debug ("Deleting stale deploy tmpdir %s", flatpak_file_get_path_cached (tmp));
+ (void)flatpak_rm_rf (tmp, NULL, NULL);
+ }
+}
+
gboolean
flatpak_dir_deploy_appstream (FlatpakDir *self,
const char *remote,
@@ -8571,6 +8631,12 @@ flatpak_dir_deploy (FlatpakDir *self,
if (!glnx_opendirat (AT_FDCWD, flatpak_file_get_path_cached (deploy_base), TRUE, &deploy_base_dfd, error))
return FALSE;
+ /* There used to be a bug here where temporary files beneath @deploy_base were not removed,
+ * which could use quite a lot of space over time, so we check for these and remove them.
+ * We only do so for the current app to avoid every deploy operation iterating over
+ * every app directory and all their immediate descendents. That would be a bit much I/O. */
+ remove_old_deploy_tmpdirs (deploy_base);
+
if (checksum_or_latest == NULL)
{
g_debug ("No checksum specified, getting tip of %s from origin %s", flatpak_decomposed_get_ref (ref), origin);