Пример #1
0
int HIDDEN
xbps_pkgdb_init(struct xbps_handle *xhp)
{
	int rv;

	assert(xhp != NULL);

	if (xhp->pkgdb_plist == NULL)
		xhp->pkgdb_plist = xbps_xasprintf("%s/%s", xhp->metadir, XBPS_PKGDB);

#if 0
	if ((rv = xbps_pkgdb_conversion(xhp)) != 0)
		return rv;
#endif

	if (xhp->pkgdb != NULL)
		return 0;

	if ((rv = xbps_pkgdb_update(xhp, false, true)) != 0) {
		if (rv != ENOENT)
			xbps_dbg_printf(xhp, "[pkgdb] cannot internalize "
			    "pkgdb array: %s\n", strerror(rv));

		return rv;
	}
	if ((rv = pkgdb_map_vpkgs(xhp)) != 0) {
		xbps_dbg_printf(xhp, "[pkgdb] pkgdb_map_vpkgs %s\n", strerror(rv));
		return rv;
	}
	assert(xhp->pkgdb);
	xbps_dbg_printf(xhp, "[pkgdb] initialized ok.\n");

	return 0;
}
Пример #2
0
/**
 * @file lib/pkgdb.c
 * @brief Package database handling routines
 * @defgroup pkgdb Package database handling functions
 *
 * Functions to manipulate the main package database plist file (pkgdb).
 *
 * The following image shown below shows the proplib structure used
 * by the main package database plist:
 *
 * @image html images/xbps_pkgdb_array.png
 *
 * Legend:
 *  - <b>Salmon filled box</b>: \a XBPS_PKGDB file internalized.
 *  - <b>White filled box</b>: mandatory objects.
 *  - <b>Grey filled box</b>: optional objects.
 *  - <b>Green filled box</b>: possible value set in the object, only one
 *    of them is set.
 *
 * Text inside of white boxes are the key associated with the object, its
 * data type is specified on its edge, i.e array, bool, integer, string,
 * dictionary.
 */
int HIDDEN
xbps_pkgdb_init(struct xbps_handle *xhp)
{
	int rv;

	assert(xhp != NULL);

	if (xhp->pkgdb != NULL)
		return 0;

	if ((rv = xbps_pkgdb_update(xhp, false)) != 0) {
		if (rv != ENOENT)
			xbps_dbg_printf(xhp, "[pkgdb] cannot internalize "
			    "pkgdb array: %s\n", strerror(rv));

		return rv;
	}
	xbps_dbg_printf(xhp, "[pkgdb] initialized ok.\n");

	return 0;
}
Пример #3
0
int HIDDEN
xbps_remove_pkg(struct xbps_handle *xhp,
		const char *pkgver,
		bool update,
		bool soft_replace)
{
	xbps_dictionary_t pkgd = NULL;
	char *pkgname, *buf = NULL;
	int rv = 0;
	pkg_state_t state = 0;

	assert(xhp);
	assert(pkgver);

	pkgname = xbps_pkg_name(pkgver);
	assert(pkgname);

	if ((rv = xbps_pkg_state_installed(xhp, pkgname, &state)) != 0)
		goto out;

	xbps_dbg_printf(xhp, "attempting to remove %s state %d\n",
	    pkgver, state);

	if (!update)
		xbps_set_cb_state(xhp, XBPS_STATE_REMOVE, 0, pkgver, NULL);

	if (chdir(xhp->rootdir) == -1) {
		rv = errno;
		xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FAIL,
		    rv, pkgver,
		   "%s: [remove] failed to chdir to rootdir `%s': %s",
		    pkgver, xhp->rootdir, strerror(rv));
		goto out;
	}

	/* internalize pkg dictionary from metadir */
	buf = xbps_xasprintf("%s/.%s.plist", xhp->metadir, pkgname);
	pkgd = xbps_dictionary_internalize_from_file(buf);
	free(buf);
	if (pkgd == NULL)
		xbps_dbg_printf(xhp, "WARNING: metaplist for %s "
		    "doesn't exist!\n", pkgver);

	/* If package was "half-removed", remove it fully. */
	if (state == XBPS_PKG_STATE_HALF_REMOVED)
		goto purge;
	/*
	 * Run the pre remove action.
	 */
	if (pkgd) {
		rv = xbps_pkg_exec_script(xhp, pkgd, "remove-script",
		    "pre", update);
		if (rv != 0) {
			xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FAIL,
			    errno, pkgver,
			    "%s: [remove] REMOVE script failed to "
			    "execute pre ACTION: %s",
			    pkgver, strerror(rv));
			goto out;
		}
	}
	/*
	 * If updating a package, we just need to execute the current
	 * pre-remove action target and we are done. Its files will be
	 * overwritten later in unpack phase.
	 */
	if (update) {
		if (pkgd)
			xbps_object_release(pkgd);
		free(pkgname);
		return 0;
	} else if (soft_replace) {
		/*
		 * Soft replace a package. Do not remove its files, but
		 * execute PURGE action, remove metadata files and unregister
		 * from pkgdb.
		 */
		goto softreplace;
	}

	if (pkgd) {
		/* Remove regular files */
		if ((rv = xbps_remove_pkg_files(xhp, pkgd, "files", pkgver)) != 0)
			goto out;
		/* Remove configuration files */
		if ((rv = xbps_remove_pkg_files(xhp, pkgd, "conf_files", pkgver)) != 0)
			goto out;
		/* Remove links */
		if ((rv = xbps_remove_pkg_files(xhp, pkgd, "links", pkgver)) != 0)
			goto out;
		/* Remove dirs */
		if ((rv = xbps_remove_pkg_files(xhp, pkgd, "dirs", pkgver)) != 0)
			goto out;
		/*
		 * Execute the post REMOVE action if file exists and we aren't
		 * updating the package.
		 */
		rv = xbps_pkg_exec_script(xhp, pkgd, "remove-script", "post", false);
		if (rv != 0) {
			xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FAIL,
			    rv, pkgver,
			    "%s: [remove] REMOVE script failed to execute "
			    "post ACTION: %s", pkgver, strerror(rv));
			goto out;
		}
	}

softreplace:
	/*
	 * Set package state to "half-removed".
	 */
	rv = xbps_set_pkg_state_installed(xhp, pkgver,
	     XBPS_PKG_STATE_HALF_REMOVED);
	if (rv != 0) {
		xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FAIL,
		    rv, pkgver,
		    "%s: [remove] failed to set state to half-removed: %s",
		    pkgver, strerror(rv));
		goto out;
	}

purge:
	/*
	 * Execute the purge REMOVE action if file exists.
	 */
	if (pkgd) {
		rv = xbps_pkg_exec_script(xhp, pkgd, "remove-script", "purge", false);
		if (rv != 0) {
			xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FAIL,
			    rv, pkgver,
			    "%s: REMOVE script failed to execute "
			    "purge ACTION: %s", pkgver, strerror(rv));
			goto out;
		}
		xbps_object_release(pkgd);
	}
	/*
	 * Remove package metadata plist.
	 */
	buf = xbps_xasprintf("%s/.%s.plist", xhp->metadir, pkgname);
	if (remove(buf) == -1) {
		if (errno != ENOENT) {
			xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FAIL,
			    rv, pkgver,
			    "%s: failed to remove metadata file: %s",
			    pkgver, strerror(errno));
		}
	}
	free(buf);
	/*
	 * Unregister package from pkgdb.
	 */
	xbps_dictionary_remove(xhp->pkgdb, pkgname);
	if ((rv = xbps_pkgdb_update(xhp, true)) != 0)
		goto out;

	xbps_dbg_printf(xhp, "[remove] unregister %s returned %d\n", pkgver, rv);

	xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_DONE, 0, pkgver, NULL);
out:
	if (pkgname != NULL)
		free(pkgname);

	return rv;
}
Пример #4
0
int
xbps_transaction_commit(struct xbps_handle *xhp)
{
    prop_object_t obj;
    prop_object_iterator_t iter;
    size_t i;
    const char *pkgname, *version, *pkgver, *tract;
    int rv = 0;
    bool update, install, sr;

    assert(prop_object_type(xhp->transd) == PROP_TYPE_DICTIONARY);

    update = install = false;
    iter = xbps_array_iter_from_dict(xhp->transd, "packages");
    if (iter == NULL)
        return EINVAL;
    /*
     * Download binary packages (if they come from a remote repository).
     */
    xbps_set_cb_state(xhp, XBPS_STATE_TRANS_DOWNLOAD, 0, NULL, NULL, NULL);
    if ((rv = download_binpkgs(xhp, iter)) != 0)
        goto out;
    /*
     * Check SHA256 hashes for binary packages in transaction.
     */
    xbps_set_cb_state(xhp, XBPS_STATE_TRANS_VERIFY, 0, NULL, NULL, NULL);
    if ((rv = check_binpkgs_hash(xhp, iter)) != 0)
        goto out;
    /*
     * Install, update, configure or remove packages as specified
     * in the transaction dictionary.
     */
    xbps_set_cb_state(xhp, XBPS_STATE_TRANS_RUN, 0, NULL, NULL, NULL);

    i = 0;
    while ((obj = prop_object_iterator_next(iter)) != NULL) {
        if ((xhp->transaction_frequency_flush > 0) &&
                (++i >= xhp->transaction_frequency_flush)) {
            rv = xbps_pkgdb_update(xhp, true);
            if (rv != 0 && rv != ENOENT)
                goto out;

            i = 0;
        }
        update = false;
        prop_dictionary_get_cstring_nocopy(obj, "transaction", &tract);
        prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
        prop_dictionary_get_cstring_nocopy(obj, "version", &version);
        prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);

        if (strcmp(tract, "remove") == 0) {
            update = false;
            sr = false;
            /*
             * Remove package.
             */
            prop_dictionary_get_bool(obj, "remove-and-update",
                                     &update);
            prop_dictionary_get_bool(obj, "softreplace", &sr);
            rv = xbps_remove_pkg(xhp, pkgname, version, update, sr);
            if (rv != 0)
                goto out;
        } else if (strcmp(tract, "configure") == 0) {
            /*
             * Reconfigure pending package.
             */
            rv = xbps_configure_pkg(xhp, pkgname, false, false, false);
            if (rv != 0)
                goto out;
        } else {
            /*
             * Install or update a package.
             */
            if (strcmp(tract, "update") == 0)
                update = true;
            else
                install = true;

            if (update) {
                /*
                 * Update a package: execute pre-remove
                 * action if found before unpacking.
                 */
                xbps_set_cb_state(xhp, XBPS_STATE_UPDATE, 0,
                                  pkgname, version, NULL);
                rv = xbps_remove_pkg(xhp, pkgname, version,
                                     true, false);
                if (rv != 0) {
                    xbps_set_cb_state(xhp,
                                      XBPS_STATE_UPDATE_FAIL,
                                      rv, pkgname, version,
                                      "%s: [trans] failed to update "
                                      "package to `%s': %s", pkgver,
                                      version, strerror(rv));
                    goto out;
                }
            } else {
                /* Install a package */
                xbps_set_cb_state(xhp, XBPS_STATE_INSTALL,
                                  0, pkgname, version, NULL);
            }
            /*
             * Unpack binary package.
             */
            if ((rv = xbps_unpack_binary_pkg(xhp, obj)) != 0)
                goto out;
            /*
             * Register package.
             */
            if ((rv = xbps_register_pkg(xhp, obj, false)) != 0)
                goto out;
        }
    }
    prop_object_iterator_reset(iter);

    /* force a flush now packages were removed/unpacked */
    if ((rv = xbps_pkgdb_update(xhp, true)) != 0)
        goto out;

    /* if there are no packages to install or update we are done */
    if (!update && !install)
        goto out;
    /*
     * Configure all unpacked packages.
     */
    xbps_set_cb_state(xhp, XBPS_STATE_TRANS_CONFIGURE, 0, NULL, NULL, NULL);

    i = 0;
    while ((obj = prop_object_iterator_next(iter)) != NULL) {
        if (xhp->transaction_frequency_flush > 0 &&
                ++i >= xhp->transaction_frequency_flush) {
            if ((rv = xbps_pkgdb_update(xhp, true)) != 0)
                goto out;

            i = 0;
        }

        prop_dictionary_get_cstring_nocopy(obj, "transaction", &tract);
        if ((strcmp(tract, "remove") == 0) ||
                (strcmp(tract, "configure") == 0))
            continue;

        prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
        prop_dictionary_get_cstring_nocopy(obj, "version", &version);
        update = false;
        if (strcmp(tract, "update") == 0)
            update = true;

        rv = xbps_configure_pkg(xhp, pkgname, false, update, false);
        if (rv != 0)
            goto out;
        /*
         * Notify client callback when a package has been
         * installed or updated.
         */
        if (update) {
            xbps_set_cb_state(xhp, XBPS_STATE_UPDATE_DONE, 0,
                              pkgname, version, NULL);
        } else {
            xbps_set_cb_state(xhp, XBPS_STATE_INSTALL_DONE, 0,
                              pkgname, version, NULL);
        }
    }

    /* Force a flush now that packages are configured */
    rv = xbps_pkgdb_update(xhp, true);
out:
    prop_object_iterator_release(iter);

    return rv;
}