diff options
author | Philip Withnall <pwithnall@endlessos.org> | 2022-11-03 15:41:39 +0000 |
---|---|---|
committer | Simon McVittie <smcv@debian.org> | 2022-11-16 18:46:01 +0000 |
commit | 9ec783f029a4bd41fb41d8472796c2b10d97ec4c (patch) | |
tree | 8d9c9020b9573fb82fab0246c1f14ac58e371b54 | |
parent | 6c7eb34dd641f1bca29d1e44ac3954898f2ee57c (diff) | |
download | flatpak-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.c | 66 |
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); |