# HG changeset patch # User Paul Boddie # Date 1619901436 -7200 # Node ID bf404ff6a9e15cc23ef05784ba253e9047c23b7e # Parent 8968c31239cb706f317c571fb7d037346beebe20 Introduced filesystem client support for pipes, along with the notion of a file having a well-defined size, as opposed to a pipe which is of potentially unlimited size. Changed the pipe test to use the higher-level library and to cycle between reading and writing to test continual transmission of content. diff -r 8968c31239cb -r bf404ff6a9e1 libfsclient/include/fsclient/file.h --- a/libfsclient/include/fsclient/file.h Sat May 01 01:46:33 2021 +0200 +++ b/libfsclient/include/fsclient/file.h Sat May 01 22:37:16 2021 +0200 @@ -55,6 +55,10 @@ int can_mmap; + /* Explicit size support. */ + + int has_size; + } file_t; diff -r 8968c31239cb -r bf404ff6a9e1 libfsclient/lib/src/client.cc --- a/libfsclient/lib/src/client.cc Sat May 01 01:46:33 2021 +0200 +++ b/libfsclient/lib/src/client.cc Sat May 01 22:37:16 2021 +0200 @@ -126,9 +126,11 @@ /* Strict conditions for region navigation in pipes. */ - else if ((position != file->end_pos) || - (client_next_region(file) == NULL)) - return -L4_EIO; + else + { + if ((position != file->end_pos) || (client_next_region(file) == NULL)) + return -L4_EIO; + } } /* Otherwise, flush any written data in the current region and update the @@ -136,15 +138,26 @@ else { - err = client_flush(file); - - if (err) - return err; + if (file->can_mmap) + { + err = client_flush(file); + if (err) + return err; + } + else + { + if (client_current_region(file) == NULL) + return -L4_EIO; + } } /* Update the current data offset. */ - file->data_current = position - file->start_pos; + if (file->has_size) + file->data_current = position - file->start_pos; + else + file->data_current = 0; + return L4_EOK; } @@ -200,6 +213,24 @@ +/* Ensure that memory is mapped for accessing the given file, using the + indicated count as a region size hint. */ + +static void *_map_memory(file_t *file, offset_t count) +{ + if (file->memory == NULL) + { + if (file->can_mmap) + return client_mmap(file, client_tell(file), count); + else if (pipe_current(file)) + return NULL; + } + + return file->memory; +} + + + /* Read from the filesystem object into the buffer provided. */ offset_t client_read(file_t *file, void *buf, offset_t count) @@ -209,7 +240,7 @@ /* Map memory if none has been mapped so far. */ - if ((file->memory == NULL) && (client_mmap(file, client_tell(file), count) == NULL)) + if (_map_memory(file, count) == NULL) return 0; /* Amount available in the descriptor buffer already. */ @@ -348,7 +379,7 @@ /* Map memory if none has been mapped so far. */ - if ((file->memory == NULL) && (client_mmap(file, client_tell(file), count) == NULL)) + if (_map_memory(file, count) == NULL) return 0; /* Attempt to ensure that the file can accept the amount of data to be @@ -357,12 +388,15 @@ offset_t needed_size = file_data_current_position(file) + count; - if (file->size < needed_size) + if (file->has_size) { - file_resize(file, needed_size); + if (file->size < needed_size) + { + file_resize(file, needed_size); - if (file->size < needed_size) - count = file->size - file_data_current_position(file); + if (file->size < needed_size) + count = file->size - file_data_current_position(file); + } } /* Space remaining in the descriptor buffer. */ diff -r 8968c31239cb -r bf404ff6a9e1 libfsclient/lib/src/file.cc --- a/libfsclient/lib/src/file.cc Sat May 01 01:46:33 2021 +0200 +++ b/libfsclient/lib/src/file.cc Sat May 01 22:37:16 2021 +0200 @@ -70,6 +70,7 @@ file->data_end = 0; file->data_current = 0; file->can_mmap = 1; + file->has_size = 1; } @@ -202,6 +203,9 @@ long file_resize(file_t *file, offset_t size) { + if (!file->has_size) + return -L4_EIO; + client_File _file(file->ref); offset_t file_size = size; long err = _file.resize(&file_size); @@ -372,7 +376,9 @@ /* Pipes can usually only be accessed via region navigation. */ reader->can_mmap = 0; + reader->has_size = 0; writer->can_mmap = 0; + writer->has_size = 0; long err = opener.pipe(size, &reader->ref, &writer->ref); if (err) diff -r 8968c31239cb -r bf404ff6a9e1 tests/dstest_pipe_client.cc --- a/tests/dstest_pipe_client.cc Sat May 01 01:46:33 2021 +0200 +++ b/tests/dstest_pipe_client.cc Sat May 01 22:37:16 2021 +0200 @@ -26,33 +26,12 @@ #include #include +#include #include #include -static void show(file_t *file, offset_t step, offset_t sample) -{ - /* Allocate a buffer for sampling from the file. */ - - char buf[sample + 1]; - - for (offset_t offset = 0; offset < file_populated_span(file); offset += step) - { - printf("show %ld of %ld...\n", offset, file_populated_span(file)); - - unsigned long remaining = file_populated_span(file) - offset; - unsigned long sample_remaining = remaining < sample ? remaining : sample; - - printf("%ld bytes from %p...\n", sample_remaining, (file->memory + offset)); - strncpy(buf, (file->memory + offset), sample_remaining); - buf[sample_remaining] = '\0'; - printf("%s\n", buf); - } -} - - - const unsigned int PIPE_PAGES = 2; int main(void) @@ -74,45 +53,58 @@ /* Use the writer to fill the pipe with data. */ - for (int region = 0; region < 3; region++) + offset_t size = 600; + char buffer[size]; + int region = 0; + + for (int loop = 0; loop < 3; loop++) { - printf("Write %ld to pipe at %p...\n", file_span(&writer), writer.memory); + while (1) + { + printf("Writing %ld to pipe...\n", size); - memset(writer.memory, (int) 'a' + region, file_span(&writer)); + memset(buffer, (int) 'a' + region, size); + + offset_t nwritten = client_write(&writer, buffer, size); - err = pipe_written(&writer, file_span(&writer)); + printf("Written %ld to pipe...\n", nwritten); + + for (offset_t i = 0; i < nwritten; i += 60) + { + fwrite(buffer + i, sizeof(char), nwritten - i > 60 ? 60 : nwritten - i, stdout); + fputs("\n", stdout); + } - if (err) - { - printf("Written data error: %s\n", l4sys_errtostr(err)); - return 1; + if (!nwritten) + break; + + region++; + + if (region == 26) + region = 0; } - show(&writer, page(1), 60); + /* Use the reader to obtain data from the pipe. */ - err = pipe_next(&writer); + offset_t nread; - if (err) + do { - printf("Region traversal error at region %d: %s\n", region, l4sys_errtostr(err)); - break; - } - } + printf("Reading %ld from pipe...\n", size); + + nread = client_read(&reader, buffer, size); - /* Use the reader to obtain data from the pipe. */ - - err = pipe_current(&reader); + printf("Read %ld from pipe...\n", nread); - while (!err) - { - printf("show...\n"); - show(&reader, page(1), 60); - err = pipe_next(&reader); + for (offset_t i = 0; i < nread; i += 60) + { + fwrite(buffer + i, sizeof(char), nread - i > 60 ? 60 : nread - i, stdout); + fputs("\n", stdout); + } + } + while (nread); } - if (err) - printf("Reading termination condition: %s\n", l4sys_errtostr(err)); - printf("Data shown.\n"); return 0;