2011-12-22 16:19:25 +01:00
|
|
|
/*
|
2017-07-07 12:32:09 +02:00
|
|
|
* \brief Libc file-system test
|
2011-12-22 16:19:25 +01:00
|
|
|
* \author Christian Prochaska
|
|
|
|
* \author Norman Feske
|
|
|
|
* \date 2011-05-27
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-02-20 13:23:52 +01:00
|
|
|
* Copyright (C) 2011-2017 Genode Labs GmbH
|
2011-12-22 16:19:25 +01:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
2017-02-20 13:23:52 +01:00
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
2011-12-22 16:19:25 +01:00
|
|
|
*/
|
|
|
|
|
2012-07-10 16:02:15 +02:00
|
|
|
/* Genode includes */
|
2017-03-07 15:16:15 +01:00
|
|
|
#include <base/attached_rom_dataspace.h>
|
|
|
|
#include <libc/component.h>
|
2012-07-10 16:02:15 +02:00
|
|
|
|
2011-12-22 16:19:25 +01:00
|
|
|
/* libc includes */
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <stdio.h>
|
2015-11-12 11:54:12 +01:00
|
|
|
#include <stdlib.h>
|
2011-12-22 16:19:25 +01:00
|
|
|
#include <sys/stat.h>
|
2012-07-12 17:08:59 +02:00
|
|
|
#include <sys/uio.h>
|
2011-12-22 16:19:25 +01:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
|
2017-03-07 15:16:15 +01:00
|
|
|
struct Test_failed : Genode::Exception { };
|
|
|
|
|
|
|
|
#define CALL_AND_CHECK(ret, operation, condition, info_string, ...) \
|
|
|
|
printf("calling " #operation " " info_string "\n", ##__VA_ARGS__); \
|
|
|
|
ret = operation; \
|
|
|
|
if (condition) { \
|
|
|
|
printf(#operation " succeeded\n"); \
|
|
|
|
} else { \
|
|
|
|
printf(#operation " failed, " #ret "=%ld, errno=%d\n", (long)ret, errno); \
|
|
|
|
throw Test_failed(); \
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void test_write_read(Genode::Xml_node node)
|
2015-11-12 11:54:12 +01:00
|
|
|
{
|
|
|
|
size_t rounds = 4;
|
|
|
|
size_t size = 4*1024*1024;
|
|
|
|
size_t buffer_size = 32*1024;
|
|
|
|
|
|
|
|
try {
|
2017-03-07 15:16:15 +01:00
|
|
|
Genode::Xml_node config = node.sub_node("write-read");
|
2015-11-12 11:54:12 +01:00
|
|
|
|
2019-01-21 15:59:00 +01:00
|
|
|
rounds = config.attribute_value("rounds", rounds);
|
2015-11-12 11:54:12 +01:00
|
|
|
|
2019-01-21 15:59:00 +01:00
|
|
|
Genode::Number_of_bytes n { };
|
2015-11-12 11:54:12 +01:00
|
|
|
try {
|
2019-01-21 15:59:00 +01:00
|
|
|
config.attribute("size").value(n);
|
2015-11-12 11:54:12 +01:00
|
|
|
size = n;
|
|
|
|
} catch (...) { }
|
|
|
|
try {
|
2019-01-21 15:59:00 +01:00
|
|
|
config.attribute("buffer_size").value(n);
|
2015-11-12 11:54:12 +01:00
|
|
|
buffer_size = n;
|
|
|
|
} catch (...) { }
|
|
|
|
} catch (...) { }
|
|
|
|
|
|
|
|
void *buf = malloc(buffer_size);
|
|
|
|
char const *file_name = "write_read.tst";
|
|
|
|
|
|
|
|
printf("write-read test: %zu rounds of %zu MiB (buffer size %zu)\n",
|
|
|
|
rounds, size/(1024*1024), buffer_size);
|
|
|
|
|
|
|
|
for (unsigned round = 0; buf && round < rounds; ++round) {
|
|
|
|
printf("starting round %u\n", round);
|
|
|
|
|
|
|
|
unlink(file_name);
|
|
|
|
|
|
|
|
int fd = open(file_name, O_CREAT | O_RDWR);
|
|
|
|
|
|
|
|
memset(buf, round, buffer_size);
|
|
|
|
|
|
|
|
/* write-read i_max times the buffer */
|
|
|
|
unsigned const i_max = size/buffer_size;
|
|
|
|
for (unsigned i = 0; i < i_max; ++i) write(fd, buf, buffer_size);
|
|
|
|
lseek(fd, SEEK_SET, 0);
|
|
|
|
for (unsigned i = 0; i < i_max; ++i) read(fd, buf, buffer_size);
|
|
|
|
|
|
|
|
close(fd);
|
|
|
|
printf("finished round %u\n", round);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-07 15:16:15 +01:00
|
|
|
static void test(Genode::Xml_node node)
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
|
|
|
int ret, fd;
|
2012-07-12 16:42:59 +02:00
|
|
|
ssize_t count;
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2020-05-04 14:39:51 +02:00
|
|
|
char const *trailing_slash_dir_name = "testdir/";
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2020-05-04 14:39:51 +02:00
|
|
|
char const *dir_name = "testdir";
|
|
|
|
char const *dir_name2 = "testdir2";
|
|
|
|
char const *file_name = "test.tst";
|
|
|
|
char const *file_name2 = "test2.tst";
|
|
|
|
char const *file_name3 = "test3.tst";
|
|
|
|
char const *file_name4 = "test4.tst";
|
|
|
|
char const *file_name5 = "test5.tst";
|
|
|
|
char const *pattern = "a single line of text";
|
|
|
|
|
|
|
|
size_t const pattern_size = strlen(pattern) + 1;
|
2012-07-12 16:42:59 +02:00
|
|
|
|
2012-07-10 16:02:15 +02:00
|
|
|
unsigned int iterations = 1;
|
|
|
|
|
|
|
|
try {
|
2019-01-21 15:59:00 +01:00
|
|
|
node.sub_node("iterations").attribute("value").value(iterations);
|
2012-07-10 16:02:15 +02:00
|
|
|
} catch(...) { }
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < iterations; i++) {
|
|
|
|
|
2020-05-04 14:39:51 +02:00
|
|
|
/* create directory given with a trailing slash */
|
|
|
|
CALL_AND_CHECK(ret, mkdir(trailing_slash_dir_name, 0777), (ret == 0), "dir_name=%s", dir_name);
|
|
|
|
|
|
|
|
/* remove directory given with a trailing slash */
|
|
|
|
CALL_AND_CHECK(ret, rmdir(trailing_slash_dir_name), (ret == 0), "dir_name=%s", dir_name);
|
|
|
|
|
2012-07-10 16:02:15 +02:00
|
|
|
/* create directory (short name) */
|
|
|
|
CALL_AND_CHECK(ret, mkdir(dir_name, 0777), ((ret == 0) || (errno == EEXIST)), "dir_name=%s", dir_name);
|
|
|
|
|
2017-03-23 17:59:25 +01:00
|
|
|
/* try to create again */
|
2017-06-12 16:02:11 +02:00
|
|
|
CALL_AND_CHECK(ret, mkdir(dir_name, 0777), (errno == EEXIST), "dir_name=%s", dir_name);
|
2017-03-23 17:59:25 +01:00
|
|
|
|
2012-07-10 16:02:15 +02:00
|
|
|
/* change to new directory */
|
|
|
|
CALL_AND_CHECK(ret, chdir(dir_name), ret == 0, "dir_name=%s", dir_name);
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2012-07-31 19:44:59 +02:00
|
|
|
/* create subdirectory with relative path */
|
|
|
|
CALL_AND_CHECK(ret, mkdir(dir_name2, 0777), ((ret == 0) || (errno == EEXIST)), "dir_name=%s", dir_name2);
|
|
|
|
|
2012-07-10 16:02:15 +02:00
|
|
|
/* write pattern to a file */
|
|
|
|
CALL_AND_CHECK(fd, open(file_name, O_CREAT | O_WRONLY), fd >= 0, "file_name=%s", file_name);
|
2012-07-12 16:42:59 +02:00
|
|
|
CALL_AND_CHECK(count, write(fd, pattern, pattern_size), (size_t)count == pattern_size, "");
|
2012-07-10 16:02:15 +02:00
|
|
|
CALL_AND_CHECK(ret, close(fd), ret == 0, "");
|
|
|
|
|
2012-08-06 18:52:37 +02:00
|
|
|
/* open the file with O_CREAT again (should have no effect on the file) */
|
|
|
|
CALL_AND_CHECK(fd, open(file_name, O_CREAT | O_WRONLY), fd >= 0, "file_name=%s", file_name);
|
|
|
|
CALL_AND_CHECK(ret, close(fd), ret == 0, "");
|
|
|
|
|
2012-07-10 16:02:15 +02:00
|
|
|
/* query file status of new file */
|
|
|
|
struct stat stat_buf;
|
|
|
|
CALL_AND_CHECK(ret, stat(file_name, &stat_buf), ret == 0, "file_name=%s", file_name);
|
|
|
|
printf("file size: %u bytes\n", (unsigned)stat_buf.st_size);
|
|
|
|
struct tm *file_time = gmtime(&stat_buf.st_mtime);
|
|
|
|
printf("last modified: %04u-%02u-%02u %02u:%02u:%02u\n",
|
|
|
|
file_time->tm_year, file_time->tm_mon, file_time->tm_mday,
|
|
|
|
file_time->tm_hour, file_time->tm_min, file_time->tm_sec);
|
|
|
|
|
|
|
|
/* read and verify file content */
|
|
|
|
CALL_AND_CHECK(fd, open(file_name, O_RDONLY), fd >= 0, "file_name=%s", file_name);
|
|
|
|
static char buf[512];
|
2012-07-12 16:42:59 +02:00
|
|
|
CALL_AND_CHECK(count, read(fd, buf, sizeof(buf)), (size_t)count == pattern_size, "");
|
2012-07-10 16:02:15 +02:00
|
|
|
CALL_AND_CHECK(ret, close(fd), ret == 0, "");
|
|
|
|
printf("content of file: \"%s\"\n", buf);
|
|
|
|
if (strcmp(buf, pattern) != 0) {
|
|
|
|
printf("unexpected content of file\n");
|
2017-03-07 15:16:15 +01:00
|
|
|
throw Test_failed();
|
2011-12-22 16:19:25 +01:00
|
|
|
} else {
|
2012-07-10 16:02:15 +02:00
|
|
|
printf("file content is correct\n");
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
2012-07-10 16:02:15 +02:00
|
|
|
|
2016-03-08 16:45:13 +01:00
|
|
|
/* move file (target does not exist) */
|
|
|
|
CALL_AND_CHECK(fd, open(file_name5, O_CREAT | O_WRONLY), fd >= 0, "file_name=%s", file_name5);
|
|
|
|
CALL_AND_CHECK(ret, rename(file_name5, "x"), ret == 0, "file_name=%s", file_name5);
|
2017-05-16 20:59:37 +02:00
|
|
|
CALL_AND_CHECK(ret, close(fd), ret == 0, "");
|
2016-03-08 16:45:13 +01:00
|
|
|
|
|
|
|
/* move file (target already exists) */
|
|
|
|
CALL_AND_CHECK(fd, open(file_name5, O_CREAT | O_WRONLY), fd >= 0, "file_name=%s", file_name5);
|
|
|
|
CALL_AND_CHECK(ret, rename(file_name5, "x"), ret == 0, "file_name=%s", file_name5);
|
2017-05-16 20:59:37 +02:00
|
|
|
CALL_AND_CHECK(ret, close(fd), ret == 0, "");
|
2016-03-08 16:45:13 +01:00
|
|
|
|
2012-07-12 16:42:59 +02:00
|
|
|
/* test 'pread()' and 'pwrite()' */
|
2012-10-08 14:44:31 +02:00
|
|
|
CALL_AND_CHECK(fd, open(file_name2, O_CREAT | O_WRONLY), fd >= 0, "file_name=%s", file_name2);
|
2012-07-12 16:42:59 +02:00
|
|
|
/* write "a single line of" */
|
|
|
|
CALL_AND_CHECK(count, pwrite(fd, pattern, (pattern_size - 6), 0), (size_t)count == (pattern_size - 6), "");
|
|
|
|
/* write "line of text" at offset 9 */
|
|
|
|
CALL_AND_CHECK(count, pwrite(fd, &pattern[9], (pattern_size - 9), 9), (size_t)count == (pattern_size - 9), "");
|
|
|
|
CALL_AND_CHECK(ret, close(fd), ret == 0, "");
|
2012-10-08 14:44:31 +02:00
|
|
|
CALL_AND_CHECK(fd, open(file_name2, O_RDONLY), fd >= 0, "file_name=%s", file_name2);
|
2012-07-12 16:42:59 +02:00
|
|
|
memset(buf, 0, sizeof(buf));
|
|
|
|
/* read "single line of text" from offset 2 */
|
|
|
|
CALL_AND_CHECK(count, pread(fd, buf, sizeof(buf), 2), (size_t)count == (pattern_size - 2), "");
|
|
|
|
CALL_AND_CHECK(ret, close(fd), ret == 0, "");
|
|
|
|
printf("content of file: \"%s\"\n", buf);
|
|
|
|
if (strcmp(buf, &pattern[2]) != 0) {
|
|
|
|
printf("unexpected content of file\n");
|
2017-03-07 15:16:15 +01:00
|
|
|
throw Test_failed();
|
2012-07-12 16:42:59 +02:00
|
|
|
} else {
|
|
|
|
printf("file content is correct\n");
|
|
|
|
}
|
|
|
|
|
2012-07-12 17:08:59 +02:00
|
|
|
/* test 'readv()' and 'writev()' */
|
2012-10-08 14:44:31 +02:00
|
|
|
CALL_AND_CHECK(fd, open(file_name3, O_CREAT | O_WRONLY), fd >= 0, "file_name=%s", file_name3);
|
2012-07-12 17:08:59 +02:00
|
|
|
struct iovec iov[2];
|
|
|
|
/* write "a single line" */
|
|
|
|
iov[0].iov_base = (void*)pattern;
|
|
|
|
iov[0].iov_len = 13;
|
|
|
|
/* write " line of text" */
|
|
|
|
iov[1].iov_base = (void*)&pattern[8];
|
|
|
|
iov[1].iov_len = pattern_size - 8;
|
|
|
|
CALL_AND_CHECK(count, writev(fd, iov, 2), (size_t)count == (pattern_size + 5), "");
|
|
|
|
CALL_AND_CHECK(ret, close(fd), ret == 0, "");
|
2012-10-08 14:44:31 +02:00
|
|
|
CALL_AND_CHECK(fd, open(file_name3, O_RDONLY), fd >= 0, "file_name=%s", file_name3);
|
2012-07-12 17:08:59 +02:00
|
|
|
memset(buf, 0, sizeof(buf));
|
|
|
|
/* read "a single line" */
|
|
|
|
iov[0].iov_base = buf;
|
|
|
|
iov[0].iov_len = 13;
|
|
|
|
/* read " line of text" to offset 8 */
|
|
|
|
iov[1].iov_base = &buf[8];
|
|
|
|
iov[1].iov_len = pattern_size;
|
|
|
|
CALL_AND_CHECK(count, readv(fd, iov, 2), (size_t)count == (pattern_size + 5), "");
|
|
|
|
CALL_AND_CHECK(ret, close(fd), ret == 0, "");
|
|
|
|
printf("content of buffer: \"%s\"\n", buf);
|
|
|
|
if (strcmp(buf, pattern) != 0) {
|
|
|
|
printf("unexpected content of file\n");
|
2017-03-07 15:16:15 +01:00
|
|
|
throw Test_failed();
|
2012-07-12 17:08:59 +02:00
|
|
|
} else {
|
|
|
|
printf("file content is correct\n");
|
|
|
|
}
|
|
|
|
|
2012-07-10 16:02:15 +02:00
|
|
|
/* read directory entries */
|
|
|
|
DIR *dir;
|
2014-04-11 15:01:48 +02:00
|
|
|
|
|
|
|
CALL_AND_CHECK(ret, chdir(".."), ret == 0, "dir_name=..");
|
2012-07-10 16:02:15 +02:00
|
|
|
CALL_AND_CHECK(dir, opendir(dir_name), dir, "dir_name=\"%s\"", dir_name);
|
|
|
|
printf("calling readdir()\n");
|
|
|
|
for (;;) {
|
|
|
|
struct dirent *dirent = readdir(dir);
|
|
|
|
if (dirent) {
|
|
|
|
if (dirent->d_type == DT_DIR)
|
|
|
|
printf("found directory %s\n", dirent->d_name);
|
|
|
|
else
|
|
|
|
printf("found file %s\n", dirent->d_name);
|
|
|
|
} else {
|
|
|
|
printf("no (more) direntries found\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-02 15:17:24 +02:00
|
|
|
/* test 'ftruncate()' */
|
|
|
|
CALL_AND_CHECK(fd, open(file_name4, O_CREAT | O_WRONLY), fd >= 0, "file_name=%s", file_name4);
|
|
|
|
CALL_AND_CHECK(ret, ftruncate(fd, 100), ret == 0, ""); /* increase size */
|
|
|
|
CALL_AND_CHECK(ret, close(fd), ret == 0, "");
|
|
|
|
CALL_AND_CHECK(ret, stat(file_name4, &stat_buf),
|
2017-03-07 15:16:15 +01:00
|
|
|
(ret == 0) && (stat_buf.st_size == 100),
|
|
|
|
"file_name=%s", file_name4);
|
2012-08-02 15:17:24 +02:00
|
|
|
CALL_AND_CHECK(fd, open(file_name4, O_WRONLY), fd >= 0, "file_name=%s", file_name4);
|
|
|
|
CALL_AND_CHECK(ret, ftruncate(fd, 10), ret == 0, ""); /* decrease size */
|
|
|
|
CALL_AND_CHECK(ret, close(fd), ret == 0, "");
|
|
|
|
CALL_AND_CHECK(ret, stat(file_name4, &stat_buf),
|
2017-03-07 15:16:15 +01:00
|
|
|
(ret == 0) && (stat_buf.st_size == 10),
|
|
|
|
"file_name=%s", file_name4);
|
2012-08-02 15:17:24 +02:00
|
|
|
|
2012-08-07 17:32:15 +02:00
|
|
|
/* test 'O_TRUNC' flag */
|
|
|
|
CALL_AND_CHECK(fd, open(file_name4, O_WRONLY | O_TRUNC), fd >= 0, "file_name=%s", file_name4);
|
|
|
|
CALL_AND_CHECK(ret, close(fd), ret == 0, "");
|
|
|
|
CALL_AND_CHECK(ret, stat(file_name4, &stat_buf),
|
2017-03-07 15:16:15 +01:00
|
|
|
(ret == 0) && (stat_buf.st_size == 0),
|
|
|
|
"file_name=%s", file_name4);
|
2012-08-07 17:32:15 +02:00
|
|
|
|
2012-10-08 14:44:31 +02:00
|
|
|
/* test 'fchdir()' */
|
|
|
|
CALL_AND_CHECK(fd, open(dir_name, O_RDONLY), fd >= 0, "dir_name=%s", dir_name);
|
|
|
|
CALL_AND_CHECK(ret, fchdir(fd), ret == 0, "");
|
|
|
|
CALL_AND_CHECK(ret, close(fd), ret == 0, "");
|
|
|
|
CALL_AND_CHECK(ret, stat(file_name, &stat_buf), ret == 0, "file_name=%s", file_name);
|
|
|
|
|
2014-01-21 13:40:49 +01:00
|
|
|
/* test 'unlink()' */
|
|
|
|
CALL_AND_CHECK(ret, unlink(file_name), (ret == 0), "file_name=%s", file_name);
|
|
|
|
CALL_AND_CHECK(ret, stat(file_name, &stat_buf), (ret == -1), "file_name=%s", file_name);
|
|
|
|
CALL_AND_CHECK(ret, stat(dir_name2, &stat_buf), (ret == 0), "dir_name=%s", dir_name2);
|
2014-04-18 22:58:45 +02:00
|
|
|
CALL_AND_CHECK(ret, rmdir(dir_name2), (ret == 0), "dir_name=%s", dir_name2);
|
2014-01-21 13:40:49 +01:00
|
|
|
CALL_AND_CHECK(ret, stat(dir_name2, &stat_buf), (ret == -1), "dir_name=%s", dir_name2);
|
|
|
|
|
2012-10-08 14:44:31 +02:00
|
|
|
/* test symbolic links */
|
2017-07-28 23:19:30 +02:00
|
|
|
if ((symlink("/", "symlinks_supported") == 0) || (errno != EPERM)) {
|
2014-04-11 15:01:48 +02:00
|
|
|
CALL_AND_CHECK(ret, mkdir("a", 0777), ((ret == 0) || (errno == EEXIST)), "dir_name=%s", "a");
|
|
|
|
CALL_AND_CHECK(ret, mkdir("c", 0777), ((ret == 0) || (errno == EEXIST)), "dir_name=%s", "c");
|
|
|
|
CALL_AND_CHECK(ret, symlink("../a", "c/d"),
|
2017-03-07 15:16:15 +01:00
|
|
|
((ret == 0) || (errno == EEXIST)), "dir_name=%s", "/c/d");
|
2014-04-11 15:01:48 +02:00
|
|
|
CALL_AND_CHECK(ret, symlink("c", "e"), ((ret == 0) || (errno == EEXIST)), "dir_name=%s", "e");
|
2012-10-08 14:44:31 +02:00
|
|
|
|
2014-04-11 15:01:48 +02:00
|
|
|
CALL_AND_CHECK(fd, open("a/b", O_CREAT | O_WRONLY), fd >= 0, "file_name=%s", "a/b");
|
2012-10-08 14:44:31 +02:00
|
|
|
CALL_AND_CHECK(count, write(fd, pattern, pattern_size), (size_t)count == pattern_size, "");
|
|
|
|
CALL_AND_CHECK(ret, close(fd), ret == 0, "");
|
|
|
|
|
2014-04-11 15:01:48 +02:00
|
|
|
CALL_AND_CHECK(fd, open("e/d/b", O_RDONLY), fd >= 0, "file_name=%s", "e/d/b");
|
2012-10-08 14:44:31 +02:00
|
|
|
CALL_AND_CHECK(count, read(fd, buf, sizeof(buf)), (size_t)count == pattern_size, "");
|
|
|
|
CALL_AND_CHECK(ret, close(fd), ret == 0, "");
|
|
|
|
printf("content of file: \"%s\"\n", buf);
|
|
|
|
if (strcmp(buf, pattern) != 0) {
|
|
|
|
printf("unexpected content of file\n");
|
2017-03-07 15:16:15 +01:00
|
|
|
throw Test_failed();
|
2012-10-08 14:44:31 +02:00
|
|
|
} else {
|
|
|
|
printf("file content is correct\n");
|
|
|
|
}
|
2014-01-21 13:40:49 +01:00
|
|
|
|
|
|
|
/* test unlink for symbolic links */
|
2014-04-11 15:01:48 +02:00
|
|
|
CALL_AND_CHECK(ret, unlink("c/d"), (ret == 0), "symlink=%s", "c/d");
|
|
|
|
CALL_AND_CHECK(ret, stat("c/d", &stat_buf), (ret == -1), "symlink=%s", "c/d");
|
2012-10-08 14:44:31 +02:00
|
|
|
}
|
|
|
|
|
2012-07-10 16:02:15 +02:00
|
|
|
if (i < (iterations - 1))
|
|
|
|
sleep(2);
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
2017-03-07 15:16:15 +01:00
|
|
|
}
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2015-11-12 11:54:12 +01:00
|
|
|
|
2017-03-07 15:16:15 +01:00
|
|
|
struct Main
|
|
|
|
{
|
|
|
|
Main(Genode::Env &env)
|
|
|
|
{
|
|
|
|
Genode::Attached_rom_dataspace config_rom { env, "config" };
|
2012-08-07 14:37:00 +02:00
|
|
|
|
2017-03-07 15:16:15 +01:00
|
|
|
Libc::with_libc([&] () {
|
|
|
|
|
|
|
|
test(config_rom.xml());
|
|
|
|
test_write_read(config_rom.xml());
|
|
|
|
|
|
|
|
printf("test finished\n");
|
|
|
|
});
|
|
|
|
|
|
|
|
env.parent().exit(0);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void Libc::Component::construct(Libc::Env &env) { static Main main(env); }
|