xiaoxiang781216 commented on code in PR #3720:
URL: https://github.com/apache/nuttx-apps/pull/3720#discussion_r3764164872
##########
system/nxpkg/pkg_install.c:
##########
@@ -247,185 +331,346 @@ int pkg_install(FAR const char *name)
FAR struct pkg_index_s *index;
FAR struct pkg_installed_db_s *installed;
FAR const struct pkg_manifest_s *manifest;
- char source[PATH_MAX];
- char tmp[PATH_MAX] = "";
- char payload[PATH_MAX];
- char manifest_path[PATH_MAX];
- char lock[PATH_MAX] = "";
+ FAR char *source;
+ FAR char *tmp;
+ FAR char *payload;
+ FAR char *manifest_path;
+ FAR char *lock;
+ FAR char *installed_lock;
+ FAR const char *artifact;
char digest[PKG_HASH_HEX_LEN + 1];
+ char pruned_version[PKG_VERSION_MAX + 1];
+ bool staged_to_tmp;
+ bool version_dir_created;
+ bool installed_lock_held;
int ret;
- index = malloc(sizeof(*index));
- installed = malloc(sizeof(*installed));
- if (index == NULL || installed == NULL)
+ pruned_version[0] = '\0';
+
+ index = pkg_zalloc(sizeof(*index));
+ installed = pkg_zalloc(sizeof(*installed));
+ source = pkg_path_alloc();
+ tmp = pkg_path_alloc();
+ payload = pkg_path_alloc();
+ manifest_path = pkg_path_alloc();
+ lock = pkg_path_alloc();
+ installed_lock = pkg_path_alloc();
+ if (index == NULL || installed == NULL || source == NULL || tmp == NULL ||
+ payload == NULL || manifest_path == NULL || lock == NULL ||
+ installed_lock == NULL)
{
- free(index);
- free(installed);
+ pkg_free(index);
+ pkg_free(installed);
+ pkg_free(source);
+ pkg_free(tmp);
+ pkg_free(payload);
+ pkg_free(manifest_path);
+ pkg_free(lock);
+ pkg_free(installed_lock);
pkg_error("unable to allocate package metadata buffers");
return EXIT_FAILURE;
}
+ source[0] = '\0';
+ tmp[0] = '\0';
+ payload[0] = '\0';
+ manifest_path[0] = '\0';
+ lock[0] = '\0';
+ installed_lock[0] = '\0';
+ installed_lock_held = false;
+ artifact = NULL;
+ staged_to_tmp = false;
+ version_dir_created = false;
+
ret = pkg_store_prepare_layout();
if (ret < 0)
{
- free(index);
- free(installed);
+ pkg_free(index);
+ pkg_free(installed);
+ pkg_free(source);
+ pkg_free(tmp);
+ pkg_free(payload);
+ pkg_free(manifest_path);
+ pkg_free(lock);
+ pkg_free(installed_lock);
pkg_error("unable to prepare package layout: %d", ret);
return EXIT_FAILURE;
}
ret = pkg_metadata_load_index(index);
if (ret < 0)
{
- free(index);
- free(installed);
+ pkg_free(index);
+ pkg_free(installed);
+ pkg_free(source);
+ pkg_free(tmp);
+ pkg_free(payload);
+ pkg_free(manifest_path);
+ pkg_free(lock);
+ pkg_free(installed_lock);
pkg_error("unable to load local index metadata: %d", ret);
return EXIT_FAILURE;
}
manifest = pkg_metadata_find_latest(index, name);
if (manifest == NULL)
{
- free(index);
- free(installed);
+ pkg_free(index);
+ pkg_free(installed);
+ pkg_free(source);
+ pkg_free(tmp);
+ pkg_free(payload);
+ pkg_free(manifest_path);
+ pkg_free(lock);
+ pkg_free(installed_lock);
Review Comment:
ditto
##########
system/nxpkg/pkg_install.c:
##########
@@ -108,8 +127,63 @@ static bool pkg_install_has_version(
return false;
}
+static int pkg_install_prune_oldest_version(
+ FAR struct pkg_installed_entry_s *entry,
+ FAR char *pruned_version, size_t pruned_version_size)
+{
+ size_t victim = entry->version_count;
+ size_t i;
+
+ /* Versions are appended in install order, so the lowest index that
+ * isn't the active ("current") or rollback ("previous") version is the
+ * oldest one safe to drop. Without this, a package updated more than
+ * PKG_INSTALLED_VERSIONS_MAX times becomes permanently un-installable
+ * (pkg_install_add_version would just fail forever).
+ */
+
+ for (i = 0; i < entry->version_count; i++)
+ {
+ if (strcmp(entry->versions[i], entry->current) != 0 &&
+ strcmp(entry->versions[i], entry->previous) != 0)
+ {
+ victim = i;
+ break;
+ }
+ }
+
+ if (victim == entry->version_count)
+ {
+ return -E2BIG;
+ }
+
+ /* Deleting the pruned version's on-disk directory here, before this
+ * in-memory db update is even durably saved, left a real inconsistency
+ * window: if pkg_metadata_save_installed() subsequently failed (full
+ * SD card, I/O error), the payload was already gone but the last
+ * successfully-saved instpkg.jsn could still list that version as
+ * installed. Hand the victim's version string back to the caller
+ * instead, so it can defer the actual directory removal until after
+ * the save succeeds - mirroring how this file already treats the
+ * installed db as authoritative everywhere else.
+ */
+
+ snprintf(pruned_version, pruned_version_size, "%s",
+ entry->versions[victim]);
+
+ for (i = victim; i + 1 < entry->version_count; i++)
+ {
+ memcpy(entry->versions[i], entry->versions[i + 1],
+ sizeof(entry->versions[i]));
Review Comment:
add space
##########
system/nxpkg/pkg_install.c:
##########
@@ -247,185 +331,346 @@ int pkg_install(FAR const char *name)
FAR struct pkg_index_s *index;
FAR struct pkg_installed_db_s *installed;
FAR const struct pkg_manifest_s *manifest;
- char source[PATH_MAX];
- char tmp[PATH_MAX] = "";
- char payload[PATH_MAX];
- char manifest_path[PATH_MAX];
- char lock[PATH_MAX] = "";
+ FAR char *source;
+ FAR char *tmp;
+ FAR char *payload;
+ FAR char *manifest_path;
+ FAR char *lock;
+ FAR char *installed_lock;
+ FAR const char *artifact;
char digest[PKG_HASH_HEX_LEN + 1];
+ char pruned_version[PKG_VERSION_MAX + 1];
+ bool staged_to_tmp;
+ bool version_dir_created;
+ bool installed_lock_held;
int ret;
- index = malloc(sizeof(*index));
- installed = malloc(sizeof(*installed));
- if (index == NULL || installed == NULL)
+ pruned_version[0] = '\0';
+
+ index = pkg_zalloc(sizeof(*index));
+ installed = pkg_zalloc(sizeof(*installed));
+ source = pkg_path_alloc();
+ tmp = pkg_path_alloc();
+ payload = pkg_path_alloc();
+ manifest_path = pkg_path_alloc();
+ lock = pkg_path_alloc();
+ installed_lock = pkg_path_alloc();
+ if (index == NULL || installed == NULL || source == NULL || tmp == NULL ||
+ payload == NULL || manifest_path == NULL || lock == NULL ||
+ installed_lock == NULL)
{
- free(index);
- free(installed);
+ pkg_free(index);
+ pkg_free(installed);
+ pkg_free(source);
+ pkg_free(tmp);
+ pkg_free(payload);
+ pkg_free(manifest_path);
+ pkg_free(lock);
+ pkg_free(installed_lock);
pkg_error("unable to allocate package metadata buffers");
return EXIT_FAILURE;
}
+ source[0] = '\0';
+ tmp[0] = '\0';
+ payload[0] = '\0';
+ manifest_path[0] = '\0';
+ lock[0] = '\0';
+ installed_lock[0] = '\0';
+ installed_lock_held = false;
+ artifact = NULL;
+ staged_to_tmp = false;
+ version_dir_created = false;
+
ret = pkg_store_prepare_layout();
if (ret < 0)
{
- free(index);
- free(installed);
+ pkg_free(index);
+ pkg_free(installed);
+ pkg_free(source);
+ pkg_free(tmp);
+ pkg_free(payload);
+ pkg_free(manifest_path);
+ pkg_free(lock);
+ pkg_free(installed_lock);
pkg_error("unable to prepare package layout: %d", ret);
return EXIT_FAILURE;
}
ret = pkg_metadata_load_index(index);
if (ret < 0)
{
- free(index);
- free(installed);
+ pkg_free(index);
+ pkg_free(installed);
+ pkg_free(source);
+ pkg_free(tmp);
+ pkg_free(payload);
+ pkg_free(manifest_path);
+ pkg_free(lock);
+ pkg_free(installed_lock);
Review Comment:
ditto
##########
system/nxpkg/pkg_install.c:
##########
@@ -475,27 +760,331 @@ int pkg_list(FAR FILE *stream)
ret = pkg_store_prepare_layout();
if (ret < 0)
{
- free(db);
+ pkg_free(db);
pkg_error("unable to prepare package layout: %d", ret);
return EXIT_FAILURE;
}
ret = pkg_metadata_load_installed(db);
if (ret < 0)
{
- free(db);
+ pkg_free(db);
pkg_error("unable to load installed metadata: %d", ret);
return EXIT_FAILURE;
}
ret = pkg_metadata_print_installed(stream, db);
if (ret < 0)
{
- free(db);
+ pkg_free(db);
pkg_error("unable to print installed metadata: %d", ret);
return EXIT_FAILURE;
}
- free(db);
+ pkg_free(db);
+ return EXIT_SUCCESS;
+}
+
+/****************************************************************************
+ * Name: pkg_uninstall
+ *
+ * Description:
+ * Remove every installed version of "name": their version directories
+ * (payload + manifest.jsn), the current/previous pointer files, any
+ * leftover txn.tx, the entry in the shared installed-packages database,
+ * and finally the now-empty package root directory. Refuses to run
+ * while an install/update for the same package is in flight (a live
+ * lock.lk), since removing the store out from under it would corrupt
+ * whatever it's mid-writing.
+ *
+ ****************************************************************************/
+
+int pkg_uninstall(FAR const char *name)
+{
+ FAR struct pkg_installed_db_s *db;
+ FAR struct pkg_installed_entry_s *entry;
+ struct pkg_installed_entry_s removed;
+ char path[PATH_MAX];
+ char package_lock[PATH_MAX];
+ char installed_lock[PATH_MAX];
+ size_t index;
+ size_t i;
+ int ret;
+
+ if (!pkg_validate_path_component(name))
+ {
+ pkg_error("remove requires a valid package name");
+ return EXIT_FAILURE;
+ }
+
+ db = pkg_zalloc(sizeof(*db));
+ if (db == NULL)
+ {
+ pkg_error("unable to allocate installed metadata buffer");
+ return EXIT_FAILURE;
+ }
+
+ ret = pkg_store_prepare_layout();
+ if (ret < 0)
+ {
+ pkg_free(db);
+ pkg_error("unable to prepare package layout: %d", ret);
+ return EXIT_FAILURE;
+ }
+
+ ret = pkg_install_acquire_lock(name, package_lock, sizeof(package_lock));
+ if (ret < 0)
+ {
+ pkg_free(db);
+ pkg_error("unable to acquire package lock for '%s': %d", name, ret);
+ return EXIT_FAILURE;
+ }
+
+ ret = pkg_install_acquire_installed_lock(installed_lock,
+ sizeof(installed_lock));
+ if (ret < 0)
+ {
+ pkg_store_remove_file(package_lock);
+ pkg_free(db);
+ pkg_error("unable to acquire installed-db lock: %d", ret);
+ return EXIT_FAILURE;
+ }
+
+ ret = pkg_metadata_load_installed(db);
+ if (ret < 0)
+ {
+ pkg_store_remove_file(installed_lock);
+ pkg_store_remove_file(package_lock);
+ pkg_free(db);
+ pkg_error("unable to load installed metadata: %d", ret);
+ return EXIT_FAILURE;
+ }
+
+ entry = pkg_metadata_find_installed(db, name);
+ if (entry == NULL)
+ {
+ pkg_store_remove_file(installed_lock);
+ pkg_store_remove_file(package_lock);
+ pkg_free(db);
Review Comment:
could we use goto to avoid the code duplication too
##########
system/nxpkg/pkg_install.c:
##########
@@ -247,185 +331,346 @@ int pkg_install(FAR const char *name)
FAR struct pkg_index_s *index;
FAR struct pkg_installed_db_s *installed;
FAR const struct pkg_manifest_s *manifest;
- char source[PATH_MAX];
- char tmp[PATH_MAX] = "";
- char payload[PATH_MAX];
- char manifest_path[PATH_MAX];
- char lock[PATH_MAX] = "";
+ FAR char *source;
+ FAR char *tmp;
+ FAR char *payload;
+ FAR char *manifest_path;
+ FAR char *lock;
+ FAR char *installed_lock;
+ FAR const char *artifact;
char digest[PKG_HASH_HEX_LEN + 1];
+ char pruned_version[PKG_VERSION_MAX + 1];
+ bool staged_to_tmp;
+ bool version_dir_created;
+ bool installed_lock_held;
int ret;
- index = malloc(sizeof(*index));
- installed = malloc(sizeof(*installed));
- if (index == NULL || installed == NULL)
+ pruned_version[0] = '\0';
+
+ index = pkg_zalloc(sizeof(*index));
+ installed = pkg_zalloc(sizeof(*installed));
+ source = pkg_path_alloc();
+ tmp = pkg_path_alloc();
+ payload = pkg_path_alloc();
+ manifest_path = pkg_path_alloc();
+ lock = pkg_path_alloc();
+ installed_lock = pkg_path_alloc();
+ if (index == NULL || installed == NULL || source == NULL || tmp == NULL ||
+ payload == NULL || manifest_path == NULL || lock == NULL ||
+ installed_lock == NULL)
{
- free(index);
- free(installed);
+ pkg_free(index);
+ pkg_free(installed);
+ pkg_free(source);
+ pkg_free(tmp);
+ pkg_free(payload);
+ pkg_free(manifest_path);
+ pkg_free(lock);
+ pkg_free(installed_lock);
pkg_error("unable to allocate package metadata buffers");
return EXIT_FAILURE;
}
+ source[0] = '\0';
+ tmp[0] = '\0';
+ payload[0] = '\0';
+ manifest_path[0] = '\0';
+ lock[0] = '\0';
+ installed_lock[0] = '\0';
+ installed_lock_held = false;
+ artifact = NULL;
+ staged_to_tmp = false;
+ version_dir_created = false;
+
ret = pkg_store_prepare_layout();
if (ret < 0)
{
- free(index);
- free(installed);
+ pkg_free(index);
+ pkg_free(installed);
+ pkg_free(source);
+ pkg_free(tmp);
+ pkg_free(payload);
+ pkg_free(manifest_path);
+ pkg_free(lock);
+ pkg_free(installed_lock);
pkg_error("unable to prepare package layout: %d", ret);
return EXIT_FAILURE;
}
ret = pkg_metadata_load_index(index);
if (ret < 0)
{
- free(index);
- free(installed);
+ pkg_free(index);
+ pkg_free(installed);
+ pkg_free(source);
+ pkg_free(tmp);
+ pkg_free(payload);
+ pkg_free(manifest_path);
+ pkg_free(lock);
+ pkg_free(installed_lock);
pkg_error("unable to load local index metadata: %d", ret);
return EXIT_FAILURE;
}
manifest = pkg_metadata_find_latest(index, name);
if (manifest == NULL)
{
- free(index);
- free(installed);
+ pkg_free(index);
+ pkg_free(installed);
+ pkg_free(source);
+ pkg_free(tmp);
+ pkg_free(payload);
+ pkg_free(manifest_path);
+ pkg_free(lock);
+ pkg_free(installed_lock);
pkg_error("package '%s' not found in local index", name);
return EXIT_FAILURE;
}
- ret = pkg_install_resolve_artifact(source, sizeof(source), manifest);
+ ret = pkg_resolve_artifact_source(source, PATH_MAX, manifest);
if (ret < 0)
{
- pkg_error("artifact path for '%s' is too long", name);
+ pkg_free(index);
+ pkg_free(installed);
+ pkg_free(source);
+ pkg_free(tmp);
+ pkg_free(payload);
+ pkg_free(manifest_path);
+ pkg_free(lock);
+ pkg_free(installed_lock);
+ pkg_error("unable to resolve artifact source for '%s': %d", name, ret);
Review Comment:
ditto
##########
system/nxpkg/pkg_install.c:
##########
@@ -247,185 +331,346 @@ int pkg_install(FAR const char *name)
FAR struct pkg_index_s *index;
FAR struct pkg_installed_db_s *installed;
FAR const struct pkg_manifest_s *manifest;
- char source[PATH_MAX];
- char tmp[PATH_MAX] = "";
- char payload[PATH_MAX];
- char manifest_path[PATH_MAX];
- char lock[PATH_MAX] = "";
+ FAR char *source;
+ FAR char *tmp;
+ FAR char *payload;
+ FAR char *manifest_path;
+ FAR char *lock;
+ FAR char *installed_lock;
+ FAR const char *artifact;
char digest[PKG_HASH_HEX_LEN + 1];
+ char pruned_version[PKG_VERSION_MAX + 1];
+ bool staged_to_tmp;
+ bool version_dir_created;
+ bool installed_lock_held;
int ret;
- index = malloc(sizeof(*index));
- installed = malloc(sizeof(*installed));
- if (index == NULL || installed == NULL)
+ pruned_version[0] = '\0';
+
+ index = pkg_zalloc(sizeof(*index));
+ installed = pkg_zalloc(sizeof(*installed));
+ source = pkg_path_alloc();
+ tmp = pkg_path_alloc();
+ payload = pkg_path_alloc();
+ manifest_path = pkg_path_alloc();
+ lock = pkg_path_alloc();
+ installed_lock = pkg_path_alloc();
+ if (index == NULL || installed == NULL || source == NULL || tmp == NULL ||
+ payload == NULL || manifest_path == NULL || lock == NULL ||
+ installed_lock == NULL)
{
- free(index);
- free(installed);
+ pkg_free(index);
+ pkg_free(installed);
+ pkg_free(source);
+ pkg_free(tmp);
+ pkg_free(payload);
+ pkg_free(manifest_path);
+ pkg_free(lock);
+ pkg_free(installed_lock);
pkg_error("unable to allocate package metadata buffers");
return EXIT_FAILURE;
Review Comment:
goto errout to avoid the code dup
##########
system/nxpkg/pkg_install.c:
##########
@@ -437,35 +682,75 @@ int pkg_install(FAR const char *name)
}
pkg_info("installed %s version %s", manifest->name, manifest->version);
- free(index);
- free(installed);
+ pkg_free(index);
+ pkg_free(installed);
+ pkg_free(source);
+ pkg_free(tmp);
+ pkg_free(payload);
+ pkg_free(manifest_path);
+ pkg_free(lock);
+ pkg_free(installed_lock);
Review Comment:
could we goto the end to avoid the code dup
##########
system/nxpkg/pkg_install.c:
##########
@@ -475,27 +760,331 @@ int pkg_list(FAR FILE *stream)
ret = pkg_store_prepare_layout();
if (ret < 0)
{
- free(db);
+ pkg_free(db);
pkg_error("unable to prepare package layout: %d", ret);
return EXIT_FAILURE;
}
ret = pkg_metadata_load_installed(db);
if (ret < 0)
{
- free(db);
+ pkg_free(db);
pkg_error("unable to load installed metadata: %d", ret);
return EXIT_FAILURE;
}
ret = pkg_metadata_print_installed(stream, db);
if (ret < 0)
{
- free(db);
+ pkg_free(db);
pkg_error("unable to print installed metadata: %d", ret);
return EXIT_FAILURE;
}
- free(db);
+ pkg_free(db);
+ return EXIT_SUCCESS;
+}
+
+/****************************************************************************
+ * Name: pkg_uninstall
+ *
+ * Description:
+ * Remove every installed version of "name": their version directories
+ * (payload + manifest.jsn), the current/previous pointer files, any
+ * leftover txn.tx, the entry in the shared installed-packages database,
+ * and finally the now-empty package root directory. Refuses to run
+ * while an install/update for the same package is in flight (a live
+ * lock.lk), since removing the store out from under it would corrupt
+ * whatever it's mid-writing.
+ *
+ ****************************************************************************/
+
+int pkg_uninstall(FAR const char *name)
+{
+ FAR struct pkg_installed_db_s *db;
+ FAR struct pkg_installed_entry_s *entry;
+ struct pkg_installed_entry_s removed;
+ char path[PATH_MAX];
+ char package_lock[PATH_MAX];
+ char installed_lock[PATH_MAX];
+ size_t index;
+ size_t i;
+ int ret;
+
+ if (!pkg_validate_path_component(name))
+ {
+ pkg_error("remove requires a valid package name");
+ return EXIT_FAILURE;
+ }
+
+ db = pkg_zalloc(sizeof(*db));
+ if (db == NULL)
+ {
+ pkg_error("unable to allocate installed metadata buffer");
+ return EXIT_FAILURE;
+ }
+
+ ret = pkg_store_prepare_layout();
+ if (ret < 0)
+ {
+ pkg_free(db);
+ pkg_error("unable to prepare package layout: %d", ret);
+ return EXIT_FAILURE;
+ }
+
+ ret = pkg_install_acquire_lock(name, package_lock, sizeof(package_lock));
+ if (ret < 0)
+ {
+ pkg_free(db);
+ pkg_error("unable to acquire package lock for '%s': %d", name, ret);
+ return EXIT_FAILURE;
+ }
+
+ ret = pkg_install_acquire_installed_lock(installed_lock,
+ sizeof(installed_lock));
+ if (ret < 0)
+ {
+ pkg_store_remove_file(package_lock);
+ pkg_free(db);
+ pkg_error("unable to acquire installed-db lock: %d", ret);
+ return EXIT_FAILURE;
+ }
+
+ ret = pkg_metadata_load_installed(db);
+ if (ret < 0)
+ {
+ pkg_store_remove_file(installed_lock);
+ pkg_store_remove_file(package_lock);
+ pkg_free(db);
+ pkg_error("unable to load installed metadata: %d", ret);
+ return EXIT_FAILURE;
+ }
+
+ entry = pkg_metadata_find_installed(db, name);
+ if (entry == NULL)
+ {
+ pkg_store_remove_file(installed_lock);
+ pkg_store_remove_file(package_lock);
+ pkg_free(db);
+ pkg_error("package '%s' is not installed", name);
+ return EXIT_FAILURE;
+ }
+
+ /* Drop this entry from the authoritative database before removing its
+ * payloads. A power loss can then leave reclaimable orphan files, but
+ * never a database entry that points at a payload already deleted.
+ */
+
+ removed = *entry;
+ index = (size_t)(entry - db->entries);
+ for (i = index; i + 1 < db->count; i++)
+ {
+ db->entries[i] = db->entries[i + 1];
+ }
+
+ db->count--;
+
+ ret = pkg_metadata_save_installed(db);
+ pkg_store_remove_file(installed_lock);
+ if (ret < 0)
+ {
+ pkg_store_remove_file(package_lock);
+ pkg_free(db);
+ pkg_error("unable to save installed metadata: %d", ret);
+ return EXIT_FAILURE;
+ }
+
+ for (i = 0; i < removed.version_count; i++)
+ {
+ pkg_store_remove_version_dir(name, removed.versions[i]);
+ }
+
+ if (pkg_store_format_txn_path(path, sizeof(path), name) == 0)
+ {
+ pkg_store_remove_file(path);
+ }
+
+ if (pkg_store_format_current_path(path, sizeof(path), name) == 0)
+ {
+ pkg_store_remove_file(path);
+ }
+
+ if (pkg_store_format_previous_path(path, sizeof(path), name) == 0)
+ {
+ pkg_store_remove_file(path);
+ }
+
+ pkg_store_remove_file(package_lock);
+
+ if (pkg_store_format_package_root(path, sizeof(path), name) == 0)
+ {
+ rmdir(path);
+ }
+
+ pkg_info("removed %s", name);
+ pkg_free(db);
+ return EXIT_SUCCESS;
+}
+
+/****************************************************************************
+ * Name: pkg_rollback
+ *
+ * Description:
+ * Swap "name"'s current and previous installed versions. The swap (as
+ * opposed to just clearing "previous") lets a second rollback undo the
+ * first. Verifies the rollback target's version directory still
+ * exists on disk before committing any state change, and refuses to
+ * run while an install/update for the same package is in flight.
+ *
+ ****************************************************************************/
+
+int pkg_rollback(FAR const char *name)
+{
+ FAR struct pkg_installed_db_s *db;
+ FAR struct pkg_installed_entry_s *entry;
+ char version_path[PATH_MAX];
+ char package_lock[PATH_MAX];
+ char installed_lock[PATH_MAX];
+ char swap[PKG_VERSION_MAX + 1];
+ struct stat st;
+ int ret;
+
+ if (!pkg_validate_path_component(name))
+ {
+ pkg_error("rollback requires a valid package name");
+ return EXIT_FAILURE;
+ }
+
+ db = pkg_zalloc(sizeof(*db));
+ if (db == NULL)
+ {
+ pkg_error("unable to allocate installed metadata buffer");
+ return EXIT_FAILURE;
+ }
+
+ ret = pkg_store_prepare_layout();
+ if (ret < 0)
+ {
+ pkg_free(db);
+ pkg_error("unable to prepare package layout: %d", ret);
+ return EXIT_FAILURE;
+ }
+
+ ret = pkg_install_acquire_lock(name, package_lock, sizeof(package_lock));
+ if (ret < 0)
+ {
+ pkg_free(db);
+ pkg_error("unable to acquire package lock for '%s': %d", name, ret);
+ return EXIT_FAILURE;
+ }
+
+ ret = pkg_install_acquire_installed_lock(installed_lock,
+ sizeof(installed_lock));
+ if (ret < 0)
+ {
+ pkg_store_remove_file(package_lock);
+ pkg_free(db);
+ pkg_error("unable to acquire installed-db lock: %d", ret);
+ return EXIT_FAILURE;
+ }
+
+ ret = pkg_metadata_load_installed(db);
+ if (ret < 0)
+ {
+ pkg_store_remove_file(installed_lock);
+ pkg_store_remove_file(package_lock);
+ pkg_free(db);
+ pkg_error("unable to load installed metadata: %d", ret);
+ return EXIT_FAILURE;
+ }
+
+ entry = pkg_metadata_find_installed(db, name);
+ if (entry == NULL)
+ {
+ pkg_store_remove_file(installed_lock);
+ pkg_store_remove_file(package_lock);
+ pkg_free(db);
+ pkg_error("package '%s' is not installed", name);
+ return EXIT_FAILURE;
+ }
+
+ if (entry->previous[0] == '\0')
+ {
+ pkg_store_remove_file(installed_lock);
+ pkg_store_remove_file(package_lock);
+ pkg_free(db);
+ pkg_error("package '%s' has no previous version to roll back to",
+ name);
+ return EXIT_FAILURE;
+ }
+
+ ret = pkg_store_format_version_path(version_path, sizeof(version_path),
+ name, entry->previous);
+ if (ret < 0 || stat(version_path, &st) < 0)
+ {
+ pkg_store_remove_file(installed_lock);
+ pkg_store_remove_file(package_lock);
+ pkg_free(db);
+ pkg_error("rollback target version '%s' is missing on disk",
+ entry->previous);
+ return EXIT_FAILURE;
+ }
+
+ ret = snprintf(swap, sizeof(swap), "%s", entry->current);
+ if (ret < 0 || (size_t)ret >= sizeof(swap))
+ {
+ pkg_store_remove_file(installed_lock);
+ pkg_store_remove_file(package_lock);
+ pkg_free(db);
+ pkg_error("current version string too long to swap");
+ return EXIT_FAILURE;
+ }
+
+ ret = snprintf(entry->current, sizeof(entry->current), "%s",
+ entry->previous);
+ if (ret < 0 || (size_t)ret >= sizeof(entry->current))
+ {
+ pkg_store_remove_file(installed_lock);
+ pkg_store_remove_file(package_lock);
+ pkg_free(db);
+ pkg_error("unable to update current version");
+ return EXIT_FAILURE;
+ }
+
+ ret = snprintf(entry->previous, sizeof(entry->previous), "%s", swap);
+ if (ret < 0 || (size_t)ret >= sizeof(entry->previous))
+ {
+ pkg_store_remove_file(installed_lock);
+ pkg_store_remove_file(package_lock);
+ pkg_free(db);
+ pkg_error("unable to update previous version");
+ return EXIT_FAILURE;
+ }
+
+ /* The installed database is authoritative, so commit it first. Refresh
+ * the current/previous pointer files afterwards as convenience mirrors;
+ * they can be reconstructed from the database if either write fails.
+ */
+
+ ret = pkg_metadata_save_installed(db);
+ if (ret < 0)
+ {
+ pkg_store_remove_file(installed_lock);
+ pkg_store_remove_file(package_lock);
+ pkg_free(db);
Review Comment:
ditto
##########
system/nxpkg/pkg_install.c:
##########
@@ -247,185 +331,346 @@ int pkg_install(FAR const char *name)
FAR struct pkg_index_s *index;
FAR struct pkg_installed_db_s *installed;
FAR const struct pkg_manifest_s *manifest;
- char source[PATH_MAX];
- char tmp[PATH_MAX] = "";
- char payload[PATH_MAX];
- char manifest_path[PATH_MAX];
- char lock[PATH_MAX] = "";
+ FAR char *source;
+ FAR char *tmp;
+ FAR char *payload;
+ FAR char *manifest_path;
+ FAR char *lock;
+ FAR char *installed_lock;
+ FAR const char *artifact;
char digest[PKG_HASH_HEX_LEN + 1];
+ char pruned_version[PKG_VERSION_MAX + 1];
+ bool staged_to_tmp;
+ bool version_dir_created;
+ bool installed_lock_held;
int ret;
- index = malloc(sizeof(*index));
- installed = malloc(sizeof(*installed));
- if (index == NULL || installed == NULL)
+ pruned_version[0] = '\0';
+
+ index = pkg_zalloc(sizeof(*index));
+ installed = pkg_zalloc(sizeof(*installed));
+ source = pkg_path_alloc();
+ tmp = pkg_path_alloc();
+ payload = pkg_path_alloc();
+ manifest_path = pkg_path_alloc();
+ lock = pkg_path_alloc();
+ installed_lock = pkg_path_alloc();
+ if (index == NULL || installed == NULL || source == NULL || tmp == NULL ||
+ payload == NULL || manifest_path == NULL || lock == NULL ||
+ installed_lock == NULL)
{
- free(index);
- free(installed);
+ pkg_free(index);
+ pkg_free(installed);
+ pkg_free(source);
+ pkg_free(tmp);
+ pkg_free(payload);
+ pkg_free(manifest_path);
+ pkg_free(lock);
+ pkg_free(installed_lock);
pkg_error("unable to allocate package metadata buffers");
return EXIT_FAILURE;
}
+ source[0] = '\0';
+ tmp[0] = '\0';
+ payload[0] = '\0';
+ manifest_path[0] = '\0';
+ lock[0] = '\0';
+ installed_lock[0] = '\0';
+ installed_lock_held = false;
+ artifact = NULL;
+ staged_to_tmp = false;
+ version_dir_created = false;
+
ret = pkg_store_prepare_layout();
if (ret < 0)
{
- free(index);
- free(installed);
+ pkg_free(index);
+ pkg_free(installed);
+ pkg_free(source);
+ pkg_free(tmp);
+ pkg_free(payload);
+ pkg_free(manifest_path);
+ pkg_free(lock);
+ pkg_free(installed_lock);
pkg_error("unable to prepare package layout: %d", ret);
return EXIT_FAILURE;
}
ret = pkg_metadata_load_index(index);
if (ret < 0)
{
- free(index);
- free(installed);
+ pkg_free(index);
+ pkg_free(installed);
+ pkg_free(source);
+ pkg_free(tmp);
+ pkg_free(payload);
+ pkg_free(manifest_path);
+ pkg_free(lock);
+ pkg_free(installed_lock);
pkg_error("unable to load local index metadata: %d", ret);
return EXIT_FAILURE;
}
manifest = pkg_metadata_find_latest(index, name);
if (manifest == NULL)
{
- free(index);
- free(installed);
+ pkg_free(index);
+ pkg_free(installed);
+ pkg_free(source);
+ pkg_free(tmp);
+ pkg_free(payload);
+ pkg_free(manifest_path);
+ pkg_free(lock);
+ pkg_free(installed_lock);
pkg_error("package '%s' not found in local index", name);
return EXIT_FAILURE;
}
- ret = pkg_install_resolve_artifact(source, sizeof(source), manifest);
+ ret = pkg_resolve_artifact_source(source, PATH_MAX, manifest);
if (ret < 0)
{
- pkg_error("artifact path for '%s' is too long", name);
+ pkg_free(index);
+ pkg_free(installed);
+ pkg_free(source);
+ pkg_free(tmp);
+ pkg_free(payload);
+ pkg_free(manifest_path);
+ pkg_free(lock);
+ pkg_free(installed_lock);
+ pkg_error("unable to resolve artifact source for '%s': %d", name, ret);
return EXIT_FAILURE;
}
- ret = pkg_install_acquire_lock(name, lock, sizeof(lock));
+ ret = pkg_install_acquire_lock(name, lock, PATH_MAX);
if (ret < 0)
{
+ pkg_free(index);
+ pkg_free(installed);
+ pkg_free(source);
+ pkg_free(tmp);
+ pkg_free(payload);
+ pkg_free(manifest_path);
+ pkg_free(lock);
+ pkg_free(installed_lock);
Review Comment:
ditto
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]