/** * Resolve base+relative URI * * @v base_uri Base URI, or NULL * @v relative_uri Relative URI * @ret resolved_uri Resolved URI * * Takes a base URI (e.g. "http://etherboot.org/kernels/vmlinuz" and a * relative URI (e.g. "../initrds/initrd.gz") and produces a new URI * (e.g. "http://etherboot.org/initrds/initrd.gz"). */ struct uri * resolve_uri ( struct uri *base_uri, struct uri *relative_uri ) { struct uri tmp_uri; char *tmp_path = NULL; struct uri *new_uri; /* If relative URI is absolute, just re-use it */ if ( uri_is_absolute ( relative_uri ) || ( ! base_uri ) ) return uri_get ( relative_uri ); /* Mangle URI */ memcpy ( &tmp_uri, base_uri, sizeof ( tmp_uri ) ); if ( relative_uri->path ) { tmp_path = resolve_path ( ( base_uri->path ? base_uri->path : "/" ), relative_uri->path ); tmp_uri.path = tmp_path; tmp_uri.query = relative_uri->query; tmp_uri.fragment = relative_uri->fragment; } else if ( relative_uri->query ) { tmp_uri.query = relative_uri->query; tmp_uri.fragment = relative_uri->fragment; } else if ( relative_uri->fragment ) { tmp_uri.fragment = relative_uri->fragment; } /* Create demangled URI */ new_uri = uri_dup ( &tmp_uri ); free ( tmp_path ); return new_uri; }
/** * Construct TFTP URI from next-server and filename * * @v next_server Next-server address * @v port Port number, or zero to use the default port * @v filename Filename * @ret uri URI, or NULL on failure * * TFTP filenames specified via the DHCP next-server field often * contain characters such as ':' or '#' which would confuse the * generic URI parser. We provide a mechanism for directly * constructing a TFTP URI from the next-server and filename. */ struct uri * tftp_uri ( struct in_addr next_server, unsigned int port, const char *filename ) { char buf[ 6 /* "65535" + NUL */ ]; struct uri uri; memset ( &uri, 0, sizeof ( uri ) ); uri.scheme = "tftp"; uri.host = inet_ntoa ( next_server ); if ( port ) { snprintf ( buf, sizeof ( buf ), "%d", port ); uri.port = buf; } uri.path = filename; return uri_dup ( &uri ); }
/** * Construct TFTP URI from server address and filename * * @v sa_server Server address * @v filename Filename * @ret uri URI, or NULL on failure */ static struct uri * tftp_uri ( struct sockaddr *sa_server, const char *filename ) { struct sockaddr_tcpip *st_server = ( ( struct sockaddr_tcpip * ) sa_server ); char buf[ 6 /* "65535" + NUL */ ]; char *path; struct uri tmp; struct uri *uri = NULL; /* Initialise TFTP URI */ memset ( &tmp, 0, sizeof ( tmp ) ); tmp.scheme = "tftp"; /* Construct TFTP server address */ tmp.host = sock_ntoa ( sa_server ); if ( ! tmp.host ) goto err_host; /* Construct TFTP server port, if applicable */ if ( st_server->st_port ) { snprintf ( buf, sizeof ( buf ), "%d", ntohs ( st_server->st_port ) ); tmp.port = buf; } /* Construct TFTP path */ if ( asprintf ( &path, "/%s", filename ) < 0 ) goto err_path; tmp.path = path; /* Demangle URI */ uri = uri_dup ( &tmp ); if ( ! uri ) goto err_uri; err_uri: free ( path ); err_path: err_host: return uri; }