]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[settings] Expose current working URI and directory URI via settings
authorMichael Brown <mcb30@ipxe.org>
Tue, 19 Mar 2024 13:22:57 +0000 (13:22 +0000)
committerMichael Brown <mcb30@ipxe.org>
Tue, 19 Mar 2024 13:33:21 +0000 (13:33 +0000)
iPXE maintains a concept of a current working URI, which is used when
resolving relative URIs and allows scripts to download files using
URIs relative to the script itself.

There are situations in which it is valuable for a script to be able
to access the URI explicitly as a string, not just implicitly as a
base URI for subsequent downloads.  For example, when booting a Fedora
installer, the "inst.repo" command-line parameter may be used to pass
the URI of the repository to the installer.

Expose the current working URI as ${cwuri}.  Since relative URIs may
be constructed as strings only from a directory URI (not from a full
URI), also expose the current working directory URI as ${cwduri}.

This feature may be used as e.g.

  #!ipxe
  echo Booting from ${cwuri}
  prompt -k 0x197e -t 2000 Press F12 to install Fedora... || exit
  kernel images/pxeboot/vmlinux inst.repo=${cwduri}
  initrd images/pxeboot/initrd.img
  boot

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/core/settings.c
src/tests/uri_test.c

index 4593876f0c82e061aa92a334ce2554fa8d63dcad..9fbf753ab1a8f2b6d8161c6d143f74f8607f53bc 100644 (file)
@@ -2650,6 +2650,113 @@ struct builtin_setting unixtime_builtin_setting __builtin_setting = {
        .fetch = unixtime_fetch,
 };
 
+/**
+ * Fetch current working URI-related setting
+ *
+ * @v data             Buffer to fill with setting data
+ * @v len              Length of buffer
+ * @v rel              Relative URI string
+ * @ret len            Length of setting data, or negative error
+ */
+static int cwuri_fetch_uri ( void *data, size_t len, const char *rel ) {
+       struct uri *reluri;
+       struct uri *uri;
+       char *uristring;
+       int ret;
+
+       /* Check that current working URI is set */
+       if ( ! cwuri ) {
+               ret = -ENOENT;
+               goto err_unset;
+       }
+
+       /* Construct relative URI */
+       reluri = parse_uri ( rel );
+       if ( ! reluri ) {
+               ret = -ENOMEM;
+               goto err_parse;
+       }
+
+       /* Construct resolved URI */
+       uri = resolve_uri ( cwuri, reluri );
+       if ( ! uri ) {
+               ret = -ENOMEM;
+               goto err_resolve;
+       }
+
+       /* Format URI string into allocated buffer (with NUL) */
+       uristring = format_uri_alloc ( uri );
+       if ( ! uristring ) {
+               ret = -ENOMEM;
+               goto err_format;
+       }
+
+       /* Copy URI string to buffer */
+       strncpy ( data, uristring, len );
+       ret = strlen ( uristring );
+
+       free ( uristring );
+ err_format:
+       uri_put ( uri );
+ err_resolve:
+       uri_put ( reluri );
+ err_parse:
+ err_unset:
+       return ret;
+}
+
+/**
+ * Fetch current working URI setting
+ *
+ * @v data             Buffer to fill with setting data
+ * @v len              Length of buffer
+ * @ret len            Length of setting data, or negative error
+ */
+static int cwuri_fetch ( void *data, size_t len ) {
+
+       return cwuri_fetch_uri ( data, len, "" );
+}
+
+/**
+ * Fetch current working directory URI setting
+ *
+ * @v data             Buffer to fill with setting data
+ * @v len              Length of buffer
+ * @ret len            Length of setting data, or negative error
+ */
+static int cwduri_fetch ( void *data, size_t len ) {
+
+       return cwuri_fetch_uri ( data, len, "." );
+}
+
+/** Current working URI setting */
+const struct setting cwuri_setting __setting ( SETTING_MISC, cwuri ) = {
+       .name = "cwuri",
+       .description = "Current working URI",
+       .type = &setting_type_string,
+       .scope = &builtin_scope,
+};
+
+/** Current working directory URI setting */
+const struct setting cwduri_setting __setting ( SETTING_MISC, cwduri ) = {
+       .name = "cwduri",
+       .description = "Current working directory URI",
+       .type = &setting_type_string,
+       .scope = &builtin_scope,
+};
+
+/** Current working URI built-in setting */
+struct builtin_setting cwuri_builtin_setting __builtin_setting = {
+       .setting = &cwuri_setting,
+       .fetch = cwuri_fetch,
+};
+
+/** Current working directory URI built-in setting */
+struct builtin_setting cwduri_builtin_setting __builtin_setting = {
+       .setting = &cwduri_setting,
+       .fetch = cwduri_fetch,
+};
+
 /**
  * Fetch built-in setting
  *
index 9d2f6dba5c068e8b40ff5178296f8cab77b81d45..7ce87a20813ca2b706a855770aa0133f0faa5672 100644 (file)
@@ -754,6 +754,20 @@ static struct uri_resolve_test uri_fragment = {
        "http://192.168.0.254/test#bar",
 };
 
+/** Empty relative URI resolution test */
+static struct uri_resolve_test uri_self = {
+       "http://192.168.0.1/path/to/me",
+       "",
+       "http://192.168.0.1/path/to/me",
+};
+
+/** Current directory URI resolution test */
+static struct uri_resolve_test uri_cwd = {
+       "http://192.168.0.1/path/to/me",
+       ".",
+       "http://192.168.0.1/path/to/",
+};
+
 /** PXE URI with absolute URI */
 static struct uri_pxe_test uri_pxe_absolute = {
        {
@@ -996,6 +1010,8 @@ static void uri_test_exec ( void ) {
        uri_resolve_ok ( &uri_absolute_uri_path );
        uri_resolve_ok ( &uri_query );
        uri_resolve_ok ( &uri_fragment );
+       uri_resolve_ok ( &uri_self );
+       uri_resolve_ok ( &uri_cwd );
 
        /* PXE URI construction tests */
        uri_pxe_ok ( &uri_pxe_absolute );