Misc cleanups and performance improvements.
- There's no need to check rval for prop_dictionary_get_*, we are sure the objects are there at prop_dictionary_set_* time. - Avoid two chdir(2) calls per INSTALL/REMOVE run. - Avoid using access(2) to check for existence of INSTALL/REMOVE scripts, just try to run the executable directly and check for ENOENT.
This commit is contained in:
@ -29,6 +29,7 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include <xbps_api.h>
|
||||
|
||||
@ -75,8 +76,8 @@ xbps_remove_pkg_files(prop_dictionary_t dict, const char *key)
|
||||
prop_array_t array;
|
||||
prop_object_iterator_t iter;
|
||||
prop_object_t obj;
|
||||
const char *file, *sha256;
|
||||
char *path = NULL;
|
||||
const char *file, *sha256, *curobj = NULL;
|
||||
char *dname = NULL, *path = NULL;
|
||||
int flags = 0, rv = 0;
|
||||
|
||||
assert(dict != NULL);
|
||||
@ -92,11 +93,17 @@ xbps_remove_pkg_files(prop_dictionary_t dict, const char *key)
|
||||
if (iter == NULL)
|
||||
return errno;
|
||||
|
||||
if (strcmp(key, "files") == 0)
|
||||
curobj = "file";
|
||||
else if (strcmp(key, "conf_files") == 0)
|
||||
curobj = "configuration file";
|
||||
else if (strcmp(key, "links") == 0)
|
||||
curobj = "link";
|
||||
else if (strcmp(key, "dirs") == 0)
|
||||
curobj = "directory";
|
||||
|
||||
while ((obj = prop_object_iterator_next(iter))) {
|
||||
if (!prop_dictionary_get_cstring_nocopy(obj, "file", &file)) {
|
||||
rv = errno;
|
||||
break;
|
||||
}
|
||||
prop_dictionary_get_cstring_nocopy(obj, "file", &file);
|
||||
path = xbps_xasprintf("%s/%s", xbps_get_rootdir(), file);
|
||||
if (path == NULL) {
|
||||
rv = errno;
|
||||
@ -108,12 +115,8 @@ xbps_remove_pkg_files(prop_dictionary_t dict, const char *key)
|
||||
* Check SHA256 hash in regular files and
|
||||
* configuration files.
|
||||
*/
|
||||
if (!prop_dictionary_get_cstring_nocopy(obj,
|
||||
"sha256", &sha256)) {
|
||||
free(path);
|
||||
rv = errno;
|
||||
break;
|
||||
}
|
||||
prop_dictionary_get_cstring_nocopy(obj,
|
||||
"sha256", &sha256);
|
||||
rv = xbps_check_file_hash(path, sha256);
|
||||
if (rv == ENOENT) {
|
||||
fprintf(stderr,
|
||||
@ -144,38 +147,40 @@ xbps_remove_pkg_files(prop_dictionary_t dict, const char *key)
|
||||
free(path);
|
||||
break;
|
||||
}
|
||||
} else if (strcmp(key, "dirs") == 0) {
|
||||
if ((rv = rmdir(path)) == -1) {
|
||||
rv = 0;
|
||||
if (errno == ENOTEMPTY) {
|
||||
free(path);
|
||||
continue;
|
||||
}
|
||||
if (flags & XBPS_FLAG_VERBOSE) {
|
||||
fprintf(stderr,
|
||||
"WARNING: can't remove "
|
||||
"directory %s (%s)\n", file,
|
||||
strerror(errno));
|
||||
free(path);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (strcmp(key, "dirs")) {
|
||||
if ((rv = remove(path)) == -1) {
|
||||
/*
|
||||
* Remove the object if possible.
|
||||
*/
|
||||
if (remove(path) == -1) {
|
||||
if (flags & XBPS_FLAG_VERBOSE)
|
||||
fprintf(stderr,
|
||||
"WARNING: can't remove %s %s "
|
||||
"(%s)\n", curobj, file, strerror(errno));
|
||||
|
||||
} else {
|
||||
/* Success */
|
||||
if (flags & XBPS_FLAG_VERBOSE)
|
||||
printf("Removed %s: %s\n", curobj, file);
|
||||
}
|
||||
/*
|
||||
* When purging a package, also remove the directory where
|
||||
* the conf_files are living on.
|
||||
*/
|
||||
if (strcmp(key, "conf_files") == 0) {
|
||||
dname = dirname(path);
|
||||
if (rmdir(dname) == -1) {
|
||||
if (errno != ENOTEMPTY) {
|
||||
fprintf(stderr,
|
||||
"WARNING: can't remove %s %s "
|
||||
"(%s)\n", curobj, file,
|
||||
strerror(errno));
|
||||
}
|
||||
} else {
|
||||
if (flags & XBPS_FLAG_VERBOSE)
|
||||
fprintf(stderr,
|
||||
"WARNING: can't remove %s "
|
||||
"(%s)\n", file, strerror(errno));
|
||||
|
||||
rv = 0;
|
||||
free(path);
|
||||
continue;
|
||||
printf("Removed empty directory: "
|
||||
"%s\n", dname);
|
||||
}
|
||||
}
|
||||
if (flags & XBPS_FLAG_VERBOSE)
|
||||
printf("Removed: %s\n", file);
|
||||
|
||||
free(path);
|
||||
}
|
||||
prop_object_iterator_release(iter);
|
||||
@ -187,10 +192,8 @@ int
|
||||
xbps_remove_pkg(const char *pkgname, const char *version, bool update)
|
||||
{
|
||||
prop_dictionary_t dict;
|
||||
const char *rootdir = xbps_get_rootdir();
|
||||
char *path, *buf;
|
||||
int rv = 0;
|
||||
bool prepostf = false;
|
||||
|
||||
assert(pkgname != NULL);
|
||||
assert(version != NULL);
|
||||
@ -201,34 +204,27 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
|
||||
if (!xbps_check_is_installed_pkgname(pkgname))
|
||||
return ENOENT;
|
||||
|
||||
if (strcmp(rootdir, "") == 0)
|
||||
rootdir = "/";
|
||||
|
||||
if (chdir(rootdir) == -1)
|
||||
return errno;
|
||||
|
||||
buf = xbps_xasprintf(".%s/metadata/%s/REMOVE",
|
||||
XBPS_META_PATH, pkgname);
|
||||
if (buf == NULL)
|
||||
return errno;
|
||||
|
||||
if (chdir(xbps_get_rootdir()) == -1) {
|
||||
free(buf);
|
||||
return errno;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find out if the REMOVE file exists.
|
||||
* Run the pre remove action.
|
||||
*/
|
||||
if (access(buf, X_OK) == 0) {
|
||||
/*
|
||||
* Run the pre remove action.
|
||||
*/
|
||||
prepostf = true;
|
||||
rv = xbps_file_chdir_exec(rootdir, buf, "pre", pkgname,
|
||||
version, update ? "yes" : "no", NULL);
|
||||
if (rv != 0) {
|
||||
fprintf(stderr,
|
||||
"%s: prerm action target error (%s)\n", pkgname,
|
||||
strerror(errno));
|
||||
free(buf);
|
||||
return rv;
|
||||
}
|
||||
rv = xbps_file_exec(buf, "pre", pkgname, version,
|
||||
update ? "yes" : "no", NULL);
|
||||
if (rv != 0 && errno != ENOENT) {
|
||||
fprintf(stderr,
|
||||
"%s: prerm action target error (%s)\n", pkgname,
|
||||
strerror(errno));
|
||||
free(buf);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -244,55 +240,51 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
|
||||
/*
|
||||
* Remove links, files and dirs.
|
||||
*/
|
||||
path = xbps_xasprintf("%s/%s/metadata/%s/%s",
|
||||
rootdir, XBPS_META_PATH, pkgname, XBPS_PKGFILES);
|
||||
path = xbps_xasprintf(".%s/metadata/%s/%s",
|
||||
XBPS_META_PATH, pkgname, XBPS_PKGFILES);
|
||||
if (path == NULL) {
|
||||
free(buf);
|
||||
return errno;
|
||||
}
|
||||
|
||||
dict = prop_dictionary_internalize_from_zfile(path);
|
||||
if (dict == NULL) {
|
||||
free(buf);
|
||||
free(path);
|
||||
free(buf);
|
||||
return errno;
|
||||
}
|
||||
free(path);
|
||||
|
||||
/* Remove links */
|
||||
if ((rv = xbps_remove_pkg_files(dict, "links")) != 0) {
|
||||
free(buf);
|
||||
prop_object_release(dict);
|
||||
free(buf);
|
||||
return rv;
|
||||
}
|
||||
/* Remove regular files */
|
||||
if ((rv = xbps_remove_pkg_files(dict, "files")) != 0) {
|
||||
free(buf);
|
||||
prop_object_release(dict);
|
||||
free(buf);
|
||||
return rv;
|
||||
}
|
||||
/* Remove dirs */
|
||||
if ((rv = xbps_remove_pkg_files(dict, "dirs")) != 0) {
|
||||
free(buf);
|
||||
prop_object_release(dict);
|
||||
free(buf);
|
||||
return rv;
|
||||
}
|
||||
prop_object_release(dict);
|
||||
|
||||
/*
|
||||
* Run the post remove action if REMOVE file is there
|
||||
* and we aren't updating a package.
|
||||
* Execute the post REMOVE action if file exists and we aren't
|
||||
* updating the package.
|
||||
*/
|
||||
if (update == false && prepostf) {
|
||||
rv = xbps_file_chdir_exec(rootdir, buf, "post",
|
||||
pkgname, version, NULL);
|
||||
if (rv != 0) {
|
||||
fprintf(stderr,
|
||||
"%s: postrm action target error (%s)\n",
|
||||
pkgname, strerror(errno));
|
||||
free(buf);
|
||||
return rv;
|
||||
}
|
||||
rv = xbps_file_exec(buf, "post", pkgname, version, "no", NULL);
|
||||
if (rv != 0 && errno != ENOENT) {
|
||||
fprintf(stderr,
|
||||
"%s: postrm action target error (%s)\n", pkgname,
|
||||
strerror(errno));
|
||||
free(buf);
|
||||
return rv;
|
||||
}
|
||||
free(buf);
|
||||
|
||||
|
Reference in New Issue
Block a user