Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions doc/manual/rl-next/c-api-new-store-methods.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
synopsis: "C API: New store API methods"
prs: [14766]
---

The C API now includes additional methods:

- `nix_store_query_path_from_hash_part()` - Get the full store path given its hash part
- `nix_store_copy_path()` - Copy a single store path between two stores, allows repairs and configuring signature checking
38 changes: 38 additions & 0 deletions src/libstore-c/nix_api_store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -453,4 +453,42 @@ nix_err nix_derivation_get_outputs_and_optpaths(
NIXC_CATCH_ERRS
}

StorePath * nix_store_query_path_from_hash_part(nix_c_context * context, Store * store, const char * hash)
{
if (context)
context->last_err_code = NIX_OK;
try {
std::optional<nix::StorePath> s = store->ptr->queryPathFromHashPart(hash);

if (!s.has_value()) {
return nullptr;
}

return new StorePath{std::move(s.value())};
}
NIXC_CATCH_ERRS_NULL
}
Comment on lines +456 to +470
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Missing null validation for store and hash parameters.

Unlike nix_store_copy_path which validates its parameters, this function will crash if store is null (dereferencing store->ptr) or may have undefined behavior if hash is null. Consider adding validation for consistency:

🛡️ Proposed fix to add validation
 StorePath * nix_store_query_path_from_hash_part(nix_c_context * context, Store * store, const char * hash)
 {
     if (context)
         context->last_err_code = NIX_OK;
     try {
+        if (store == nullptr) {
+            nix_set_err_msg(context, NIX_ERR_UNKNOWN, "Store is null");
+            return nullptr;
+        }
+        if (hash == nullptr) {
+            nix_set_err_msg(context, NIX_ERR_UNKNOWN, "Hash is null");
+            return nullptr;
+        }
         std::optional<nix::StorePath> s = store->ptr->queryPathFromHashPart(hash);

Note: The existing nix_store_copy_closure function (line 344) also lacks null validation, so if following strict consistency with existing code, this could be considered optional.

🤖 Prompt for AI Agents
In `@src/libstore-c/nix_api_store.cc` around lines 456 - 470, The function
nix_store_query_path_from_hash_part lacks null checks for the store and hash
params; add validation at the top (after setting context->last_err_code =
NIX_OK) to return nullptr and set context->last_err_code = NIX_ERR_INVALID_ARG
when store is null or hash is null, mirroring the behavior in
nix_store_copy_path, so you never dereference store->ptr or use a null hash;
keep the existing try/catch and NIXC_CATCH_ERRS_NULL flow otherwise.


nix_err nix_store_copy_path(
nix_c_context * context, Store * srcStore, Store * dstStore, const StorePath * path, bool repair, bool checkSigs)
{
if (context)
context->last_err_code = NIX_OK;
try {
if (srcStore == nullptr)
return nix_set_err_msg(context, NIX_ERR_UNKNOWN, "Source store is null");

if (dstStore == nullptr)
return nix_set_err_msg(context, NIX_ERR_UNKNOWN, "Destination store is null");

if (path == nullptr)
return nix_set_err_msg(context, NIX_ERR_UNKNOWN, "Store path is null");

auto repairFlag = repair ? nix::RepairFlag::Repair : nix::RepairFlag::NoRepair;
auto checkSigsFlag = checkSigs ? nix::CheckSigsFlag::CheckSigs : nix::CheckSigsFlag::NoCheckSigs;
nix::copyStorePath(*srcStore->ptr, *dstStore->ptr, path->path, repairFlag, checkSigsFlag);
}
NIXC_CATCH_ERRS
}

} // extern "C"
24 changes: 24 additions & 0 deletions src/libstore-c/nix_api_store.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,30 @@ nix_err nix_derivation_get_outputs_and_optpaths(
nix_err nix_derivation_to_json(
nix_c_context * context, const nix_derivation * drv, nix_get_string_callback callback, void * userdata);

/**
* @brief Query the full store path given the hash part of a valid store
* path, or empty if no matching path is found.
*
* @param[out] context Optional, stores error information
* @param[in] store nix store reference
* @param[in] hash Hash part of path as a string
* @return Store path reference, NULL if no matching path is found.
*/
StorePath * nix_store_query_path_from_hash_part(nix_c_context * context, Store * store, const char * hash);

/**
* @brief Copy a path from one store to another.
*
* @param[out] context Optional, stores error information
* @param[in] srcStore nix source store reference
* @param[in] dstStore nix destination store reference
* @param[in] path The path to copy
* @param[in] repair Whether to repair the path
* @param[in] checkSigs Whether to check path signatures are trusted before copying
*/
nix_err nix_store_copy_path(
nix_c_context * context, Store * srcStore, Store * dstStore, const StorePath * path, bool repair, bool checkSigs);

// cffi end
#ifdef __cplusplus
}
Expand Down