am d59ed678
: Merge "Add splice, tee, and vmsplice."
* commit 'd59ed678fe6d6bc5aeb1566004490126bd552df4': Add splice, tee, and vmsplice.
This commit is contained in:
commit
19fe877ec3
@ -285,6 +285,10 @@ int klogctl:syslog(int, char*, int) all
|
|||||||
int sysinfo(struct sysinfo*) all
|
int sysinfo(struct sysinfo*) all
|
||||||
int personality(unsigned long) all
|
int personality(unsigned long) all
|
||||||
|
|
||||||
|
ssize_t tee(int, int, size_t, unsigned int) all
|
||||||
|
ssize_t splice(int, off64_t*, int, off64_t*, size_t, unsigned int) all
|
||||||
|
ssize_t vmsplice(int, const struct iovec*, size_t, unsigned int) all
|
||||||
|
|
||||||
int epoll_create1(int) all
|
int epoll_create1(int) all
|
||||||
int epoll_ctl(int, int op, int, struct epoll_event*) all
|
int epoll_ctl(int, int op, int, struct epoll_event*) all
|
||||||
int __epoll_pwait:epoll_pwait(int, struct epoll_event*, int, int, const sigset_t*, size_t) all
|
int __epoll_pwait:epoll_pwait(int, struct epoll_event*, int, int, const sigset_t*, size_t) all
|
||||||
|
22
libc/arch-arm/syscalls/splice.S
Normal file
22
libc/arch-arm/syscalls/splice.S
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/* Generated by gensyscalls.py. Do not edit. */
|
||||||
|
|
||||||
|
#include <private/bionic_asm.h>
|
||||||
|
|
||||||
|
ENTRY(splice)
|
||||||
|
mov ip, sp
|
||||||
|
stmfd sp!, {r4, r5, r6, r7}
|
||||||
|
.cfi_def_cfa_offset 16
|
||||||
|
.cfi_rel_offset r4, 0
|
||||||
|
.cfi_rel_offset r5, 4
|
||||||
|
.cfi_rel_offset r6, 8
|
||||||
|
.cfi_rel_offset r7, 12
|
||||||
|
ldmfd ip, {r4, r5, r6}
|
||||||
|
ldr r7, =__NR_splice
|
||||||
|
swi #0
|
||||||
|
ldmfd sp!, {r4, r5, r6, r7}
|
||||||
|
.cfi_def_cfa_offset 0
|
||||||
|
cmn r0, #(MAX_ERRNO + 1)
|
||||||
|
bxls lr
|
||||||
|
neg r0, r0
|
||||||
|
b __set_errno
|
||||||
|
END(splice)
|
14
libc/arch-arm/syscalls/tee.S
Normal file
14
libc/arch-arm/syscalls/tee.S
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/* Generated by gensyscalls.py. Do not edit. */
|
||||||
|
|
||||||
|
#include <private/bionic_asm.h>
|
||||||
|
|
||||||
|
ENTRY(tee)
|
||||||
|
mov ip, r7
|
||||||
|
ldr r7, =__NR_tee
|
||||||
|
swi #0
|
||||||
|
mov r7, ip
|
||||||
|
cmn r0, #(MAX_ERRNO + 1)
|
||||||
|
bxls lr
|
||||||
|
neg r0, r0
|
||||||
|
b __set_errno
|
||||||
|
END(tee)
|
14
libc/arch-arm/syscalls/vmsplice.S
Normal file
14
libc/arch-arm/syscalls/vmsplice.S
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/* Generated by gensyscalls.py. Do not edit. */
|
||||||
|
|
||||||
|
#include <private/bionic_asm.h>
|
||||||
|
|
||||||
|
ENTRY(vmsplice)
|
||||||
|
mov ip, r7
|
||||||
|
ldr r7, =__NR_vmsplice
|
||||||
|
swi #0
|
||||||
|
mov r7, ip
|
||||||
|
cmn r0, #(MAX_ERRNO + 1)
|
||||||
|
bxls lr
|
||||||
|
neg r0, r0
|
||||||
|
b __set_errno
|
||||||
|
END(vmsplice)
|
14
libc/arch-arm64/syscalls/splice.S
Normal file
14
libc/arch-arm64/syscalls/splice.S
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/* Generated by gensyscalls.py. Do not edit. */
|
||||||
|
|
||||||
|
#include <private/bionic_asm.h>
|
||||||
|
|
||||||
|
ENTRY(splice)
|
||||||
|
mov x8, __NR_splice
|
||||||
|
svc #0
|
||||||
|
|
||||||
|
cmn x0, #(MAX_ERRNO + 1)
|
||||||
|
cneg x0, x0, hi
|
||||||
|
b.hi __set_errno
|
||||||
|
|
||||||
|
ret
|
||||||
|
END(splice)
|
14
libc/arch-arm64/syscalls/tee.S
Normal file
14
libc/arch-arm64/syscalls/tee.S
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/* Generated by gensyscalls.py. Do not edit. */
|
||||||
|
|
||||||
|
#include <private/bionic_asm.h>
|
||||||
|
|
||||||
|
ENTRY(tee)
|
||||||
|
mov x8, __NR_tee
|
||||||
|
svc #0
|
||||||
|
|
||||||
|
cmn x0, #(MAX_ERRNO + 1)
|
||||||
|
cneg x0, x0, hi
|
||||||
|
b.hi __set_errno
|
||||||
|
|
||||||
|
ret
|
||||||
|
END(tee)
|
14
libc/arch-arm64/syscalls/vmsplice.S
Normal file
14
libc/arch-arm64/syscalls/vmsplice.S
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/* Generated by gensyscalls.py. Do not edit. */
|
||||||
|
|
||||||
|
#include <private/bionic_asm.h>
|
||||||
|
|
||||||
|
ENTRY(vmsplice)
|
||||||
|
mov x8, __NR_vmsplice
|
||||||
|
svc #0
|
||||||
|
|
||||||
|
cmn x0, #(MAX_ERRNO + 1)
|
||||||
|
cneg x0, x0, hi
|
||||||
|
b.hi __set_errno
|
||||||
|
|
||||||
|
ret
|
||||||
|
END(vmsplice)
|
19
libc/arch-mips/syscalls/splice.S
Normal file
19
libc/arch-mips/syscalls/splice.S
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/* Generated by gensyscalls.py. Do not edit. */
|
||||||
|
|
||||||
|
#include <private/bionic_asm.h>
|
||||||
|
|
||||||
|
ENTRY(splice)
|
||||||
|
.set noreorder
|
||||||
|
.cpload t9
|
||||||
|
li v0, __NR_splice
|
||||||
|
syscall
|
||||||
|
bnez a3, 1f
|
||||||
|
move a0, v0
|
||||||
|
j ra
|
||||||
|
nop
|
||||||
|
1:
|
||||||
|
la t9,__set_errno
|
||||||
|
j t9
|
||||||
|
nop
|
||||||
|
.set reorder
|
||||||
|
END(splice)
|
19
libc/arch-mips/syscalls/tee.S
Normal file
19
libc/arch-mips/syscalls/tee.S
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/* Generated by gensyscalls.py. Do not edit. */
|
||||||
|
|
||||||
|
#include <private/bionic_asm.h>
|
||||||
|
|
||||||
|
ENTRY(tee)
|
||||||
|
.set noreorder
|
||||||
|
.cpload t9
|
||||||
|
li v0, __NR_tee
|
||||||
|
syscall
|
||||||
|
bnez a3, 1f
|
||||||
|
move a0, v0
|
||||||
|
j ra
|
||||||
|
nop
|
||||||
|
1:
|
||||||
|
la t9,__set_errno
|
||||||
|
j t9
|
||||||
|
nop
|
||||||
|
.set reorder
|
||||||
|
END(tee)
|
19
libc/arch-mips/syscalls/vmsplice.S
Normal file
19
libc/arch-mips/syscalls/vmsplice.S
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/* Generated by gensyscalls.py. Do not edit. */
|
||||||
|
|
||||||
|
#include <private/bionic_asm.h>
|
||||||
|
|
||||||
|
ENTRY(vmsplice)
|
||||||
|
.set noreorder
|
||||||
|
.cpload t9
|
||||||
|
li v0, __NR_vmsplice
|
||||||
|
syscall
|
||||||
|
bnez a3, 1f
|
||||||
|
move a0, v0
|
||||||
|
j ra
|
||||||
|
nop
|
||||||
|
1:
|
||||||
|
la t9,__set_errno
|
||||||
|
j t9
|
||||||
|
nop
|
||||||
|
.set reorder
|
||||||
|
END(vmsplice)
|
25
libc/arch-mips64/syscalls/splice.S
Normal file
25
libc/arch-mips64/syscalls/splice.S
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/* Generated by gensyscalls.py. Do not edit. */
|
||||||
|
|
||||||
|
#include <private/bionic_asm.h>
|
||||||
|
|
||||||
|
ENTRY(splice)
|
||||||
|
.set push
|
||||||
|
.set noreorder
|
||||||
|
li v0, __NR_splice
|
||||||
|
syscall
|
||||||
|
bnez a3, 1f
|
||||||
|
move a0, v0
|
||||||
|
j ra
|
||||||
|
nop
|
||||||
|
1:
|
||||||
|
move t0, ra
|
||||||
|
bal 2f
|
||||||
|
nop
|
||||||
|
2:
|
||||||
|
.cpsetup ra, t1, 2b
|
||||||
|
LA t9,__set_errno
|
||||||
|
.cpreturn
|
||||||
|
j t9
|
||||||
|
move ra, t0
|
||||||
|
.set pop
|
||||||
|
END(splice)
|
25
libc/arch-mips64/syscalls/tee.S
Normal file
25
libc/arch-mips64/syscalls/tee.S
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/* Generated by gensyscalls.py. Do not edit. */
|
||||||
|
|
||||||
|
#include <private/bionic_asm.h>
|
||||||
|
|
||||||
|
ENTRY(tee)
|
||||||
|
.set push
|
||||||
|
.set noreorder
|
||||||
|
li v0, __NR_tee
|
||||||
|
syscall
|
||||||
|
bnez a3, 1f
|
||||||
|
move a0, v0
|
||||||
|
j ra
|
||||||
|
nop
|
||||||
|
1:
|
||||||
|
move t0, ra
|
||||||
|
bal 2f
|
||||||
|
nop
|
||||||
|
2:
|
||||||
|
.cpsetup ra, t1, 2b
|
||||||
|
LA t9,__set_errno
|
||||||
|
.cpreturn
|
||||||
|
j t9
|
||||||
|
move ra, t0
|
||||||
|
.set pop
|
||||||
|
END(tee)
|
25
libc/arch-mips64/syscalls/vmsplice.S
Normal file
25
libc/arch-mips64/syscalls/vmsplice.S
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/* Generated by gensyscalls.py. Do not edit. */
|
||||||
|
|
||||||
|
#include <private/bionic_asm.h>
|
||||||
|
|
||||||
|
ENTRY(vmsplice)
|
||||||
|
.set push
|
||||||
|
.set noreorder
|
||||||
|
li v0, __NR_vmsplice
|
||||||
|
syscall
|
||||||
|
bnez a3, 1f
|
||||||
|
move a0, v0
|
||||||
|
j ra
|
||||||
|
nop
|
||||||
|
1:
|
||||||
|
move t0, ra
|
||||||
|
bal 2f
|
||||||
|
nop
|
||||||
|
2:
|
||||||
|
.cpsetup ra, t1, 2b
|
||||||
|
LA t9,__set_errno
|
||||||
|
.cpreturn
|
||||||
|
j t9
|
||||||
|
move ra, t0
|
||||||
|
.set pop
|
||||||
|
END(vmsplice)
|
46
libc/arch-x86/syscalls/splice.S
Normal file
46
libc/arch-x86/syscalls/splice.S
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/* Generated by gensyscalls.py. Do not edit. */
|
||||||
|
|
||||||
|
#include <private/bionic_asm.h>
|
||||||
|
|
||||||
|
ENTRY(splice)
|
||||||
|
pushl %ebx
|
||||||
|
.cfi_def_cfa_offset 8
|
||||||
|
.cfi_rel_offset ebx, 0
|
||||||
|
pushl %ecx
|
||||||
|
.cfi_adjust_cfa_offset 4
|
||||||
|
.cfi_rel_offset ecx, 0
|
||||||
|
pushl %edx
|
||||||
|
.cfi_adjust_cfa_offset 4
|
||||||
|
.cfi_rel_offset edx, 0
|
||||||
|
pushl %esi
|
||||||
|
.cfi_adjust_cfa_offset 4
|
||||||
|
.cfi_rel_offset esi, 0
|
||||||
|
pushl %edi
|
||||||
|
.cfi_adjust_cfa_offset 4
|
||||||
|
.cfi_rel_offset edi, 0
|
||||||
|
pushl %ebp
|
||||||
|
.cfi_adjust_cfa_offset 4
|
||||||
|
.cfi_rel_offset ebp, 0
|
||||||
|
mov 28(%esp), %ebx
|
||||||
|
mov 32(%esp), %ecx
|
||||||
|
mov 36(%esp), %edx
|
||||||
|
mov 40(%esp), %esi
|
||||||
|
mov 44(%esp), %edi
|
||||||
|
mov 48(%esp), %ebp
|
||||||
|
movl $__NR_splice, %eax
|
||||||
|
int $0x80
|
||||||
|
cmpl $-MAX_ERRNO, %eax
|
||||||
|
jb 1f
|
||||||
|
negl %eax
|
||||||
|
pushl %eax
|
||||||
|
call __set_errno
|
||||||
|
addl $4, %esp
|
||||||
|
1:
|
||||||
|
popl %ebp
|
||||||
|
popl %edi
|
||||||
|
popl %esi
|
||||||
|
popl %edx
|
||||||
|
popl %ecx
|
||||||
|
popl %ebx
|
||||||
|
ret
|
||||||
|
END(splice)
|
36
libc/arch-x86/syscalls/tee.S
Normal file
36
libc/arch-x86/syscalls/tee.S
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/* Generated by gensyscalls.py. Do not edit. */
|
||||||
|
|
||||||
|
#include <private/bionic_asm.h>
|
||||||
|
|
||||||
|
ENTRY(tee)
|
||||||
|
pushl %ebx
|
||||||
|
.cfi_def_cfa_offset 8
|
||||||
|
.cfi_rel_offset ebx, 0
|
||||||
|
pushl %ecx
|
||||||
|
.cfi_adjust_cfa_offset 4
|
||||||
|
.cfi_rel_offset ecx, 0
|
||||||
|
pushl %edx
|
||||||
|
.cfi_adjust_cfa_offset 4
|
||||||
|
.cfi_rel_offset edx, 0
|
||||||
|
pushl %esi
|
||||||
|
.cfi_adjust_cfa_offset 4
|
||||||
|
.cfi_rel_offset esi, 0
|
||||||
|
mov 20(%esp), %ebx
|
||||||
|
mov 24(%esp), %ecx
|
||||||
|
mov 28(%esp), %edx
|
||||||
|
mov 32(%esp), %esi
|
||||||
|
movl $__NR_tee, %eax
|
||||||
|
int $0x80
|
||||||
|
cmpl $-MAX_ERRNO, %eax
|
||||||
|
jb 1f
|
||||||
|
negl %eax
|
||||||
|
pushl %eax
|
||||||
|
call __set_errno
|
||||||
|
addl $4, %esp
|
||||||
|
1:
|
||||||
|
popl %esi
|
||||||
|
popl %edx
|
||||||
|
popl %ecx
|
||||||
|
popl %ebx
|
||||||
|
ret
|
||||||
|
END(tee)
|
36
libc/arch-x86/syscalls/vmsplice.S
Normal file
36
libc/arch-x86/syscalls/vmsplice.S
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/* Generated by gensyscalls.py. Do not edit. */
|
||||||
|
|
||||||
|
#include <private/bionic_asm.h>
|
||||||
|
|
||||||
|
ENTRY(vmsplice)
|
||||||
|
pushl %ebx
|
||||||
|
.cfi_def_cfa_offset 8
|
||||||
|
.cfi_rel_offset ebx, 0
|
||||||
|
pushl %ecx
|
||||||
|
.cfi_adjust_cfa_offset 4
|
||||||
|
.cfi_rel_offset ecx, 0
|
||||||
|
pushl %edx
|
||||||
|
.cfi_adjust_cfa_offset 4
|
||||||
|
.cfi_rel_offset edx, 0
|
||||||
|
pushl %esi
|
||||||
|
.cfi_adjust_cfa_offset 4
|
||||||
|
.cfi_rel_offset esi, 0
|
||||||
|
mov 20(%esp), %ebx
|
||||||
|
mov 24(%esp), %ecx
|
||||||
|
mov 28(%esp), %edx
|
||||||
|
mov 32(%esp), %esi
|
||||||
|
movl $__NR_vmsplice, %eax
|
||||||
|
int $0x80
|
||||||
|
cmpl $-MAX_ERRNO, %eax
|
||||||
|
jb 1f
|
||||||
|
negl %eax
|
||||||
|
pushl %eax
|
||||||
|
call __set_errno
|
||||||
|
addl $4, %esp
|
||||||
|
1:
|
||||||
|
popl %esi
|
||||||
|
popl %edx
|
||||||
|
popl %ecx
|
||||||
|
popl %ebx
|
||||||
|
ret
|
||||||
|
END(vmsplice)
|
16
libc/arch-x86_64/syscalls/splice.S
Normal file
16
libc/arch-x86_64/syscalls/splice.S
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/* Generated by gensyscalls.py. Do not edit. */
|
||||||
|
|
||||||
|
#include <private/bionic_asm.h>
|
||||||
|
|
||||||
|
ENTRY(splice)
|
||||||
|
movq %rcx, %r10
|
||||||
|
movl $__NR_splice, %eax
|
||||||
|
syscall
|
||||||
|
cmpq $-MAX_ERRNO, %rax
|
||||||
|
jb 1f
|
||||||
|
negl %eax
|
||||||
|
movl %eax, %edi
|
||||||
|
call __set_errno
|
||||||
|
1:
|
||||||
|
ret
|
||||||
|
END(splice)
|
16
libc/arch-x86_64/syscalls/tee.S
Normal file
16
libc/arch-x86_64/syscalls/tee.S
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/* Generated by gensyscalls.py. Do not edit. */
|
||||||
|
|
||||||
|
#include <private/bionic_asm.h>
|
||||||
|
|
||||||
|
ENTRY(tee)
|
||||||
|
movq %rcx, %r10
|
||||||
|
movl $__NR_tee, %eax
|
||||||
|
syscall
|
||||||
|
cmpq $-MAX_ERRNO, %rax
|
||||||
|
jb 1f
|
||||||
|
negl %eax
|
||||||
|
movl %eax, %edi
|
||||||
|
call __set_errno
|
||||||
|
1:
|
||||||
|
ret
|
||||||
|
END(tee)
|
16
libc/arch-x86_64/syscalls/vmsplice.S
Normal file
16
libc/arch-x86_64/syscalls/vmsplice.S
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/* Generated by gensyscalls.py. Do not edit. */
|
||||||
|
|
||||||
|
#include <private/bionic_asm.h>
|
||||||
|
|
||||||
|
ENTRY(vmsplice)
|
||||||
|
movq %rcx, %r10
|
||||||
|
movl $__NR_vmsplice, %eax
|
||||||
|
syscall
|
||||||
|
cmpq $-MAX_ERRNO, %rax
|
||||||
|
jb 1f
|
||||||
|
negl %eax
|
||||||
|
movl %eax, %edi
|
||||||
|
call __set_errno
|
||||||
|
1:
|
||||||
|
ret
|
||||||
|
END(vmsplice)
|
@ -33,6 +33,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <linux/fadvise.h>
|
#include <linux/fadvise.h>
|
||||||
#include <linux/fcntl.h>
|
#include <linux/fcntl.h>
|
||||||
|
#include <linux/uio.h>
|
||||||
#include <unistd.h> /* this is not required, but makes client code much happier */
|
#include <unistd.h> /* this is not required, but makes client code much happier */
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
@ -51,9 +52,12 @@ struct flock64 {
|
|||||||
#define F_SETLKW64 F_SETLKW
|
#define F_SETLKW64 F_SETLKW
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef O_ASYNC
|
#define O_ASYNC FASYNC
|
||||||
#define O_ASYNC FASYNC
|
|
||||||
#endif
|
#define SPLICE_F_MOVE 1
|
||||||
|
#define SPLICE_F_NONBLOCK 2
|
||||||
|
#define SPLICE_F_MORE 4
|
||||||
|
#define SPLICE_F_GIFT 8
|
||||||
|
|
||||||
#define SYNC_FILE_RANGE_WAIT_BEFORE 1
|
#define SYNC_FILE_RANGE_WAIT_BEFORE 1
|
||||||
#define SYNC_FILE_RANGE_WRITE 2
|
#define SYNC_FILE_RANGE_WRITE 2
|
||||||
@ -70,7 +74,10 @@ extern int open(const char*, int, ...);
|
|||||||
extern int open64(const char*, int, ...);
|
extern int open64(const char*, int, ...);
|
||||||
extern int posix_fallocate64(int, off64_t, off64_t);
|
extern int posix_fallocate64(int, off64_t, off64_t);
|
||||||
extern int posix_fallocate(int, off_t, off_t);
|
extern int posix_fallocate(int, off_t, off_t);
|
||||||
|
extern ssize_t splice(int, off64_t*, int, off64_t*, size_t, unsigned int);
|
||||||
|
extern ssize_t tee(int, int, size_t, unsigned int);
|
||||||
extern int unlinkat(int, const char*, int);
|
extern int unlinkat(int, const char*, int);
|
||||||
|
extern ssize_t vmsplice(int, const struct iovec*, size_t, unsigned int);
|
||||||
|
|
||||||
#if defined(__BIONIC_FORTIFY)
|
#if defined(__BIONIC_FORTIFY)
|
||||||
|
|
||||||
|
@ -132,3 +132,87 @@ TEST(fcntl, f_getlk64) {
|
|||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(fcntl, splice) {
|
||||||
|
int pipe_fds[2];
|
||||||
|
ASSERT_EQ(0, pipe(pipe_fds));
|
||||||
|
|
||||||
|
int in = open("/proc/cpuinfo", O_RDONLY);
|
||||||
|
ASSERT_NE(in, -1);
|
||||||
|
|
||||||
|
TemporaryFile tf;
|
||||||
|
|
||||||
|
ssize_t bytes_read = splice(in, 0, pipe_fds[1], NULL, 8*1024, SPLICE_F_MORE | SPLICE_F_MOVE);
|
||||||
|
ASSERT_NE(bytes_read, -1);
|
||||||
|
|
||||||
|
ssize_t bytes_written = splice(pipe_fds[0], NULL, tf.fd, 0, bytes_read, SPLICE_F_MORE | SPLICE_F_MOVE);
|
||||||
|
ASSERT_EQ(bytes_read, bytes_written);
|
||||||
|
|
||||||
|
close(pipe_fds[0]);
|
||||||
|
close(pipe_fds[1]);
|
||||||
|
close(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(fcntl, vmsplice) {
|
||||||
|
int pipe_fds[2];
|
||||||
|
ASSERT_EQ(0, pipe(pipe_fds));
|
||||||
|
|
||||||
|
iovec v[2];
|
||||||
|
v[0].iov_base = const_cast<char*>("hello ");
|
||||||
|
v[0].iov_len = 6;
|
||||||
|
v[1].iov_base = const_cast<char*>("world\n");
|
||||||
|
v[1].iov_len = 6;
|
||||||
|
ssize_t bytes_written = vmsplice(pipe_fds[1], v, sizeof(v)/sizeof(iovec), 0);
|
||||||
|
ASSERT_EQ(v[0].iov_len + v[1].iov_len, static_cast<size_t>(bytes_written));
|
||||||
|
close(pipe_fds[1]);
|
||||||
|
|
||||||
|
char buf[BUFSIZ];
|
||||||
|
FILE* fp = fdopen(pipe_fds[0], "r");
|
||||||
|
ASSERT_TRUE(fp != NULL);
|
||||||
|
ASSERT_TRUE(fgets(buf, sizeof(buf), fp) != NULL);
|
||||||
|
fclose(fp);
|
||||||
|
ASSERT_STREQ("hello world\n", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(fcntl, tee) {
|
||||||
|
char expected[256];
|
||||||
|
FILE* expected_fp = fopen("/proc/version", "r");
|
||||||
|
ASSERT_TRUE(expected_fp != NULL);
|
||||||
|
ASSERT_TRUE(fgets(expected, sizeof(expected), expected_fp) != NULL);
|
||||||
|
fclose(expected_fp);
|
||||||
|
|
||||||
|
int pipe1[2];
|
||||||
|
ASSERT_EQ(0, pipe(pipe1));
|
||||||
|
|
||||||
|
int pipe2[2];
|
||||||
|
ASSERT_EQ(0, pipe(pipe2));
|
||||||
|
|
||||||
|
int in = open("/proc/version", O_RDONLY);
|
||||||
|
ASSERT_NE(in, -1);
|
||||||
|
|
||||||
|
// Write /proc/version into pipe1.
|
||||||
|
ssize_t bytes_read = splice(in, 0, pipe1[1], NULL, 8*1024, SPLICE_F_MORE | SPLICE_F_MOVE);
|
||||||
|
ASSERT_NE(bytes_read, -1);
|
||||||
|
close(pipe1[1]);
|
||||||
|
|
||||||
|
// Tee /proc/version from pipe1 into pipe2.
|
||||||
|
ssize_t bytes_teed = tee(pipe1[0], pipe2[1], SIZE_MAX, 0);
|
||||||
|
ASSERT_EQ(bytes_read, bytes_teed);
|
||||||
|
close(pipe2[1]);
|
||||||
|
|
||||||
|
// The out fds of both pipe1 and pipe2 should now contain /proc/version.
|
||||||
|
char buf1[BUFSIZ];
|
||||||
|
FILE* fp1 = fdopen(pipe1[0], "r");
|
||||||
|
ASSERT_TRUE(fp1 != NULL);
|
||||||
|
ASSERT_TRUE(fgets(buf1, sizeof(buf1), fp1) != NULL);
|
||||||
|
fclose(fp1);
|
||||||
|
|
||||||
|
char buf2[BUFSIZ];
|
||||||
|
FILE* fp2 = fdopen(pipe2[0], "r");
|
||||||
|
ASSERT_TRUE(fp2 != NULL);
|
||||||
|
ASSERT_TRUE(fgets(buf2, sizeof(buf2), fp2) != NULL);
|
||||||
|
fclose(fp2);
|
||||||
|
|
||||||
|
ASSERT_STREQ(expected, buf1);
|
||||||
|
ASSERT_STREQ(expected, buf2);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user