summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan McGee <dan@archlinux.org>2012-02-29 15:51:54 -0600
committerDan McGee <dan@archlinux.org>2012-03-05 11:44:33 -0600
commitd1151b5ab9c407732ded462a0fe0259dea8dcc2a (patch)
treed693ec6f216e9b4d149cc48cd7bdfaf32394d66d
parent78adb71f20ee335dff49e34d33f04817a40002b6 (diff)
downloadpacman-d1151b5ab9c407732ded462a0fe0259dea8dcc2a.tar.xz
Database cleanup enhancements
Ensure we give database signatures special treatment like we already did for package signatures. Attempt to parse the database name out of them before taking the proper steps to handle their existence. This fixes FS#28714. We also add an unlink_verbose() helper method that displays any errors that occur when unlinking, optionally opting to skip any ENOENT errors from being fatal. Finally, the one prompt per unknown database has been removed, this has no real sound purpose and we don't do this for packages. Simply kill databases we don't know about; other programs shouldn't have random data in this directory anyway. Signed-off-by: Dan McGee <dan@archlinux.org>
-rw-r--r--src/pacman/sync.c71
1 files changed, 45 insertions, 26 deletions
diff --git a/src/pacman/sync.c b/src/pacman/sync.c
index fcc887ae..a9a9e99c 100644
--- a/src/pacman/sync.c
+++ b/src/pacman/sync.c
@@ -25,6 +25,7 @@
#include <string.h>
#include <limits.h>
#include <unistd.h>
+#include <errno.h>
#include <dirent.h>
#include <sys/stat.h>
@@ -37,6 +38,20 @@
#include "package.h"
#include "conf.h"
+static int unlink_verbose(const char *pathname, int ignore_missing)
+{
+ int ret = unlink(pathname);
+ if(ret) {
+ if(ignore_missing && errno == ENOENT) {
+ ret = 0;
+ } else {
+ pm_printf(ALPM_LOG_ERROR, _("could not remove %s: %s\n"),
+ pathname, strerror(errno));
+ }
+ }
+ return ret;
+}
+
/* if keep_used != 0, then the db files which match an used syncdb
* will be kept */
static int sync_cleandb(const char *dbpath, int keep_used)
@@ -44,6 +59,7 @@ static int sync_cleandb(const char *dbpath, int keep_used)
DIR *dir;
struct dirent *ent;
alpm_list_t *syncdbs;
+ int ret = 0;
dir = opendir(dbpath);
if(dir == NULL) {
@@ -60,6 +76,7 @@ static int sync_cleandb(const char *dbpath, int keep_used)
struct stat buf;
int found = 0;
const char *dname = ent->d_name;
+ char *dbname;
size_t len;
if(strcmp(dname, ".") == 0 || strcmp(dname, "..") == 0) {
@@ -79,44 +96,46 @@ static int sync_cleandb(const char *dbpath, int keep_used)
/* remove all non-skipped directories and non-database files */
stat(path, &buf);
- len = strlen(path);
- if(S_ISDIR(buf.st_mode) || strcmp(path + len - 3, ".db") != 0) {
+ if(S_ISDIR(buf.st_mode)) {
if(rmrf(path)) {
- pm_printf(ALPM_LOG_ERROR,
- _("could not remove %s\n"), path);
- closedir(dir);
- return 1;
+ pm_printf(ALPM_LOG_ERROR, _("could not remove %s: %s\n"),
+ path, strerror(errno));
}
continue;
}
+ len = strlen(dname);
+ if(len > 3 && strcmp(dname + len - 3, ".db") == 0) {
+ dbname = strndup(dname, len - 3);
+ } else if(len > 7 && strcmp(dname + len - 7, ".db.sig") == 0) {
+ dbname = strndup(dname, len - 7);
+ } else {
+ ret += unlink_verbose(path, 0);
+ continue;
+ }
+
if(keep_used) {
alpm_list_t *i;
- len = strlen(dname);
- char *dbname = strndup(dname, len - 3);
for(i = syncdbs; i && !found; i = alpm_list_next(i)) {
alpm_db_t *db = alpm_list_getdata(i);
found = !strcmp(dbname, alpm_db_get_name(db));
}
- free(dbname);
}
- /* We have a database that doesn't match any syncdb.
- * Ask the user if he wants to remove it. */
- if(!found) {
- if(!yesno(_("Do you want to remove %s?"), path)) {
- continue;
- }
- if(rmrf(path)) {
- pm_printf(ALPM_LOG_ERROR,
- _("could not remove %s\n"), path);
- closedir(dir);
- return 1;
- }
+ /* We have a database that doesn't match any syncdb. */
+ if(!found) {
+ /* ENOENT check is because the signature and database could come in any
+ * order in our readdir() call, so either file may already be gone. */
+ snprintf(path, PATH_MAX, "%s%s.db", dbpath, dbname);
+ ret += unlink_verbose(path, 1);
+ /* unlink a signature file if present too */
+ snprintf(path, PATH_MAX, "%s%s.db.sig", dbpath, dbname);
+ ret += unlink_verbose(path, 1);
}
+ free(dbname);
}
closedir(dir);
- return 0;
+ return ret;
}
static int sync_cleandb_all(void)
@@ -130,6 +149,7 @@ static int sync_cleandb_all(void)
if(!yesno(_("Do you want to remove unused repositories?"))) {
return 0;
}
+ printf(_("removing unused sync repositories...\n"));
/* The sync dbs were previously put in dbpath/ but are now in dbpath/sync/.
* We will clean everything in dbpath/ except local/, sync/ and db.lck, and
* only the unused sync dbs in dbpath/sync/ */
@@ -142,7 +162,6 @@ static int sync_cleandb_all(void)
ret += sync_cleandb(newdbpath, 1);
free(newdbpath);
- printf(_("Database directory cleaned up\n"));
return ret;
}
@@ -210,7 +229,7 @@ static int sync_cleancache(int level)
/* short circuit for removing all files from cache */
if(level > 1) {
- unlink(path);
+ ret += unlink_verbose(path, 0);
continue;
}
@@ -256,11 +275,11 @@ static int sync_cleancache(int level)
if(delete) {
size_t pathlen = strlen(path);
- unlink(path);
+ ret += unlink_verbose(path, 0);
/* unlink a signature file if present too */
if(PATH_MAX - 5 >= pathlen) {
strcpy(path + pathlen, ".sig");
- unlink(path);
+ ret += unlink_verbose(path, 1);
}
}
}