Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145570943
D19917.1778217117.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D19917.1778217117.diff
View Options
Index: head/sys/amd64/linux/linux_dummy.c
===================================================================
--- head/sys/amd64/linux/linux_dummy.c
+++ head/sys/amd64/linux/linux_dummy.c
@@ -59,7 +59,6 @@
UNIMPLEMENTED(uselib);
UNIMPLEMENTED(vserver);
-DUMMY(sendfile);
DUMMY(setfsuid);
DUMMY(setfsgid);
DUMMY(sysfs);
Index: head/sys/amd64/linux32/linux32_dummy.c
===================================================================
--- head/sys/amd64/linux32/linux32_dummy.c
+++ head/sys/amd64/linux32/linux32_dummy.c
@@ -72,7 +72,6 @@
DUMMY(quotactl);
DUMMY(bdflush);
DUMMY(sysfs);
-DUMMY(sendfile);
DUMMY(setfsuid);
DUMMY(setfsgid);
DUMMY(pivot_root);
Index: head/sys/amd64/linux32/syscalls.master
===================================================================
--- head/sys/amd64/linux32/syscalls.master
+++ head/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_loff_t *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: head/sys/arm/linux/syscalls.master
===================================================================
--- head/sys/arm/linux/syscalls.master
+++ head/sys/arm/linux/syscalls.master
@@ -868,7 +868,12 @@
);
}
187 AUE_SENDFILE STD {
- int linux_sendfile(void);
+ int linux_sendfile(
+ l_int out,
+ l_int in,
+ l_long *offset,
+ l_size_t count
+ );
}
188 AUE_NULL UNIMPL ; was getpmsg
189 AUE_NULL UNIMPL ; was putpmsg
@@ -1090,7 +1095,14 @@
int sig
);
}
-239 AUE_SENDFILE UNIMPL linux_sendfile64
+239 AUE_SENDFILE STD {
+ int linux_sendfile64(
+ l_int out,
+ l_int in,
+ l_loff_t *offset,
+ l_size_t count
+ );
+ }
240 AUE_NULL STD {
int linux_sys_futex(void *uaddr,
int op,
Index: head/sys/arm64/linux/linux_dummy.c
===================================================================
--- head/sys/arm64/linux/linux_dummy.c
+++ head/sys/arm64/linux/linux_dummy.c
@@ -64,7 +64,6 @@
UNIMPLEMENTED(uselib);
UNIMPLEMENTED(vserver);
-DUMMY(sendfile);
DUMMY(setfsuid);
DUMMY(setfsgid);
DUMMY(vhangup);
Index: head/sys/compat/linux/linux_socket.h
===================================================================
--- head/sys/compat/linux/linux_socket.h
+++ head/sys/compat/linux/linux_socket.h
@@ -132,7 +132,9 @@
uint32_t gid;
};
-#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
+#if defined(__i386__) || defined(__arm__) || \
+ (defined(__amd64__) && defined(COMPAT_LINUX32))
+
struct linux_accept_args {
register_t s;
register_t addr;
@@ -162,7 +164,9 @@
#define LINUX_ACCEPT4 18
#define LINUX_RECVMMSG 19
#define LINUX_SENDMMSG 20
-#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
+#define LINUX_SENDFILE 21
+
+#endif /* __i386__ || __arm__ || (__amd64__ && COMPAT_LINUX32) */
/* Socket defines */
#define LINUX_SOL_SOCKET 1
Index: head/sys/compat/linux/linux_socket.c
===================================================================
--- head/sys/compat/linux/linux_socket.c
+++ head/sys/compat/linux/linux_socket.c
@@ -49,9 +49,13 @@
#include <sys/socketvar.h>
#include <sys/syscallsubr.h>
#include <sys/uio.h>
+#include <sys/stat.h>
#include <sys/syslog.h>
#include <sys/un.h>
+#include <sys/unistd.h>
+#include <security/audit/audit.h>
+
#include <net/if.h>
#include <net/vnet.h>
#include <netinet/in.h>
@@ -1581,8 +1585,135 @@
return (error);
}
-#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
+static int
+linux_sendfile_common(struct thread *td, l_int out, l_int in,
+ l_loff_t *offset, l_size_t count)
+{
+ off_t bytes_read;
+ int error;
+ l_loff_t current_offset;
+ struct file *fp;
+ AUDIT_ARG_FD(in);
+ error = fget_read(td, in, &cap_pread_rights, &fp);
+ if (error != 0)
+ return (error);
+
+ if (offset != NULL) {
+ current_offset = *offset;
+ } else {
+ error = (fp->f_ops->fo_flags & DFLAG_SEEKABLE) != 0 ?
+ fo_seek(fp, 0, SEEK_CUR, td) : ESPIPE;
+ if (error != 0)
+ goto drop;
+ current_offset = td->td_uretoff.tdu_off;
+ }
+
+ bytes_read = 0;
+
+ /* Linux cannot have 0 count. */
+ if (count <= 0 || current_offset < 0) {
+ error = EINVAL;
+ goto drop;
+ }
+
+ error = fo_sendfile(fp, out, NULL, NULL, current_offset, count,
+ &bytes_read, 0, td);
+ if (error != 0)
+ goto drop;
+ current_offset += bytes_read;
+
+ if (offset != NULL) {
+ *offset = current_offset;
+ } else {
+ error = fo_seek(fp, current_offset, SEEK_SET, td);
+ if (error != 0)
+ goto drop;
+ }
+
+ td->td_retval[0] = (ssize_t)bytes_read;
+drop:
+ fdrop(fp, td);
+ return (error);
+}
+
+int
+linux_sendfile(struct thread *td, struct linux_sendfile_args *arg)
+{
+ /*
+ * Differences between FreeBSD and Linux sendfile:
+ * - Linux doesn't send anything when count is 0 (FreeBSD uses 0 to
+ * mean send the whole file.) In linux_sendfile given fds are still
+ * checked for validity when the count is 0.
+ * - Linux can send to any fd whereas FreeBSD only supports sockets.
+ * The same restriction follows for linux_sendfile.
+ * - Linux doesn't have an equivalent for FreeBSD's flags and sf_hdtr.
+ * - Linux takes an offset pointer and updates it to the read location.
+ * FreeBSD 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
+ * returns 0. We use the 'bytes read' parameter to get this value.
+ */
+
+ l_loff_t offset64;
+ l_long offset;
+ int ret;
+ int error;
+
+ if (arg->offset != NULL) {
+ error = copyin(arg->offset, &offset, sizeof(offset));
+ if (error != 0)
+ return (error);
+ offset64 = (l_loff_t)offset;
+ }
+
+ ret = linux_sendfile_common(td, arg->out, arg->in,
+ arg->offset != NULL ? &offset64 : NULL, arg->count);
+
+ if (arg->offset != NULL) {
+#if defined(__i386__) || defined(__arm__) || \
+ (defined(__amd64__) && defined(COMPAT_LINUX32))
+ if (offset64 > INT32_MAX)
+ return (EOVERFLOW);
+#endif
+ offset = (l_long)offset64;
+ error = copyout(&offset, arg->offset, sizeof(offset));
+ if (error != 0)
+ return (error);
+ }
+
+ return (ret);
+}
+
+#if defined(__i386__) || defined(__arm__) || \
+ (defined(__amd64__) && defined(COMPAT_LINUX32))
+
+int
+linux_sendfile64(struct thread *td, struct linux_sendfile64_args *arg)
+{
+ l_loff_t offset;
+ int ret;
+ int error;
+
+ if (arg->offset != NULL) {
+ error = copyin(arg->offset, &offset, sizeof(offset));
+ if (error != 0)
+ return (error);
+ }
+
+ ret = linux_sendfile_common(td, arg->out, arg->in,
+ arg->offset != NULL ? &offset : NULL, arg->count);
+
+ if (arg->offset != NULL) {
+ error = copyout(&offset, arg->offset, sizeof(offset));
+ if (error != 0)
+ return (error);
+ }
+
+ return (ret);
+}
+
/* Argument list sizes for linux_socketcall */
static const unsigned char lxs_args_cnt[] = {
0 /* unused*/, 3 /* socket */,
@@ -1595,7 +1726,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))
@@ -1664,9 +1795,11 @@
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);
return (ENOSYS);
}
-#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
+#endif /* __i386__ || __arm__ || (__amd64__ && COMPAT_LINUX32) */
Index: head/sys/i386/linux/linux_dummy.c
===================================================================
--- head/sys/i386/linux/linux_dummy.c
+++ head/sys/i386/linux/linux_dummy.c
@@ -75,7 +75,6 @@
DUMMY(bdflush);
DUMMY(sysfs);
DUMMY(vm86);
-DUMMY(sendfile); /* different semantics */
DUMMY(setfsuid);
DUMMY(setfsgid);
DUMMY(pivot_root);
Index: head/sys/i386/linux/syscalls.master
===================================================================
--- head/sys/i386/linux/syscalls.master
+++ head/sys/i386/linux/syscalls.master
@@ -341,7 +341,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); }
@@ -415,7 +416,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_loff_t *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, \
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, May 8, 5:11 AM (11 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28600990
Default Alt Text
D19917.1778217117.diff (9 KB)
Attached To
Mode
D19917: Implement linux_sendfile for the linuxulator
Attached
Detach File
Event Timeline
Log In to Comment