diff options
| author | Andrew Clayton <a.clayton@nginx.com> | 2023-09-21 17:14:17 +0100 |
|---|---|---|
| committer | Andrew Clayton <a.clayton@nginx.com> | 2023-09-25 17:39:43 +0100 |
| commit | 43c8e44d33572b818cdd0a5945e494c5510ab24f (patch) | |
| tree | 24369b22c30fb348ffb9765db423588ef5ca6d7f /src/c/libunit-wasm.c | |
| parent | 1dd1b34194573661b10015fbc60d6910dbea8fcc (diff) | |
| download | unit-wasm-43c8e44d33572b818cdd0a5945e494c5510ab24f.tar.gz unit-wasm-43c8e44d33572b818cdd0a5945e494c5510ab24f.tar.bz2 | |
libunit-wasm: Add a luw_mem_splice_file() function
This is inspired by the likes of splice(2) and sendfile(2) in that it
takes data from one place and puts it in another.
This function write(2)'s the request data straight from the shared
memory to a given file (referenced by its file descriptor).
This is an alternative to using luw_req_buf_copy() and avoids an extra
copying of the request data.
E.g
/* In the request_handler */
if (total_bytes_wrote == 0) {
luw_init_ctx(&ctx, addr, 0);
luw_set_req_buf(&ctx, &request_buf, LUW_SRB_NONE);
fd = open("/var/tmp/large-file.dat", O_CREAT|O_TRUNC|O_WRONLY,
0666);
}
total_bytes_wrote += luw_mem_splice_file(addr, fd);
if (total_bytes_wrote == luw_get_http_content_len(&ctx)) {
close(fd);
total_bytes_wrote = 0;
luw_http_response_end();
}
NOTE:
We include a typedef definition for ssize_t in unit-wasm.h, to avoid
having a dependency on the wasi-sysroot when generating the rust
bindings.
ssize_t is defined in sys/types.h which is provided by libc and not the
compiler.
Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
Diffstat (limited to 'src/c/libunit-wasm.c')
| -rw-r--r-- | src/c/libunit-wasm.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/src/c/libunit-wasm.c b/src/c/libunit-wasm.c index fdf9499..1b36cf9 100644 --- a/src/c/libunit-wasm.c +++ b/src/c/libunit-wasm.c @@ -14,10 +14,16 @@ #include <stdarg.h> #include <string.h> #include <strings.h> +#include <unistd.h> #include <errno.h> #include "unit/unit-wasm.h" +#define MIN(a, b) \ + ({ __typeof__(a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a < _b ? _a : _b; }) + /* * Some handlers are required some are optional. * @@ -315,6 +321,29 @@ void luw_req_buf_copy(luw_ctx_t *ctx, const u8 *src) ctx->req->total_content_sent = req->total_content_sent; } +/* Copy data from the request to a given file-descriptor. */ +ssize_t luw_mem_splice_file(const u8 *src, int fd) +{ + struct luw_req *req = (struct luw_req *)src; + size_t written = 0; + size_t bytes_splice = 1024 * 128; /* It's what cp(1) uses */ + + do { + ssize_t bytes_wrote; + + bytes_splice = MIN(bytes_splice, req->content_sent - written); + + bytes_wrote = write(fd, src + req->content_off + written, + bytes_splice); + if (bytes_wrote == -1) + return -1; + + written += bytes_wrote; + } while (written < req->content_sent); + + return written; +} + /* * Convenience function to fill the response buffer with data from * the request buffer. |
