commit 520c3a1027335708828e2c249ae51b3363db99f0
parent acd516d2f9716356b7c3c7a9717877ed02ec5549
Author: Nihal Jere <nihal@nihaljere.xyz>
Date: Mon, 22 Feb 2021 17:55:12 -0600
alt.*: add alt_swap
Diffstat:
M | alt.c | | | 56 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | alt.h | | | 1 | + |
2 files changed, 57 insertions(+), 0 deletions(-)
diff --git a/alt.c b/alt.c
@@ -160,3 +160,59 @@ alt_owner(char owner[PKG_NAME_MAX], char *path)
closedir(installed);
}
+
+void
+alt_swap(struct alt_t *in)
+{
+ struct alt_t out;
+ memset(&out, 0, sizeof(out));
+ char choice[PATH_LEN], out_choice_path[PATH_LEN], in_choice_path[PATH_LEN],
+ out_manifest[PATH_LEN], in_manifest[PATH_LEN];
+ int n;
+
+ alt_owner(out.name, in->path);
+ if (!out.name[0])
+ die("%s: %s doesn't belong to a package", __func__, in->path);
+
+ strcpy(out.path, in->path);
+
+ to_choice(&out, choice);
+ n = snprintf(out_choice_path, PATH_LEN, "%s/%s", KISS_CHOICES, choice);
+ if (n >= PATH_LEN)
+ die("%s: full path for %s too long", __func__, choice);
+
+ to_choice(in, choice);
+ n = snprintf(in_choice_path, PATH_LEN, "%s/%s", KISS_CHOICES, choice);
+ if (n >= PATH_LEN)
+ die("%s: full path for %s too long", __func__, choice);
+
+ n = snprintf(out_manifest, PATH_LEN, "%s/%s/manifest", KISS_INSTALLED, out.name);
+ if (n >= PATH_LEN)
+ die("%s: full manifest path for %s too long", __func__, out.name);
+
+ n = snprintf(in_manifest, PATH_LEN, "%s/%s/manifest", KISS_INSTALLED, in->name);
+ if (n >= PATH_LEN)
+ die("%s: full manifest path for %s too long", __func__, in->name);
+
+ /* TODO use goto for error handling */
+ if (mv(out.path, out_choice_path) == -1)
+ die("%s: failed to swap out %s:", __func__, out.name);
+
+ if (mv(in_choice_path, in->path) == -1) {
+ mv(out_choice_path, out.path);
+ die("%s: failed to swap in %s:", __func__, in->name);
+ }
+
+ if (file_dropadd(out_manifest, out.path, out_choice_path) == -1) {
+ mv(in->path, in_choice_path);
+ mv(out_choice_path, out.path);
+ die("%s: failed to update manifest for %s; it might be screwed up:", __func__, in->name);
+ }
+
+ if (file_dropadd(in_manifest, in_choice_path, in->path) == -1) {
+ file_dropadd(out_manifest, out_choice_path, out.path);
+ mv(in->path, in_choice_path);
+ mv(out_choice_path, out.path);
+ die("%s: failed to update manifest for %s; it might be screwed up:", __func__, out.name);
+ }
+}
diff --git a/alt.h b/alt.h
@@ -9,3 +9,4 @@ struct alt_t {
void alt_load();
int alt_exists(struct alt_t *alt);
void alt_owner(char owner[PKG_NAME_MAX], char *path);
+void alt_swap(struct alt_t *new);