commit 571608344a37fb96f46850a1124415ab68b1a431 from: Stefan Sperling date: Tue May 31 11:00:09 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 - f18c433aae68e5537cf67eae05c0343e970307ad commit + 571608344a37fb96f46850a1124415ab68b1a431 blob - 80e5d2fbcd031246f1194edf450fa9da6e1a2901 blob + cf96009500ac33bb3b660dd7e99902801b0cb975 --- 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 - 471a8ac92d12a89ee0e086f430301d0ca2adb743 blob + 59c11d1ab01684d8a2f16d934fb1d6870d7ac871 --- gotadmin/gotadmin.c +++ gotadmin/gotadmin.c @@ -295,7 +295,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 @@ -307,7 +307,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; @@ -963,14 +968,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 - 2d612890612d7d8a8e30549c38659cd083a2e41e blob + 47175236af75523bec4c9972e40679dcdd6d15f0 --- lib/object.c +++ lib/object.c @@ -172,7 +172,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 @@ -183,23 +183,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 - 2c612a33c5d96977b8bbe4ac08c2fc41cc78381b blob + bbeafedb2d303742ae359d0ab03b005700ed75e2 --- lib/pack.c +++ lib/pack.c @@ -751,6 +751,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 - 7896e9194a183430cbeecf89b54758b1e9b1dc94 blob + f4585bf3d903303171bdbc6a683382e865a425e9 --- lib/repository.c +++ lib/repository.c @@ -50,6 +50,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" @@ -700,6 +701,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) { @@ -786,6 +800,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); @@ -1326,6 +1350,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;