commit bfb5ee0b7372ae375143b9dee5552b8bec26cf05 from: Stefan Sperling via: Thomas Adam date: Tue May 31 23:14:47 2022 UTC open temporary files needed for delta application in got_repo_open() This prepares for callers of got_repo_open() that cannot afford to open files in /tmp, such as gotwebd. In a follow-up change, we could ask such callers to pass in the required amount of open temporary files. One consequence is that got_repo_open() now requires the "cpath" pledge promise. Add the "cpath" promise to affected callers and remove it once the repository has been opened. ok tracey commit - 6c85883bcc71c13fe4fa5bfba2ddf30edabc92b9 commit + bfb5ee0b7372ae375143b9dee5552b8bec26cf05 blob - fec8b481e755f21aca6e7edbd64d43e009c1a558 blob + a31f890564b5e9f199d3c82b30a741bd8cce2236 --- got/got.c +++ got/got.c @@ -5845,15 +5845,9 @@ cmd_ref(int argc, char *argv[]) got_path_strip_trailing_slashes(refname); #ifndef PROFILE - if (do_list) { - if (pledge("stdio rpath wpath flock proc exec sendfd unveil", - NULL) == -1) - err(1, "pledge"); - } else { - if (pledge("stdio rpath wpath cpath fattr flock proc exec " - "sendfd unveil", NULL) == -1) - err(1, "pledge"); - } + if (pledge("stdio rpath wpath cpath fattr flock proc exec " + "sendfd unveil", NULL) == -1) + err(1, "pledge"); #endif cwd = getcwd(NULL, 0); if (cwd == NULL) { @@ -5886,6 +5880,15 @@ cmd_ref(int argc, char *argv[]) error = got_repo_open(&repo, repo_path, NULL); if (error != NULL) goto done; + +#ifndef PROFILE + if (do_list) { + /* Remove "cpath" promise. */ + if (pledge("stdio rpath wpath flock proc exec sendfd unveil", + NULL) == -1) + err(1, "pledge"); + } +#endif error = apply_unveil(got_repo_get_path(repo), do_list, worktree ? got_worktree_get_root_path(worktree) : NULL); @@ -6213,15 +6216,9 @@ cmd_branch(int argc, char *argv[]) usage_branch(); #ifndef PROFILE - if (do_list || do_show) { - if (pledge("stdio rpath wpath flock proc exec sendfd unveil", - NULL) == -1) - err(1, "pledge"); - } else { - if (pledge("stdio rpath wpath cpath fattr flock proc exec " - "sendfd unveil", NULL) == -1) - err(1, "pledge"); - } + if (pledge("stdio rpath wpath cpath fattr flock proc exec " + "sendfd unveil", NULL) == -1) + err(1, "pledge"); #endif cwd = getcwd(NULL, 0); if (cwd == NULL) { @@ -6254,6 +6251,15 @@ cmd_branch(int argc, char *argv[]) error = got_repo_open(&repo, repo_path, NULL); if (error != NULL) goto done; + +#ifndef PROFILE + if (do_list || do_show) { + /* Remove "cpath" promise. */ + if (pledge("stdio rpath wpath flock proc exec sendfd unveil", + NULL) == -1) + err(1, "pledge"); + } +#endif error = apply_unveil(got_repo_get_path(repo), do_list, worktree ? got_worktree_get_root_path(worktree) : NULL); @@ -6756,15 +6762,9 @@ cmd_tag(int argc, char *argv[]) tag_name = argv[0]; #ifndef PROFILE - if (do_list) { - if (pledge("stdio rpath wpath flock proc exec sendfd unveil", - NULL) == -1) - err(1, "pledge"); - } else { - if (pledge("stdio rpath wpath cpath fattr flock proc exec " - "sendfd unveil", NULL) == -1) - err(1, "pledge"); - } + if (pledge("stdio rpath wpath cpath fattr flock proc exec " + "sendfd unveil", NULL) == -1) + err(1, "pledge"); #endif cwd = getcwd(NULL, 0); if (cwd == NULL) { @@ -6803,6 +6803,12 @@ cmd_tag(int argc, char *argv[]) error = got_repo_open(&repo, repo_path, NULL); if (error != NULL) goto done; +#ifndef PROFILE + /* Remove "cpath" promise. */ + if (pledge("stdio rpath wpath flock proc exec sendfd unveil", + NULL) == -1) + err(1, "pledge"); +#endif error = apply_unveil(got_repo_get_path(repo), 1, NULL); if (error) goto done; @@ -12109,7 +12115,7 @@ cmd_info(int argc, char *argv[]) argv += optind; #ifndef PROFILE - if (pledge("stdio rpath wpath flock proc exec sendfd unveil", + if (pledge("stdio rpath wpath cpath flock proc exec sendfd unveil", NULL) == -1) err(1, "pledge"); #endif @@ -12126,6 +12132,12 @@ cmd_info(int argc, char *argv[]) goto done; } +#ifndef PROFILE + /* Remove "cpath" promise. */ + if (pledge("stdio rpath wpath flock proc exec sendfd unveil", + NULL) == -1) + err(1, "pledge"); +#endif error = apply_unveil(NULL, 0, got_worktree_get_root_path(worktree)); if (error) goto done; blob - 1834caf43b755826f1f69c5bb7145897b24be016 blob + 46dde67bc1a81fb350b49f982708b80abf6294ec --- gotadmin/gotadmin.c +++ gotadmin/gotadmin.c @@ -294,7 +294,7 @@ cmd_info(int argc, char *argv[]) argv += optind; #ifndef PROFILE - if (pledge("stdio rpath wpath flock proc exec sendfd unveil", + if (pledge("stdio rpath wpath cpath flock proc exec sendfd unveil", NULL) == -1) err(1, "pledge"); #endif @@ -306,7 +306,12 @@ cmd_info(int argc, char *argv[]) error = got_repo_open(&repo, repo_path, NULL); if (error) goto done; - +#ifndef PROFILE + /* Remove "cpath" promise. */ + if (pledge("stdio rpath wpath flock proc exec sendfd unveil", + NULL) == -1) + err(1, "pledge"); +#endif error = apply_unveil(got_repo_get_path_git_dir(repo), 1); if (error) goto done; @@ -962,14 +967,19 @@ cmd_listpack(int argc, char *argv[]) return got_error_from_errno2("realpath", argv[0]); #ifndef PROFILE - if (pledge("stdio rpath wpath flock proc exec sendfd unveil", + if (pledge("stdio rpath wpath cpath flock proc exec sendfd unveil", NULL) == -1) err(1, "pledge"); #endif error = got_repo_open(&repo, packfile_path, NULL); if (error) goto done; - +#ifndef PROFILE + /* Remove "cpath" promise. */ + if (pledge("stdio rpath wpath flock proc exec sendfd unveil", + NULL) == -1) + err(1, "pledge"); +#endif error = apply_unveil(got_repo_get_path_git_dir(repo), 1); if (error) goto done; blob - 6a3d3981c9afd96d48ef7746b2d0b1d78793a7ca blob + 0aed8754f53747ab02a5563d0a6435959c59c3d4 --- lib/got_lib_pack.h +++ lib/got_lib_pack.h @@ -21,6 +21,8 @@ struct got_pack { uint8_t *map; size_t filesize; struct got_privsep_child *privsep_child; + int basefd; + int accumfd; int child_has_tempfiles; int child_has_delta_outfd; struct got_delta_cache *delta_cache; blob - b05bed22da08811e69f54f677e5b4db823c50880 blob + 8d596caed3e5d0695957bd0d1facae2d31f8e008 --- lib/object.c +++ lib/object.c @@ -170,7 +170,7 @@ static const struct got_error * pack_child_send_tempfiles(struct imsgbuf *ibuf, struct got_pack *pack) { const struct got_error *err; - int basefd, accumfd; + int basefd = -1, accumfd = -1; /* * For performance reasons, the child will keep reusing the @@ -181,23 +181,29 @@ pack_child_send_tempfiles(struct imsgbuf *ibuf, struct if (pack->child_has_tempfiles) return NULL; - basefd = got_opentempfd(); + basefd = dup(pack->basefd); if (basefd == -1) - return got_error_from_errno("got_opentempfd"); + return got_error_from_errno("dup"); + accumfd = dup(pack->accumfd); + if (accumfd == -1) { + err = got_error_from_errno("dup"); + goto done; + } + err = got_privsep_send_tmpfd(ibuf, basefd); if (err) - return err; - - accumfd = got_opentempfd(); - if (accumfd == -1) - return got_error_from_errno("got_opentempfd"); + goto done; err = got_privsep_send_tmpfd(ibuf, accumfd); - if (err) - return err; - - pack->child_has_tempfiles = 1; +done: + if (err) { + if (basefd != -1) + close(basefd); + if (accumfd != -1) + close(accumfd); + } else + pack->child_has_tempfiles = 1; return NULL; } blob - 63393465efc849fc14e7a08eb628b52349ce399d blob + fb0db87c32da83d311bda6a69b946e48e3167f8f --- lib/pack.c +++ lib/pack.c @@ -747,6 +747,11 @@ got_pack_close(struct got_pack *pack) pack->delta_cache = NULL; } + /* + * Leave accumfd and basefd alone. They are managed by the + * repository layer and can be reused. + */ + return err; } blob - 31a38d9c9f4614918f6f64bde0b2bc151f0927f9 blob + 3fb28c2a556b23e57fb4c7d68445fa22cec08f52 --- lib/repository.c +++ lib/repository.c @@ -44,6 +44,7 @@ #include "got_path.h" #include "got_cancel.h" #include "got_object.h" +#include "got_opentemp.h" #include "got_lib_delta.h" #include "got_lib_inflate.h" @@ -694,6 +695,19 @@ got_repo_open(struct got_repository **repop, const cha repo->pack_cache_size = GOT_PACK_CACHE_SIZE; if (repo->pack_cache_size > rl.rlim_cur / 8) repo->pack_cache_size = rl.rlim_cur / 8; + for (i = 0; i < nitems(repo->packs); i++) { + if (i < repo->pack_cache_size) { + repo->packs[i].basefd = got_opentempfd(); + if (repo->packs[i].basefd == -1) + return got_error_from_errno("got_opentempfd"); + repo->packs[i].accumfd = got_opentempfd(); + if (repo->packs[i].accumfd == -1) + return got_error_from_errno("got_opentempfd"); + } else { + repo->packs[i].basefd = -1; + repo->packs[i].accumfd = -1; + } + } repo_path = realpath(path, NULL); if (repo_path == NULL) { @@ -780,6 +794,16 @@ got_repo_close(struct got_repository *repo) if (repo->packs[i].path_packfile == NULL) break; got_pack_close(&repo->packs[i]); + if (repo->packs[i].basefd != -1) { + if (close(repo->packs[i].basefd) == -1 && err == NULL) + err = got_error_from_errno("close"); + repo->packs[i].basefd = -1; + } + if (repo->packs[i].accumfd != -1) { + if (close(repo->packs[i].accumfd) == -1 && err == NULL) + err = got_error_from_errno("close"); + repo->packs[i].accumfd = -1; + } } free(repo->path); @@ -1321,6 +1345,10 @@ got_repo_cache_pack(struct got_pack **packp, struct go err = got_pack_close(&repo->packs[i - 1]); if (err) return err; + if (ftruncate(repo->packs[i - 1].basefd, 0L) == -1) + return got_error_from_errno("ftruncate"); + if (ftruncate(repo->packs[i - 1].accumfd, 0L) == -1) + return got_error_from_errno("ftruncate"); memmove(&repo->packs[1], &repo->packs[0], sizeof(repo->packs) - sizeof(repo->packs[0])); i = 0;