summaryrefslogtreecommitdiffstats
path: root/lib/libalpm/be_local.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm/be_local.c')
-rw-r--r--lib/libalpm/be_local.c40
1 files changed, 35 insertions, 5 deletions
diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c
index 36b2c5dc..137da1a8 100644
--- a/lib/libalpm/be_local.c
+++ b/lib/libalpm/be_local.c
@@ -907,14 +907,44 @@ cleanup:
int _alpm_local_db_remove(alpm_db_t *db, alpm_pkg_t *info)
{
int ret = 0;
- char *pkgpath = _alpm_local_db_pkgpath(db, info, NULL);
+ DIR *dirp;
+ struct dirent *dp;
+ char *pkgpath;
+ size_t pkgpath_len;
- /* TODO explicit file removes and then an rmdir? */
- ret = _alpm_rmrf(pkgpath);
- free(pkgpath);
- if(ret != 0) {
+ pkgpath = _alpm_local_db_pkgpath(db, info, NULL);
+ if(!pkgpath) {
+ return -1;
+ }
+ pkgpath_len = strlen(pkgpath);
+
+ dirp = opendir(pkgpath);
+ if(!dirp) {
+ return -1;
+ }
+ /* go through the local DB entry, removing the files within, which we know
+ * are not nested directories of any kind. */
+ for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
+ if(strcmp(dp->d_name, "..") != 0 && strcmp(dp->d_name, ".") != 0) {
+ char name[PATH_MAX];
+ if(pkgpath_len + strlen(dp->d_name) + 2 > PATH_MAX) {
+ /* file path is too long to remove, hmm. */
+ ret = -1;
+ } else {
+ sprintf(name, "%s/%s", pkgpath, dp->d_name);
+ if(unlink(name)) {
+ ret = -1;
+ }
+ }
+ }
+ }
+ closedir(dirp);
+
+ /* after removing all enclosed files, we can remove the directory itself. */
+ if(rmdir(pkgpath)) {
ret = -1;
}
+ free(pkgpath);
return ret;
}