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:
Juan RP
2010-11-06 06:44:00 +01:00
parent f8629652da
commit ec7cdde1e0
22 changed files with 228 additions and 461 deletions

View File

@ -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);