From 00aeb8181190a2f731ea48d52841898d70595778 Mon Sep 17 00:00:00 2001 From: Daniel Barlow Date: Fri, 19 May 2023 23:49:11 +0100 Subject: [PATCH] min-list-garbage: check all store paths against file this is step 1 of min-collect-garbage, no point implementing deletion ourselves when rm -r exists (arguably no point in implementing any of it, but this is the bit we can't do efficiently in bourne shell - it means we're reading the store-paths list once instead of grepping it afresh for every entry in /nix/store/) --- pkgs/min-copy-closure/default.nix | 8 ++- pkgs/min-copy-closure/min-list-garbage.c | 79 ++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 pkgs/min-copy-closure/min-list-garbage.c diff --git a/pkgs/min-copy-closure/default.nix b/pkgs/min-copy-closure/default.nix index f0dcf6b..1e07897 100644 --- a/pkgs/min-copy-closure/default.nix +++ b/pkgs/min-copy-closure/default.nix @@ -8,9 +8,13 @@ buildInputs = [ ]; propagatedBuildInputs = [ cpio openssh nix ]; src = ./.; + makeFlags = [ "min-list-garbage" ]; installPhase = '' mkdir -p $out/bin - cp min-copy-closure.sh $out/bin/min-copy-closure - cp liminix-rebuild.sh $out/bin/liminix-rebuild + for i in min-copy-closure liminix-rebuild; do + echo $i + cp ''${i}.sh $out/bin/$i + done + cp min-list-garbage $out/bin ''; } diff --git a/pkgs/min-copy-closure/min-list-garbage.c b/pkgs/min-copy-closure/min-list-garbage.c new file mode 100644 index 0000000..a260a8b --- /dev/null +++ b/pkgs/min-copy-closure/min-list-garbage.c @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include +#include + +typedef char hash_t[32]; +hash_t *hash_list = NULL; +int hash_list_entries = 0; +int hash_list_size = 0; + +int add_list_entry(char *name) +{ + name += strlen("/nix/store/"); + if(hash_list_entries >= hash_list_size) { + if(hash_list_size == 0) hash_list_size = 4; + hash_list_size = hash_list_size * 2; + hash_list = realloc(hash_list, hash_list_size * sizeof(hash_t)); + } + strncpy(hash_list[hash_list_entries++], name, 32); + printf("%d %d\n", hash_list_entries, hash_list_size); +} + +int read_list(char *filename) +{ + char s[1024]; + FILE *fp; + if(fp = fopen(filename, "r")) { + while(fgets(s, 1024, fp)) { + if(strrchr(s, '\n')) { + add_list_entry(s); + } else { + puts("hash list entry too long"); + exit(1); + } + } + } + fclose(fp); +} + +int on_list(char *name) +{ + int i; + for(i = 0; i < hash_list_entries; i++) { + if(!strncmp(hash_list[i], name, 32)) { + return 1; + } + } + return 0; +} + +int main(int argc, char * argv[]) +{ + struct dirent * de; + DIR * dirp; + char hash[32]; + + if(argc < 2) { + puts("Usage: min-list-garbage store-paths-file\n\nChecks all store paths against the list of expected paths in store-paths-file,\n and prints any which are present unexpectedly"); + exit(1); + } + + read_list(argv[1]); + + if((dirp = opendir("/nix/store")) == NULL) { + puts("can't open /nix/store"); + exit(1); + } + + while(de = readdir(dirp)) { + if(strlen(de->d_name) >= 32) { + strncpy(hash, de->d_name, 32); + if(!on_list(hash)) puts(de->d_name); + } + } + + closedir(dirp); +}