505 lines
22 KiB
HTML
505 lines
22 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Everest Linux - Docs</title>
|
|
<link type="text/css" rel="stylesheet" href="../css/nord.css"/>
|
|
</head>
|
|
<body>
|
|
<!-- Navbar -->
|
|
<div class="sidenav">
|
|
<img src="../img/everest-nord.svg" alt="everest-logo">
|
|
<a href="../index.html">Home</a>
|
|
<a href="../about.html">About</a>
|
|
<a href="../install.html">Install</a>
|
|
<a href="../packages.html">Packages</a>
|
|
<a href="../download.html">Downloads</a>
|
|
<a href="home.html">Docs</a>
|
|
<a href="../errata.html">Errata</a>
|
|
<a href="https://git.everestlinux.org">Git ↗</a>
|
|
</div>
|
|
|
|
<!-- Rest of page -->
|
|
<div class="main">
|
|
<button onclick="window.location.href='home.html';">
|
|
Back to home
|
|
</button>
|
|
<h2>1 - Introduction</h2>
|
|
<p><cil>libglacier</cil> is the backend library for Glacier. It simplifies many functions and allows users to extend Glacier's functionality.</p>
|
|
<h2>2 - Installation</h2>
|
|
<p>In order to install <cil>libglacier</cil>, the following libraries must be installed:</p>
|
|
<ul>
|
|
<li><p>libcolor</p></li>
|
|
<li><p>libconfig</p></li>
|
|
</ul>
|
|
<p>Once these libraries are installed, clone the <cil>libglacier</cil> repository:</p>
|
|
<p><code>$ git clone https://git.everestlinux.org/EverestLinux/libglacier</code></p>
|
|
<p>Enter the repository and edit the make configuration file:</p>
|
|
<p><code>$ cd libglacier</code></p>
|
|
<p><code>$ ${EDITOR} config.mk</code></p>
|
|
<cautionhead><strong>CAUTION</strong></cautionhead>
|
|
<div class="caution">
|
|
<p>Before proceeding with ANY other step, make sure you define <cil_inv>PREFIX</cil_inv> in config.mk.</p>
|
|
<p>By default this variable is not defined. Results will be unexpected if the library is compiled without <cil_inv>PREFIX</cil_inv> defined.</p>
|
|
</div>
|
|
<p>Build the library:</p>
|
|
<p><code>$ make lib</code></p>
|
|
<notehead><strong>NOTE</strong></notehead>
|
|
<div class="note">
|
|
<p><cil_inv>libglacier</cil_inv> is provided as a static library only.</p>
|
|
<p>If you wish to compile a shared library instead, you must edit the Makefile</p>
|
|
</div>
|
|
<h2>3 - Using libglacier in a program</h2>
|
|
<p>To use <cil>libglacier</cil> in a program, include the relevant header files:</p>
|
|
<bigcodehead><strong>CODE:</strong> Including libglacier header files</bigcodehead>
|
|
<div class="bigcode">
|
|
<p>#include <glacier/config.h></p>
|
|
<p>#include <glacier/data.h></p>
|
|
<p>#include <glacier/log.h></p>
|
|
<p>#include <glacier/pkgops.h></p>
|
|
<p>#include <glacier/runtime.h></p>
|
|
<p>#include <glacier/security.h></p>
|
|
</div>
|
|
<p></p>
|
|
<p>To compile <cil>libglacier</cil> into your program, add the flag <cil>-lglacier</cil> to your build process.</p>
|
|
<p><code>$ gcc program.c -lglacier -o program</code></p>
|
|
<p></p>
|
|
<h2>4 - Configuration Functions</h2>
|
|
<p><cil>libglacier</cil> supplies functions for parsing and getting values from libconfig-syntax configuration files. While only three are present, more are planned for the future.</p>
|
|
<p><strong>4.1</strong> init_config</p>
|
|
<p><cil>init_config</cil> initializes the libconfig library, and allows configuration files to be parsed.</p>
|
|
<p>No parameters are accepted by <cil>init_config</cil>.</p>
|
|
<bigcodehead><strong>CODE:</strong> init_config used in a program</bigcodehead>
|
|
<div class="bigcode">
|
|
<p>#include <glacier/config.h></p>
|
|
<p><span class="tab"></span></p>
|
|
<p>int</p>
|
|
<p>main()</p>
|
|
<p>{</p>
|
|
<p><span class="tab"></span>if (init_config() != 0) {</p>
|
|
<p><span class="tab"></span><span class="tab"></span>errlog("failed to initialize libconfig");</p>
|
|
<p><span class="tab"></span><span class="tab"></span>return(EXIT_FAILURE);</p>
|
|
<p><span class="tab"></span>}</p>
|
|
<p><span class="tab"></span>else {</p>
|
|
<p><span class="tab"></span><span class="tab"></span>successlog("Initialized libconfig");</p>
|
|
<p><span class="tab"></span>}</p>
|
|
<p>}</p>
|
|
</div>
|
|
<p><cil>init_config</cil> returns 0 on success, and 1 on failure.</p>
|
|
<hr>
|
|
<p><strong>4.2</strong> die_config</p>
|
|
<p><cil>die_config</cil> unloads the libconfig library. You should always run this when you're finished with libconfig in order to free memory.</p>
|
|
<p>No parameters are accepted by <cil>die_config</cil>.</p>
|
|
<bigcodehead><strong>CODE:</strong> die_config used in a program</bigcodehead>
|
|
<div class="bigcode">
|
|
<p>#include <glacier/config.h></p>
|
|
<p><span class="tab"></span></p>
|
|
<p>int</p>
|
|
<p>main()</p>
|
|
<p>{</p>
|
|
<p><span class="tab"></span>die_config();</p>
|
|
<p>}</p>
|
|
</div>
|
|
<p><cil>die_config</cil> returns 0 on success, and 1 on failure.</p>
|
|
<hr>
|
|
<p><strong>4.3</strong> load_all_from_config</p>
|
|
<p><cil>load_all_from_config</cil> loads all expected settings from /etc/glacier.cfg.</p>
|
|
<p>No parameters are accepted by <cil>load_all_from_config</cil>.</p>
|
|
<bigcodehead><strong>CODE:</strong> load_all_from_config used in a program</bigcodehead>
|
|
<div class="bigcode">
|
|
<p>#include <glacier/config.h></p>
|
|
<p><span class="tab"></span></p>
|
|
<p>int</p>
|
|
<p>main()</p>
|
|
<p>{</p>
|
|
<p><span class="tab"></span>init_config();</p>
|
|
<p>}</p>
|
|
</div>
|
|
<p><cil>load_all_from_config</cil> returns 0 on success, and 1 on failure.</p>
|
|
<h2>5 - Data structure functions</h2>
|
|
<p>Since Glacier is a package manager, <cil>libglacier</cil> provides functions for creating and handling dependency trees.</p>
|
|
<p><strong>5.1</strong> create_node</p>
|
|
<p><cil>create_node</cil> creates a node for a dependency tree.</p>
|
|
<p><cil>create_node</cil> accepts the following parameters:</p>
|
|
<ul>
|
|
<li><p><cil>char *data</cil> (the name of the node to create)</p></li>
|
|
</ul>
|
|
<bigcodehead><strong>CODE:</strong> create_node used in a program</bigcodehead>
|
|
<div class="bigcode">
|
|
<p>#include <glacier/data.h></p>
|
|
<p><span class="tab"></span></p>
|
|
<p>int</p>
|
|
<p>main()</p>
|
|
<p>{</p>
|
|
<p><span class="tab"></span>struct node package = create_node("Package");</p>
|
|
<p>}</p>
|
|
</div>
|
|
<p><cil>create_node</cil> returns a node structure.</p>
|
|
<hr>
|
|
<p><strong>5.2</strong> add_child</p>
|
|
<p><cil>add_child</cil> adds a specified child node to a parent node.</p>
|
|
<p><cil>add_child</cil> accepts the following parameters:</p>
|
|
<ul>
|
|
<li><p><cil>struct node *parent</cil> (the parent node which the child will be added to)</p></li>
|
|
<li><p><cil>struct node *child</cil> (the child node which will be added to the parent node)</p></li>
|
|
</ul>
|
|
<bigcodehead><strong>CODE:</strong> add_child used in a program</bigcodehead>
|
|
<div class="bigcode">
|
|
<p>#include <glacier/data.h></p>
|
|
<p><span class="tab"></span></p>
|
|
<p>int</p>
|
|
<p>main()</p>
|
|
<p>{</p>
|
|
<p><span class="tab"></span>struct node pack = create_node("pack");
|
|
<p><span class="tab"></span>struct node dep1 = create_node("dep1");
|
|
<p><span class="tab"></span>add_child(pack, dep1);</p>
|
|
<p>}</p>
|
|
</div>
|
|
<p><cil>add_child</cil> returns 0 on success, and 1 on failure.</p>
|
|
<hr>
|
|
<p><strong>5.3</strong> print_tree</p>
|
|
<p><cil>print_tree</cil> prints a dependency tree specified at its root node.</p>
|
|
<p><cil>print_tree</cil> accepts the following parameters:</p>
|
|
<ul>
|
|
<li><p><cil>struct node *root</cil> (the root node of the tree to print</p></li>
|
|
<li><p><cil>int level</cil> (the number of levels to descend)</p></li>
|
|
</ul>
|
|
<bigcodehead><strong>CODE:</strong> print_tree used in a program</bigcodehead>
|
|
<div class="bigcode">
|
|
<p>#include <glacier/data.h></p>
|
|
<p><span class="tab"></span></p>
|
|
<p>int</p>
|
|
<p>main()</p>
|
|
<p>{</p>
|
|
<p><span class="tab"></span>struct node pack = create_node("pack");</p>
|
|
<p><span class="tab"></span>struct node dep1 = create_node("dep1");</p>
|
|
<p><span class="tab"></span>add_child(pack, dep1);</p>
|
|
<p><span class="tab"></span>print_tree(pack, 0);</p>
|
|
<p>}</p>
|
|
</div>
|
|
<p><cil>print_tree</cil> returns 0 on success.</p>
|
|
<hr>
|
|
<p><strong>5.4</strong> init_queue</p>
|
|
<p><cil>init_queue</cil> initializes a queue data structure.</p>
|
|
<notehead><strong>REMOVED FEATURE</strong></notehead>
|
|
<div class="note">
|
|
<p>The queue data structure was removed in a recent update (March 2025). This function is no longer available in the current version of libglacier.</p>
|
|
</div>
|
|
<p><cil>init_queue</cil> accepts the following parameters:</p>
|
|
<ul>
|
|
<li><p><cil>queue *q</cil> (the name of the queue to initialize</p></li>
|
|
</ul>
|
|
<bigcodehead><strong>CODE:</strong> init_queue used in a program</bigcodehead>
|
|
<div class="bigcode">
|
|
<p>#include <glacier/data.h></p>
|
|
<p><span class="tab"></span></p>
|
|
<p>int</p>
|
|
<p>main()</p>
|
|
<p>{</p>
|
|
<p><span class="tab"></span>/* Queue implementation removed */</p>
|
|
<p>}</p>
|
|
</div>
|
|
<h2>6 - Logging Functions</h2>
|
|
<p>The logging functions <cil>libglacier</cil> provides are designed to allow a uniform style of output. </p>
|
|
<p>The following logging functions are included:</p>
|
|
<ul>
|
|
<li><p><cil>infolog</cil></p></li>
|
|
<li><p><cil>warnlog</cil></p></li>
|
|
<li><p><cil>errlog</cil></p></li>
|
|
<li><p><cil>successlog</cil></p></li>
|
|
</ul>
|
|
<p>These four functions accept the following parameters:</p>
|
|
<ul>
|
|
<li><p><cil>char MSG</cil> (the message to output</p></li>
|
|
</ul>
|
|
<p></p>
|
|
<notehead><strong>NOTE:</strong></notehead>
|
|
<div class="note">
|
|
<p>Logging functions do not require a newline character ('\n'), they will automatically place one after the message.</p>
|
|
</div>
|
|
<p></p>
|
|
<p>All logging functions return 0 on success, and 1 on failure.</p>
|
|
<bigcodehead><strong>CODE:</strong> Logging functions used in a program</bigcodehead>
|
|
<div class="bigcode">
|
|
<p>#include <glacier/log.h></p>
|
|
<p><span class="tab"></span></p>
|
|
<p>int</p>
|
|
<p>main()</p>
|
|
<p>{</p>
|
|
<p><span class="tab"></span>infolog("This is an info message");</p>
|
|
<p><span class="tab"></span>warnlog("This is a warning message");</p>
|
|
<p><span class="tab"></span>errlog("This is an error message");</p>
|
|
<p><span class="tab"></span>successlog("This is a success message");</p>
|
|
<p>}</p>
|
|
</div>
|
|
<h2>7 - Package Operation Functions</h2>
|
|
<p>This section describes the numerous functions related to operations on packages.</p>
|
|
<p><strong>7.1</strong> mkworkspace</p>
|
|
<p><cil>mkworkspace</cil> creates a Glacier workspace at <cil>/tmp/glacier-workspace</cil>.</p>
|
|
<p><cil>mkworkspace</cil> accepts no parameters.</p>
|
|
<bigcodehead><strong>CODE:</strong> mkworkspace used in a program</bigcodehead>
|
|
<div class="bigcode">
|
|
<p>#include <glacier/pkgops.h></p>
|
|
<p><span class="tab"></span></p>
|
|
<p>int</p>
|
|
<p>main()</p>
|
|
<p>{</p>
|
|
<p><span class="tab"></span>mkworkspace();</p>
|
|
<p>}</p>
|
|
</div>
|
|
<p><cil>mkworkspace</cil> returns the following values:</p>
|
|
<ul>
|
|
<li><p>0 on success</p></li>
|
|
<li><p>2 on library error</p></li>
|
|
</ul>
|
|
<p>Calling <cil>mkworkspace</cil> creates the workspace if it doesn't already exist.</p>
|
|
<hr>
|
|
<p><strong>7.2</strong> prepare_pkg</p>
|
|
<p><cil>prepare_pkg</cil> copies a package archive from the local package database to the workspace, and untars it.</p>
|
|
<p><cil>prepare_pkg</cil> accepts the following parameters:</p>
|
|
<ul>
|
|
<li><p><cil>char PACKAGE[]</cil> (the package file to prepare)</p></li>
|
|
</ul>
|
|
<bigcodehead><strong>CODE:</strong> prepare_pkg used in a program</bigcodehead>
|
|
<div class="bigcode">
|
|
<p>#include <glacier/pkgops.h></p>
|
|
<p><span class="tab"></span></p>
|
|
<p>int</p>
|
|
<p>main()</p>
|
|
<p>{</p>
|
|
<p><span class="tab"></span>prepare_pkg("/glacier/localdb/epkgs-x86_64-musl/foo.tar");</p>
|
|
<p>}</p>
|
|
</div>
|
|
<p><cil>prepare_pkg</cil> returns the following values:</p>
|
|
<ul>
|
|
<li><p>0 on success</p></li>
|
|
<li><p>1 on package does not exist, or error untarring</p></li>
|
|
</ul>
|
|
<cautionhead><strong>CAUTION:</strong></cautionhead>
|
|
<div class="caution">
|
|
<p>This example presented is not the best. Instead of manually specifying the package directory, you should be calling the system profile.</p>
|
|
</div>
|
|
<hr>
|
|
<p><strong>7.3</strong> run_make_task</p>
|
|
<p><cil>run_make_task</cil> runs a specified make task in a package's current working directory.</p>
|
|
<p><cil>run_make_task</cil> accepts the following parameters:</p>
|
|
<ul>
|
|
<li><p><cil>char TASK[]</cil> (the make task to run</p></li>
|
|
</ul>
|
|
<bigcodehead><strong>CODE:</strong> run_make_task used in a program</bigcodehead>
|
|
<div class="bigcode">
|
|
<p>#include <glacier/pkgops.h></p>
|
|
<p><span class="tab"></span></p>
|
|
<p>int</p>
|
|
<p>main()</p>
|
|
<p>{</p>
|
|
<p><span class="tab"></span>prepare_pkg("/glacier/localdb/epkgs-x86_64-musl/foo.tar");</p>
|
|
<p><span class="tab"></span>run_make_task("installpkg");</p>
|
|
<p>}</p>
|
|
</div>
|
|
<p><cil>run_make_task</cil> returns the following values:</p>
|
|
<ul>
|
|
<li><p>0 on success</p></li>
|
|
<li><p>1 on failure</p></li>
|
|
</ul>
|
|
<h2>8 - Runtime Functions</h2>
|
|
<p>The functions described here are used for various runtime checks.</p>
|
|
<p><strong>8.1</strong> runtime_exists</p>
|
|
<p><cil>runtime_exists</cil> checks if necessary runtime files exist and are in their correct locations.</p>
|
|
<p><cil>runtime_exists</cil> accepts no parameters.</p>
|
|
<bigcodehead><strong>CODE:</strong> runtime_exists used in a program</bigcodehead>
|
|
<div class="bigcode">
|
|
<p>#include <glacier/runtime.h></p>
|
|
<p><span class="tab"></span></p>
|
|
<p>int</p>
|
|
<p>main()</p>
|
|
<p>{</p>
|
|
<p><span class="tab"></span>runtime_exists();</p>
|
|
<p>}</p>
|
|
</div>
|
|
<p><cil>runtime_exists</cil> returns no values.</p>
|
|
<hr>
|
|
<p><strong>8.2</strong> is_process_root</p>
|
|
<p><cil>is_process_root</cil> verifies if the process has root privileges to perform package operations.</p>
|
|
<p><cil>is_process_root</cil> accepts no parameters.</p>
|
|
<bigcodehead><strong>CODE:</strong> is_process_root used in a program</bigcodehead>
|
|
<div class="bigcode">
|
|
<p>#include <glacier/runtime.h></p>
|
|
<p><span class="tab"></span></p>
|
|
<p>int</p>
|
|
<p>main()</p>
|
|
<p>{</p>
|
|
<p><span class="tab"></span>if (is_process_root() != 0) {</p>
|
|
<p><span class="tab"></span><span class="tab"></span>errlog("insufficient permissions to perform package operations");</p>
|
|
<p><span class="tab"></span><span class="tab"></span>return(EXIT_FAILURE);</p>
|
|
<p><span class="tab"></span>}</p>
|
|
<p>}</p>
|
|
</div>
|
|
<p><cil>is_process_root</cil> returns the following values:</p>
|
|
<ul>
|
|
<li><p>0 on sufficient permissions (process is root)</p></li>
|
|
<li><p>1 on insufficient permissions (process is not root)</p></li>
|
|
</ul>
|
|
<hr>
|
|
<p><strong>8.3</strong> get_system_profile</p>
|
|
<p><cil>get_system_profile</cil> fetches the system profile, which contains information about the architecture and libc implementation.</p>
|
|
<p><cil>get_system_profile</cil> accepts no parameters.</p>
|
|
<bigcodehead><strong>CODE:</strong> get_system_profile used in a program</bigcodehead>
|
|
<div class="bigcode">
|
|
<p>#include <glacier/runtime.h></p>
|
|
<p><span class="tab"></span></p>
|
|
<p>int</p>
|
|
<p>main()</p>
|
|
<p>{</p>
|
|
<p><span class="tab"></span>char *profile = get_system_profile();</p>
|
|
<p><span class="tab"></span>infolog(profile);</p>
|
|
<p>}</p>
|
|
</div>
|
|
<p><cil>get_system_profile</cil> returns a pointer to a string containing the system profile (e.g., "x86_64-musl").</p>
|
|
<h2>9 - Security Functions</h2>
|
|
<p>These functions provide security checks for package integrity and signatures.</p>
|
|
<p><strong>9.1</strong> verify_signature</p>
|
|
<p><cil>verify_signature</cil> checks if a package's signature is valid against the trusted keyring.</p>
|
|
<notehead><strong>UPCOMING FEATURE</strong></notehead>
|
|
<div class="note">
|
|
<p>This function is planned for a future release and is not yet implemented in the current version of libglacier.</p>
|
|
</div>
|
|
<p><cil>verify_signature</cil> accepts the following parameters:</p>
|
|
<ul>
|
|
<li><p><cil>char PACKAGE[]</cil> (the package file to verify)</p></li>
|
|
<li><p><cil>char SIGNATURE[]</cil> (the signature file to check against)</p></li>
|
|
</ul>
|
|
<bigcodehead><strong>CODE:</strong> verify_signature used in a program</bigcodehead>
|
|
<div class="bigcode">
|
|
<p>#include <glacier/security.h></p>
|
|
<p><span class="tab"></span></p>
|
|
<p>int</p>
|
|
<p>main()</p>
|
|
<p>{</p>
|
|
<p><span class="tab"></span>if (verify_signature("package.tar", "package.tar.sig") != 0) {</p>
|
|
<p><span class="tab"></span><span class="tab"></span>errlog("invalid package signature");</p>
|
|
<p><span class="tab"></span><span class="tab"></span>return(EXIT_FAILURE);</p>
|
|
<p><span class="tab"></span>}</p>
|
|
<p><span class="tab"></span>return(EXIT_SUCCESS);</p>
|
|
<p>}</p>
|
|
</div>
|
|
<p><cil>verify_signature</cil> returns the following values:</p>
|
|
<ul>
|
|
<li><p>0 on valid signature</p></li>
|
|
<li><p>1 on invalid signature</p></li>
|
|
<li><p>2 on file not found</p></li>
|
|
</ul>
|
|
<hr>
|
|
<p><strong>9.2</strong> check_integrity</p>
|
|
<p><cil>check_integrity</cil> verifies a package's SHA256 checksum against the expected value.</p>
|
|
<notehead><strong>UPCOMING FEATURE</strong></notehead>
|
|
<div class="note">
|
|
<p>This function is planned for a future release and is not yet implemented in the current version of libglacier.</p>
|
|
<p>Note that the underlying functions for calculating file hashes (<cil_inv>hash_file()</cil_inv>, <cil_inv>stash_hash()</cil_inv>, <cil_inv>print_hash()</cil_inv>) are already implemented.</p>
|
|
</div>
|
|
<p><cil>check_integrity</cil> accepts the following parameters:</p>
|
|
<ul>
|
|
<li><p><cil>char PACKAGE[]</cil> (the package file to check)</p></li>
|
|
<li><p><cil>char EXPECTED_HASH[]</cil> (the expected SHA256 hash)</p></li>
|
|
</ul>
|
|
<bigcodehead><strong>CODE:</strong> check_integrity used in a program</bigcodehead>
|
|
<div class="bigcode">
|
|
<p>#include <glacier/security.h></p>
|
|
<p><span class="tab"></span></p>
|
|
<p>int</p>
|
|
<p>main()</p>
|
|
<p>{</p>
|
|
<p><span class="tab"></span>char *expected = "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592";</p>
|
|
<p><span class="tab"></span>if (check_integrity("package.tar", expected) != 0) {</p>
|
|
<p><span class="tab"></span><span class="tab"></span>errlog("package integrity check failed");</p>
|
|
<p><span class="tab"></span><span class="tab"></span>return(EXIT_FAILURE);</p>
|
|
<p><span class="tab"></span>}</p>
|
|
<p><span class="tab"></span>return(EXIT_SUCCESS);</p>
|
|
<p>}</p>
|
|
</div>
|
|
<p><cil>check_integrity</cil> returns the following values:</p>
|
|
<ul>
|
|
<li><p>0 on hash match</p></li>
|
|
<li><p>1 on hash mismatch</p></li>
|
|
<li><p>2 on file not found or hash calculation error</p></li>
|
|
</ul>
|
|
<h2>10 - Advanced Usage</h2>
|
|
<p>This section covers more advanced usage patterns for <cil>libglacier</cil>.</p>
|
|
<p><strong>10.1</strong> Custom dependency tree handling</p>
|
|
<p>While <cil>libglacier</cil> provides functions for creating and manipulating dependency trees, you might need to implement custom behaviors for resolving dependencies.</p>
|
|
<bigcodehead><strong>CODE:</strong> Custom dependency resolution</bigcodehead>
|
|
<div class="bigcode">
|
|
<p>#include <glacier/data.h></p>
|
|
<p>#include <glacier/log.h></p>
|
|
<p><span class="tab"></span></p>
|
|
<p>int</p>
|
|
<p>resolve_dependencies(struct node *root)</p>
|
|
<p>{</p>
|
|
<p><span class="tab"></span>/* Custom dependency resolution logic here */</p>
|
|
<p><span class="tab"></span>for (int i = 0; i < root->num_children; i++) {</p>
|
|
<p><span class="tab"></span><span class="tab"></span>infolog(root->children[i]->data);</p>
|
|
<p><span class="tab"></span><span class="tab"></span>/* Process child dependencies recursively */</p>
|
|
<p><span class="tab"></span><span class="tab"></span>resolve_dependencies(root->children[i]);</p>
|
|
<p><span class="tab"></span>}</p>
|
|
<p><span class="tab"></span>return(0);</p>
|
|
<p>}</p>
|
|
<p><span class="tab"></span></p>
|
|
<p>int</p>
|
|
<p>main()</p>
|
|
<p>{</p>
|
|
<p><span class="tab"></span>struct node *root = create_node("base-package");</p>
|
|
<p><span class="tab"></span>struct node *dep1 = create_node("dependency1");</p>
|
|
<p><span class="tab"></span>struct node *dep2 = create_node("dependency2");</p>
|
|
<p><span class="tab"></span>add_child(root, dep1);</p>
|
|
<p><span class="tab"></span>add_child(root, dep2);</p>
|
|
<p><span class="tab"></span>resolve_dependencies(root);</p>
|
|
<p><span class="tab"></span>return(EXIT_SUCCESS);</p>
|
|
<p>}</p>
|
|
</div>
|
|
<hr>
|
|
<p><strong>10.2</strong> Error handling best practices</p>
|
|
<p>When using <cil>libglacier</cil>, it's important to implement proper error handling. All functions that return integer status codes should be checked.</p>
|
|
<bigcodehead><strong>CODE:</strong> Proper error handling</bigcodehead>
|
|
<div class="bigcode">
|
|
<p>#include <glacier/config.h></p>
|
|
<p>#include <glacier/log.h></p>
|
|
<p>#include <glacier/pkgops.h></p>
|
|
<p><span class="tab"></span></p>
|
|
<p>int</p>
|
|
<p>main()</p>
|
|
<p>{</p>
|
|
<p><span class="tab"></span>/* Initialize configuration */</p>
|
|
<p><span class="tab"></span>if (init_config() != 0) {</p>
|
|
<p><span class="tab"></span><span class="tab"></span>errlog("failed to initialize configuration");</p>
|
|
<p><span class="tab"></span><span class="tab"></span>return(EXIT_FAILURE);</p>
|
|
<p><span class="tab"></span>}</p>
|
|
<p><span class="tab"></span></p>
|
|
<p><span class="tab"></span>/* Create workspace */</p>
|
|
<p><span class="tab"></span>if (mkworkspace() != 0) {</p>
|
|
<p><span class="tab"></span><span class="tab"></span>errlog("failed to create workspace");</p>
|
|
<p><span class="tab"></span><span class="tab"></span>die_config();</p>
|
|
<p><span class="tab"></span><span class="tab"></span>return(EXIT_FAILURE);</p>
|
|
<p><span class="tab"></span>}</p>
|
|
<p><span class="tab"></span></p>
|
|
<p><span class="tab"></span>/* Always clean up resources */</p>
|
|
<p><span class="tab"></span>die_config();</p>
|
|
<p><span class="tab"></span>return(EXIT_SUCCESS);</p>
|
|
<p>}</p>
|
|
</div>
|
|
<p></p>
|
|
<notehead><strong>NOTE:</strong></notehead>
|
|
<div class="note">
|
|
<p>Always free resources and clean up configurations when your program exits, even on error paths.</p>
|
|
<p>This prevents memory leaks and ensures consistent behavior.</p>
|
|
</div>
|
|
</div>
|
|
<footer>
|
|
<p>Page last updated 03/22/25 @ 15:45</p>
|
|
<p>Page licensed under GNU Free Documentation License 1.3 or later</p>
|
|
<p>--------------------</p>
|
|
<p>Copyright (C) 2021-2025 Everest Linux</p>
|
|
<p>Linux (R) is a registered trademark of Linus Torvalds.</p>
|
|
<p>Everest Linux is provided AS IS, WITHOUT WARRANTY.</p>
|
|
</footer>
|