aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
Diffstat (limited to 'erts')
-rw-r--r--erts/emulator/drivers/common/efile_drv.c72
-rw-r--r--erts/emulator/drivers/common/erl_efile.h2
-rw-r--r--erts/emulator/drivers/unix/unix_efile.c14
-rw-r--r--erts/preloaded/src/prim_file.erl13
4 files changed, 26 insertions, 75 deletions
diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c
index 7eaafd5af1..5c52b99348 100644
--- a/erts/emulator/drivers/common/efile_drv.c
+++ b/erts/emulator/drivers/common/efile_drv.c
@@ -431,8 +431,6 @@ struct t_data
off_t offset;
Uint64 nbytes;
Uint64 written;
- short flags;
- struct t_sendfile_hdtl *hdtl;
} sendfile;
#endif /* HAVE_SENDFILE */
} c;
@@ -521,9 +519,6 @@ static void *ef_safe_realloc(void *op, Uint s)
!0) \
: 0)
-/* int EV_GET_SYSIOVEC(ErlIoVec *ev, Uint32, int *cnt, SysIOVec **target, int *pp, int *qp) */
-#define EV_GET_SYSIOVEC ev_get_sysiovec
-
#if 0
@@ -935,43 +930,6 @@ static int reply_eof(file_descriptor *desc) {
driver_output2(desc->port, &c, 1, NULL, 0);
return 0;
}
-
-static int ev_get_sysiovec(ErlIOVec *ev, Uint32 len, int *cnt, SysIOVec **target, int *pp, int *qp) {
- int tmp_p = *pp, tmp_q = *qp, tmp_len = len, i;
- SysIOVec *tmp_target;
- while (tmp_len != 0) {
- if (tmp_len + tmp_p > ev->iov[tmp_q].iov_len) {
-
- tmp_len -= ev->iov[tmp_q].iov_len - tmp_p;
- tmp_q++;
- tmp_p = 0;
- if (tmp_q == ev->vsize)
- return 0;
- } else break;
- }
- *cnt = tmp_q - *qp + 1;
- tmp_target = EF_SAFE_ALLOC(sizeof(SysIOVec)* (*cnt));
- *target = tmp_target;
- for (i = 0; i < *cnt; i++) {
- tmp_target[i].iov_base = ev->iov[*qp].iov_base+*pp;
- if (len + *pp <= ev->iov[*qp].iov_len) {
- tmp_target[i].iov_len = len;
- if (len + *pp == ev->iov[*qp].iov_len) {
- *pp = 0;
- (*qp)++;
- } else
- *pp += len;
- } else {
- tmp_target[i].iov_len = ev->iov[*qp].iov_len - *pp;
- len -= ev->iov[*qp].iov_len - *pp;
- *pp = 0;
- (*qp)++;
- }
- }
- return 1;
-}
-
-
static void invoke_name(void *data, int (*f)(Efile_error *, char *))
{
@@ -1781,7 +1739,7 @@ static void invoke_sendfile(void *data)
int result = 0;
d->again = 0;
- result = efile_sendfile(&d->errInfo, fd, out_fd, &d->c.sendfile.offset, &nbytes, &d->c.sendfile.hdtl);
+ result = efile_sendfile(&d->errInfo, fd, out_fd, &d->c.sendfile.offset, &nbytes, NULL);
d->c.sendfile.written += nbytes;
@@ -3426,14 +3384,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
Uint64 nbytes;
char flags;
- /* DestFD:32, Offset:64, Bytes:64,
- ChunkSize:64,
- (get_bit(Nodiskio)):1,
- (get_bit(MNowait)):1,
- (get_bit(Sync)):1,0:5,
- (encode_hdtl(Headers))/binary,
- (encode_hdtl(Trailers))/binary */
- if (ev->size < 1 + 1 + 5 * sizeof(Uint32) + sizeof(char)
+ if (ev->size < 1 + 7 * sizeof(Uint32) + sizeof(char)
|| !EV_GET_UINT32(ev, &out_fd, &p, &q)
|| !EV_GET_CHAR(ev, &flags, &p, &q)
|| !EV_GET_UINT32(ev, &offsetH, &p, &q)
@@ -3446,6 +3397,12 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
goto done;
}
+ if (hd_len != 0 || tl_len != 0 || flags != 0) {
+ // We do not allow header, trailers and/or flags right now
+ reply_posix_error(desc, EINVAL);
+ goto done;
+ }
+
d = EF_SAFE_ALLOC(sizeof(struct t_data));
d->fd = desc->fd;
d->command = command;
@@ -3454,7 +3411,6 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
d->level = 2;
d->c.sendfile.out_fd = (int) out_fd;
- d->c.sendfile.flags = (int) flags;
d->c.sendfile.written = 0;
#if SIZEOF_OFF_T == 4
@@ -3468,18 +3424,6 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
#endif
d->c.sendfile.nbytes = nbytes;
- if (hd_len == 0 && tl_len == 0)
- d->c.sendfile.hdtl = NULL;
- else {
- d->c.sendfile.hdtl = EF_SAFE_ALLOC(sizeof(struct t_sendfile_hdtl));
- if (!EV_GET_SYSIOVEC(ev, hd_len, &d->c.sendfile.hdtl->hdr_cnt, &d->c.sendfile.hdtl->headers, &p, &q)
- || !EV_GET_SYSIOVEC(ev, tl_len, &d->c.sendfile.hdtl->trl_cnt, &d->c.sendfile.hdtl->trailers, &p, &q)) {
- EF_FREE(d->c.sendfile.hdtl);
- EF_FREE(d);
- reply_posix_error(desc, EINVAL);
- goto done;
- }
- }
if (sys_info.async_threads != 0) {
SET_BLOCKING(d->c.sendfile.out_fd);
diff --git a/erts/emulator/drivers/common/erl_efile.h b/erts/emulator/drivers/common/erl_efile.h
index b73fb35120..349ab0e17b 100644
--- a/erts/emulator/drivers/common/erl_efile.h
+++ b/erts/emulator/drivers/common/erl_efile.h
@@ -177,5 +177,5 @@ int efile_fadvise(Efile_error* errInfo, int fd, Sint64 offset, Sint64 length,
int advise);
#ifdef HAVE_SENDFILE
int efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd,
- off_t *offset, Uint64 *nbytes, struct t_sendfile_hdtl **hdtl);
+ off_t *offset, Uint64 *nbytes, struct t_sendfile_hdtl *hdtl);
#endif /* HAVE_SENDFILE */
diff --git a/erts/emulator/drivers/unix/unix_efile.c b/erts/emulator/drivers/unix/unix_efile.c
index 138c550fdd..72911641d3 100644
--- a/erts/emulator/drivers/unix/unix_efile.c
+++ b/erts/emulator/drivers/unix/unix_efile.c
@@ -1471,9 +1471,21 @@ efile_fadvise(Efile_error* errInfo, int fd, Sint64 offset,
#ifdef HAVE_SENDFILE
#define SENDFILE_CHUNK_SIZE ((1 << 30) -1)
+/*
+ * sendfile: The implementation of the sendfile system call varies
+ * a lot on different *nix platforms so to make the api similar in all
+ * we have to emulate some things in linux and play with variables on
+ * bsd/darwin.
+ *
+ * It could be possible to implement header/trailer in sendfile, though
+ * you would have to emulate it in linux and on BSD/Darwin some complex
+ * calculations have to be made when using a non blocking socket to figure
+ * out how much of the header/file/trailer was sent in each command.
+ */
+
int
efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd,
- off_t *offset, Uint64 *nbytes, struct t_sendfile_hdtl** hdtl)
+ off_t *offset, Uint64 *nbytes, struct t_sendfile_hdtl* hdtl)
{
Uint64 written = 0;
#if defined(__linux__) || (defined(__sun) && defined(__SVR4))
diff --git a/erts/preloaded/src/prim_file.erl b/erts/preloaded/src/prim_file.erl
index 6f35162feb..7316e0be99 100644
--- a/erts/preloaded/src/prim_file.erl
+++ b/erts/preloaded/src/prim_file.erl
@@ -545,7 +545,7 @@ write_file(_, _) ->
%sendfile(_,_,_,_,_,_,_,_,_,_) ->
% {error, enotsup};
sendfile(#file_descriptor{module = ?MODULE, data = {Port, _}},
- Dest, Offset, Bytes, _ChunkSize, _Headers, _Trailers,
+ Dest, Offset, Bytes, _ChunkSize, Headers, Trailers,
_Nodiskio, _MNowait, _Sync) ->
case erlang:port_get_data(Dest) of
Data when Data == inet_tcp; Data == inet6_tcp ->
@@ -555,8 +555,9 @@ sendfile(#file_descriptor{module = ?MODULE, data = {Port, _}},
0:8,
Offset:64/unsigned,
Bytes:64/unsigned,
- 0:32/unsigned,
- 0:32/unsigned>>])
+ (iolist_size(Headers)):32/unsigned,
+ (iolist_size(Trailers)):32/unsigned>>,
+ Headers,Trailers])
after
ok = inet:lock_socket(Dest,false)
end;
@@ -564,12 +565,6 @@ sendfile(#file_descriptor{module = ?MODULE, data = {Port, _}},
{error,badarg}
end.
-get_bit(true) ->
- 1;
-get_bit(false) ->
- 0.
-
-
%%%-----------------------------------------------------------------
%%% Functions operating on files without handle to the file. ?DRV.