Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F156499258
D19917.id56068.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D19917.id56068.diff
View Options
Index: sys/amd64/linux/linux_dummy.c
===================================================================
--- sys/amd64/linux/linux_dummy.c
+++ sys/amd64/linux/linux_dummy.c
@@ -59,7 +59,6 @@
UNIMPLEMENTED(uselib);
UNIMPLEMENTED(vserver);
-DUMMY(sendfile);
DUMMY(syslog);
DUMMY(setfsuid);
DUMMY(setfsgid);
Index: sys/amd64/linux32/linux32_dummy.c
===================================================================
--- sys/amd64/linux32/linux32_dummy.c
+++ sys/amd64/linux32/linux32_dummy.c
@@ -73,7 +73,6 @@
DUMMY(quotactl);
DUMMY(bdflush);
DUMMY(sysfs);
-DUMMY(sendfile);
DUMMY(setfsuid);
DUMMY(setfsgid);
DUMMY(pivot_root);
Index: sys/amd64/linux32/linux32_proto.h
===================================================================
--- sys/amd64/linux32/linux32_proto.h
+++ sys/amd64/linux32/linux32_proto.h
@@ -604,7 +604,10 @@
char uoss_l_[PADL_(l_stack_t *)]; l_stack_t * uoss; char uoss_r_[PADR_(l_stack_t *)];
};
struct linux_sendfile_args {
- register_t dummy;
+ char out_l_[PADL_(l_int)]; l_int out; char out_r_[PADR_(l_int)];
+ char in_l_[PADL_(l_int)]; l_int in; char in_r_[PADR_(l_int)];
+ char offset_l_[PADL_(l_long *)]; l_long * offset; char offset_r_[PADR_(l_long *)];
+ char count_l_[PADL_(l_size_t)]; l_size_t count; char count_r_[PADR_(l_size_t)];
};
struct linux_vfork_args {
register_t dummy;
Index: sys/amd64/linux32/linux32_sysent.c
===================================================================
--- sys/amd64/linux32/linux32_sysent.c
+++ sys/amd64/linux32/linux32_sysent.c
@@ -204,7 +204,7 @@
{ AS(linux_capget_args), (sy_call_t *)linux_capget, AUE_CAPGET, NULL, 0, 0, 0, SY_THR_STATIC }, /* 184 = linux_capget */
{ AS(linux_capset_args), (sy_call_t *)linux_capset, AUE_CAPSET, NULL, 0, 0, 0, SY_THR_STATIC }, /* 185 = linux_capset */
{ AS(linux_sigaltstack_args), (sy_call_t *)linux_sigaltstack, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 186 = linux_sigaltstack */
- { 0, (sy_call_t *)linux_sendfile, AUE_SENDFILE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 187 = linux_sendfile */
+ { AS(linux_sendfile_args), (sy_call_t *)linux_sendfile, AUE_SENDFILE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 187 = linux_sendfile */
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 188 = getpmsg */
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 189 = putpmsg */
{ 0, (sy_call_t *)linux_vfork, AUE_VFORK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 190 = linux_vfork */
Index: sys/amd64/linux32/syscalls.master
===================================================================
--- sys/amd64/linux32/syscalls.master
+++ sys/amd64/linux32/syscalls.master
@@ -338,7 +338,8 @@
struct l_user_cap_data *datap); }
186 AUE_NULL STD { int linux_sigaltstack(l_stack_t *uss, \
l_stack_t *uoss); }
-187 AUE_SENDFILE STD { int linux_sendfile(void); }
+187 AUE_SENDFILE STD { int linux_sendfile(l_int out, l_int in, \
+ l_long *offset, l_size_t count); }
188 AUE_GETPMSG UNIMPL getpmsg
189 AUE_PUTPMSG UNIMPL putpmsg
190 AUE_VFORK STD { int linux_vfork(void); }
@@ -412,7 +413,8 @@
236 AUE_NULL STD { int linux_lremovexattr(void); }
237 AUE_NULL STD { int linux_fremovexattr(void); }
238 AUE_NULL STD { int linux_tkill(int tid, int sig); }
-239 AUE_SENDFILE UNIMPL linux_sendfile64
+239 AUE_SENDFILE STD { int linux_sendfile64(l_int out, l_int in, \
+ l_long *offset, l_size_t count); }
240 AUE_NULL STD { int linux_sys_futex(void *uaddr, int op, uint32_t val, \
struct l_timespec *timeout, uint32_t *uaddr2, uint32_t val3); }
241 AUE_NULL STD { int linux_sched_setaffinity(l_pid_t pid, l_uint len, \
Index: sys/compat/linux/linux_socket.h
===================================================================
--- sys/compat/linux/linux_socket.h
+++ sys/compat/linux/linux_socket.h
@@ -172,6 +172,7 @@
#define LINUX_ACCEPT4 18
#define LINUX_RECVMMSG 19
#define LINUX_SENDMMSG 20
+#define LINUX_SENDFILE 21
#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
/* Socket defines */
Index: sys/compat/linux/linux_socket.c
===================================================================
--- sys/compat/linux/linux_socket.c
+++ sys/compat/linux/linux_socket.c
@@ -49,6 +49,7 @@
#include <sys/socketvar.h>
#include <sys/syscallsubr.h>
#include <sys/uio.h>
+#include <sys/stat.h>
#include <sys/syslog.h>
#include <sys/un.h>
@@ -75,6 +76,8 @@
#include <compat/linux/linux_timer.h>
#include <compat/linux/linux_util.h>
+#include <security/audit/audit.h>
+
static int linux_to_bsd_domain(int);
static int linux_sendmsg_common(struct thread *, l_int, struct l_msghdr *,
l_uint);
@@ -1693,6 +1696,97 @@
return (error);
}
+int
+linux_sendfile(struct thread *td, struct linux_sendfile_args *arg){
+ struct stat sb;
+ struct tcp_info ti;
+ off_t bytes_read;
+ int ret;
+ l_long offset;
+ struct file *fp;
+ socklen_t size_val;
+
+ /* XXX: The differences between freebsd and linux sendfile:
+ * - linux_sendfile doesn't send anything when count is 0
+ * whereas freebsd_sendfile sends the whole file. However,
+ * in linux_sendfile given fds are still checked for if they
+ * are valid or not when count is 0.
+ * - linux_sendfile can send to any fd whereas freebsd_sendfile
+ * only sends to a socket stream. Note that only socket streams
+ * are implemented here. Also note that the current offset into
+ * the fdin shouldn't change before and after sendfile. Meaning
+ * 'lseek(fd, 0, SET_CUR)' should return same before and after.
+ * - linux_sendfile doesn't have equivalents of flags and sf_hdtr of
+ * freebsd_sendfile.
+ * - linux_sendfile takes in an offset pointer and updates it to where it
+ * was read until. freebsd_sendfile takes in an offset and a
+ * 'bytes read' parameter which is only filled if it isn't NULL.
+ * We use this parameter to update the offset pointer if it exists.
+ * - linux_sendfile returns bytes read on success while freebsd_sendfile
+ * returns 0. We use the 'bytes read' parameter to get this value.
+ */
+
+ /* fstat to get info on target fd */
+ ret = kern_fstat(td, arg->out, &sb);
+ if (ret < 0)
+ return (ret);
+
+ /* non-socket descriptor not implemented */
+ if (!S_ISSOCK(sb.st_mode)) {
+ linux_msg(td,
+ "sendfile is only implemented for sending to a stream socket");
+ return (ENOSYS);
+ }
+
+ size_val = sizeof(ti);
+ ret = kern_getsockopt(td, arg->out, IPPROTO_TCP, TCP_INFO,
+ &ti, UIO_SYSSPACE, &size_val);
+
+ /* datagram socket not implemented */
+ if (ret != 0) {
+ linux_msg(td,
+ "sendfile is only implemented for sending to a stream socket");
+ return (ENOSYS);
+ }
+
+ /* offset is assumed as 0 when no pointer is given in linux_sendfile */
+ offset = 0;
+ if (arg->offset != NULL) {
+ ret = copyin(arg->offset, &offset, sizeof(arg->offset));
+ if (ret < 0)
+ return (ret);
+ }
+
+ if (offset < 0)
+ return (EINVAL);
+
+ bytes_read = 0;
+
+ AUDIT_ARG_FD(arg->in);
+ /* Checks if fdin is valid */
+ if ((ret = fget_read(td, arg->in, &cap_pread_rights, &fp)) != 0)
+ return (ret);
+
+ /* Call real sendfile iff count != 0 */
+ if (arg->count != 0) {
+ ret = fo_sendfile(fp, arg->out, NULL, NULL, offset, arg->count,
+ &bytes_read, 0, td);
+ if (ret < 0)
+ return (ret);
+
+ offset += bytes_read;
+ }
+
+ if (arg->offset != NULL) {
+ ret = copyout(&offset, arg->offset, sizeof(offset));
+ if (ret < 0)
+ return (ret);
+ }
+
+ td->td_retval[0] = (ssize_t) bytes_read;
+ return 0;
+}
+
#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
/* Argument list sizes for linux_socketcall */
@@ -1707,7 +1801,7 @@
5 /* setsockopt */, 5 /* getsockopt */,
3 /* sendmsg */, 3 /* recvmsg */,
4 /* accept4 */, 5 /* recvmmsg */,
- 4 /* sendmmsg */
+ 4 /* sendmmsg */, 4 /* sendfile */
};
#define LINUX_ARGS_CNT (nitems(lxs_args_cnt) - 1)
#define LINUX_ARG_SIZE(x) (lxs_args_cnt[x] * sizeof(l_ulong))
@@ -1776,6 +1870,8 @@
return (linux_recvmmsg(td, arg));
case LINUX_SENDMMSG:
return (linux_sendmmsg(td, arg));
+ case LINUX_SENDFILE:
+ return (linux_sendfile(td, arg));
}
uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, May 15, 3:56 AM (3 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33072427
Default Alt Text
D19917.id56068.diff (7 KB)
Attached To
Mode
D19917: Implement linux_sendfile for the linuxulator
Attached
Detach File
Event Timeline
Log In to Comment