-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathremove.c
145 lines (128 loc) · 5.18 KB
/
remove.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/**
* this file is part of kawa
* Copyright (c) 2020-2021 Emily <elishikawa@jagudev.net>
*
* kawa is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* kawa is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with kawa. If not, see <https://www.gnu.org/licenses/>.
**/
#include "remove.h"
int pkg_remove(int pkgc, char *pkgnames[]) {
struct pkglist *database = get_all_packages();
struct pkglist *installed = get_installed_packages();
// check if packages *can* be uninstalled
for (int i = 2; i < pkgc; i++) {
int package_installed = 0;
for (int i2 = 0; i2 < installed->pkg_count; i2++) {
if (!strcmp(pkgnames[i], installed->packages[i2]->name)) {
package_installed = 1;
break;
}
}
if (!package_installed) {
fprintf(stderr, "\nError: package %s is not installed\n", pkgnames[i]);
return 1;
}
}
char has_essential = 0;
char *first_essential = NULL;
for (int i = 2; i < pkgc; i++) {
for (int i2 = 0; ESSENTIALPACKAGES[i2] != NULL; i2++) {
if (!strcmp(pkgnames[i], ESSENTIALPACKAGES[i2])) {
has_essential = 1;
first_essential = pkgnames[i];
break;
}
}
if (has_essential)
break;
}
if (has_essential) {
printf("\nAttempted to remove essential package %s.\nThis is a VERY dangerous action that will leave you with something anywhere from a major headache to a bricked system. To confirm that you are okay with this and know exactly what you are doing, please type \"Yes, do as I say.\" and press Enter.\n>>> ", first_essential);
fflush(stdout);
char input[46];
fgets(input, 46, stdin);
if (strcmp(input, "Yes, do as I say.\n")) {
printf("Non-confirmative input received. Aborting.\n");
exit(0);
}
}
printf("\nThe following packages will be removed:\n ");
for (int i = 2; i < pkgc; i++) {
printf(" %s", pkgnames[i]);
}
printf("\n\n%d package(s) will be installed, %d package(s) will be removed and %d package(s) will be updated.\n", 0, pkgc-2, 0);
printf("Do you wish to proceed? [Y/n] ");
fflush(stdout);
char response = getchar();
if (response == 'n' || response == 'N')
return 0;
else if (response == 'y' || response == 'Y' || response == '\n') {
int retval = 0;
// remove requested packages
for (int i = 2; i < pkgc; i++) {
retval += remove_single(pkgnames[i], installed, database);
}
retval += write_installed_packages(installed, database);
return retval;
} else
return 1;
return 0;
}
int remove_single(char pkgname[], struct pkglist *installed, struct pkglist *database) {
struct package *currpkg;
int *i;
if (!(i = malloc(sizeof(int)))) malloc_fail();
currpkg = bsearch_pkg(pkgname, installed, i, 0);
free(i);
struct package *currpkg_db;
if (!(i = malloc(sizeof(int)))) malloc_fail();
currpkg_db = bsearch_pkg(pkgname, database, i, 0);
free(i);
int retval = 1;
// remove the package using the function provided by the package type class
// use database version because of the way metapkg handle dependency removal
if (!strcmp(currpkg->type, "source"))
retval = sourcepkg_remove(currpkg_db);
else if (!strcmp(currpkg->type, "patch"))
retval = patchpkg_remove(currpkg_db);
else if (!strcmp(currpkg->type, "meta"))
retval = metapkg_remove(currpkg_db);
else if (!strcmp(currpkg->type, "binary"))
retval = binarypkg_remove(pkgname);
if (!retval) {
// unregister package
remove_db_entry(currpkg, installed);
kawafile_dir_remove(currpkg);
} else {
fprintf(stderr, "\nThere were errors during the removal of %s. Aborting.\n", pkgname);
exit(retval);
}
return retval;
}
void remove_db_entry(struct package *package, struct pkglist *installed) {
// we're just removing (and free-ing, hopefully this won't cause problems later (spoiler alert: it did))
// the pointer to the package in *installed, and at the end we'll re-write Installed.packages.db
struct package *currpkg;
for (int i = 0; i < installed->pkg_count; i++) {
currpkg = installed->packages[i];
// we're comparing pointers, so this (should) work(s).
if (currpkg == package) {
// retain installed database consistency for multi-package operations
for (i++; i < installed->pkg_count; i++) {
installed->packages[i - 1] = installed->packages[i];
}
break;
// free(package); caused problems
}
}
}