libports: import fetchurl from world

Fixes #2578
This commit is contained in:
Norman Feske 2017-12-05 15:56:38 +01:00 committed by Christian Helmuth
parent a3c217757c
commit c9a5f0ce45
4 changed files with 271 additions and 0 deletions

View File

@ -0,0 +1,87 @@
#
# \brief Test of 'fetchurl
# \author Emery Hemingway
# \date 2016-06-05
#
set build_components {
core init
app/fetchurl
drivers/nic
drivers/timer
}
source ${genode_dir}/repos/base/run/platform_drv.inc
append_platform_drv_build_components
build $build_components
create_boot_directory
append config {
<config verbose="yes">
<parent-provides>
<service name="CPU"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="IRQ"/>
<service name="LOG"/>
<service name="PD"/>
<service name="RAM"/>
<service name="RM"/>
<service name="ROM"/>
</parent-provides>
<default caps="100"/>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>}
append_platform_drv_config
append config {
<start name="timer">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Timer"/> </provides>
</start>
<start name="nic_drv">
<resource name="RAM" quantum="4M"/>
<provides> <service name="Nic"/> </provides>
</start>
<start name="fetchurl" caps="500">
<resource name="RAM" quantum="8M"/>
<config>
<vfs> <dir name="dev"> <log/> <null/> </dir> </vfs>
<libc stdout="/dev/log" stderr="/dev/log"/>
<fetch url="http://genode.org/about/LICENSE" path="/dev/log"/>
</config>
</start>
</config>
}
install_config $config
# generic modules
set boot_modules {
core init ld.lib.so
curl.lib.so
fetchurl
libc.lib.so
libc.lib.so
libcrypto.lib.so
libm.lib.so
libssh.lib.so
libssl.lib.so
lwip.lib.so
nic_drv
timer
zlib.lib.so
}
# platform-specific modules
append_platform_drv_boot_modules
build_boot_image $boot_modules
append qemu_args " -nographic -net nic,model=e1000 -net user"
run_genode_until {child "fetchurl" exited with exit value 0} 120

View File

@ -0,0 +1,18 @@
A small frontend to the libcURL library.
Configuration
-------------
!<config>
! <libc stdout="/dev/log" stderr="/dev/log">
! <vfs>
! <dir name="dev"> <jitterentropy name="random"/> <log/> </dir>
! </vfs>
! </libc>
! <fetch url="http://genode.org/about/LICENSE" path="LICENSE"/>
!</config>
Optionally, you can use a proxy:
! <fetch url="http://genode.org/about/LICENSE" path="LICENSE"
! proxy="sock5://10.0.0.1:9050 />

View File

@ -0,0 +1,163 @@
/*
* \brief Native fetchurl utility for Nix
* \author Emery Hemingway
* \date 2016-03-08
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* Genode includes */
#include <timer_session/connection.h>
#include <os/path.h>
#include <base/attached_rom_dataspace.h>
#include <libc/component.h>
#include <base/log.h>
/* cURL includes */
#include <curl/curl.h>
/* Libc includes */
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
struct Stats
{
Timer::Connection &timer;
unsigned long next = 0;
unsigned long remain = 0;
char const *url;
Stats(Timer::Connection &t, char const *u)
: timer(t), url(u) { }
};
static size_t write_callback(char *ptr,
size_t size,
size_t nmemb,
void *userdata)
{
int *fd = (int*)userdata;
return write(*fd, ptr, size*nmemb);
}
int progress_callback(void *clientp,
double dltotal,
double dlnow,
double ultotal,
double ulnow)
{
Stats *stats = (Stats*)clientp;
unsigned long now = stats->timer.elapsed_ms();
unsigned long remain = dltotal-dlnow;
if ((now > stats->next) && (remain != stats->remain)) {
stats->next = now + 1000;
stats->remain = remain;
Genode::log(stats->url, ": ", remain, " bytes remain");
}
return CURLE_OK;
}
void Libc::Component::construct(Libc::Env &env)
{
Genode::Attached_rom_dataspace config(env, "config");
Timer::Connection timer(env);
/* wait for DHCP */
timer.msleep(4000);
Genode::String<256> url;
Genode::Path<256> path;
CURLcode res = CURLE_OK;
curl_global_init(CURL_GLOBAL_DEFAULT);
Genode::Xml_node config_node = config.xml();
bool verbose = config_node.attribute_value("verbose", false);
config_node.for_each_sub_node("fetch", [&] (Genode::Xml_node node) {
if (res != CURLE_OK) return;
try {
node.attribute("url").value(&url);
node.attribute("path").value(path.base(), path.capacity());
} catch (...) { Genode::error("error reading 'fetch' node"); return; }
char const *out_path = path.base();
int fd = open(out_path, O_CREAT | O_RDWR);
if (fd == -1) {
switch (errno) {
case EACCES:
Genode::error("permission denied at ", out_path); break;
case EEXIST:
Genode::error(out_path, " already exists"); break;
case EISDIR:
Genode::error(out_path, " is a directory"); break;
case ENOSPC:
Genode::error("cannot create ", out_path, ", out of space"); break;
}
env.parent().exit(errno);
return;
}
CURL *curl = curl_easy_init();
if (!curl) {
Genode::error("failed to initialize libcurl");
res = CURLE_FAILED_INIT;
return;
}
Stats stats(timer, url.string());
curl_easy_setopt(curl, CURLOPT_URL, url.string());
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, true);
curl_easy_setopt(curl, CURLOPT_VERBOSE, verbose);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, true);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &fd);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_callback);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &stats);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
/* check for optional proxy configuration */
try {
Genode::String<256> proxy;
node.attribute("proxy").value(&proxy);
curl_easy_setopt(curl, CURLOPT_PROXY, proxy.string());
} catch (...) { }
Libc::with_libc([&]() {
res = curl_easy_perform(curl);
close(fd);
if (res != CURLE_OK)
Genode::error(curl_easy_strerror(res));
curl_easy_cleanup(curl);
});
});
curl_global_cleanup();
Genode::warning("SSL certificates not verified");
env.parent().exit(res ^ CURLE_OK);
}

View File

@ -0,0 +1,3 @@
TARGET = fetchurl
LIBS += curl lwip libc_lwip libc_lwip_nic_dhcp libc
SRC_CC = component.cc