Beispiel #1
0
int
cloudabi_sys_fd_stat_put(struct thread *td,
    struct cloudabi_sys_fd_stat_put_args *uap)
{
	cloudabi_fdstat_t fsb;
	cap_rights_t rights;
	int error, oflags;

	error = copyin(uap->buf, &fsb, sizeof(fsb));
	if (error != 0)
		return (error);

	if (uap->flags == CLOUDABI_FDSTAT_FLAGS) {
		/* Convert flags. */
		oflags = 0;
		if (fsb.fs_flags & CLOUDABI_FDFLAG_APPEND)
			oflags |= O_APPEND;
		if (fsb.fs_flags & CLOUDABI_FDFLAG_NONBLOCK)
			oflags |= O_NONBLOCK;
		if (fsb.fs_flags & (CLOUDABI_FDFLAG_SYNC |
		    CLOUDABI_FDFLAG_DSYNC | CLOUDABI_FDFLAG_RSYNC))
			oflags |= O_SYNC;
		return (kern_fcntl(td, uap->fd, F_SETFL, oflags));
	} else if (uap->flags == CLOUDABI_FDSTAT_RIGHTS) {
		/* Convert rights. */
		error = cloudabi_convert_rights(
		    fsb.fs_rights_base | fsb.fs_rights_inheriting, &rights);
		if (error != 0)
			return (error);
		return (kern_cap_rights_limit(td, uap->fd, &rights));
	}
	return (EINVAL);
}
Beispiel #2
0
int
cloudabi_sys_fd_stat_put(struct thread *td,
    struct cloudabi_sys_fd_stat_put_args *uap)
{
	cloudabi_fdstat_t fsb;
	int error, oflags;

	error = copyin(uap->buf, &fsb, sizeof(fsb));
	if (error != 0)
		return (error);

	if (uap->flags == CLOUDABI_FDSTAT_FLAGS) {
		/* Convert flags. */
		oflags = 0;
		if (fsb.fs_flags & CLOUDABI_FDFLAG_APPEND)
			oflags |= O_APPEND;
		if (fsb.fs_flags & CLOUDABI_FDFLAG_NONBLOCK)
			oflags |= O_NONBLOCK;
		if (fsb.fs_flags & (CLOUDABI_FDFLAG_SYNC |
		    CLOUDABI_FDFLAG_DSYNC | CLOUDABI_FDFLAG_RSYNC))
			oflags |= O_SYNC;
		return (kern_fcntl(td, uap->fd, F_SETFL, oflags));
	}
	return (EINVAL);
}
Beispiel #3
0
static int
linux_set_socket_flags(struct thread *td, int s, int flags)
{
	int error;

	if (flags & LINUX_SOCK_NONBLOCK) {
		error = kern_fcntl(td, s, F_SETFL, O_NONBLOCK);
		if (error)
			return (error);
	}
	if (flags & LINUX_SOCK_CLOEXEC) {
		error = kern_fcntl(td, s, F_SETFD, FD_CLOEXEC);
		if (error)
			return (error);
	}
	return (0);
}
Beispiel #4
0
static int
linux_accept(struct linux_accept_args *args, int *res)
{
	struct thread *td = curthread;
	struct linux_accept_args linux_args;
	struct sockaddr *sa = NULL;
	union fcntl_dat dat = { 0 };
	int error, sa_len;

	error = copyin(args, &linux_args, sizeof(linux_args));
	if (error)
		return (error);

	if (linux_args.addr) {
		error = copyin(linux_args.namelen, &sa_len, sizeof(sa_len));
		if (error)
			return (error);

		error = kern_accept(linux_args.s, 0, &sa, &sa_len, res);

		if (error) {
			/*
			 * Return a namelen of zero for older code which
			 * might ignore the return value from accept().
			 */
			sa_len = 0;
			copyout(&sa_len, linux_args.namelen,
			    sizeof(*linux_args.namelen));
		} else {
			error = linux_copyout_sockaddr(sa, linux_args.addr,
			    sa_len);
			if (error == 0) {
				error = copyout(&sa_len, linux_args.namelen,
				    sizeof(*linux_args.namelen));
			}
		}
		if (sa)
			kfree(sa, M_SONAME);
	} else {
		error = kern_accept(linux_args.s, 0, NULL, 0, res);
	}

	if (error)
		return (error);

	/*
	 * linux appears not to copy flags from the parent socket to the
	 * accepted one, so we must clear the flags in the new descriptor.
	 * Ignore any errors, because we already have an open fd.
	 */
	kern_fcntl(*res, F_SETFL, &dat, td->td_ucred);
	return (0);
}
Beispiel #5
0
static int
linux_accept_common(struct thread *td, int s, l_uintptr_t addr,
    l_uintptr_t namelen, int flags)
{
	struct accept_args /* {
		int	s;
		struct sockaddr * __restrict name;
		socklen_t * __restrict anamelen;
	} */ bsd_args;
	int error;

	if (flags & ~(LINUX_SOCK_CLOEXEC | LINUX_SOCK_NONBLOCK))
		return (EINVAL);

	bsd_args.s = s;
	/* XXX: */
	bsd_args.name = (struct sockaddr * __restrict)PTRIN(addr);
	bsd_args.anamelen = PTRIN(namelen);/* XXX */
	error = accept(td, &bsd_args);
	bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.name);
	if (error) {
		if (error == EFAULT && namelen != sizeof(struct sockaddr_in))
			return (EINVAL);
		return (error);
	}

	/*
	 * linux appears not to copy flags from the parent socket to the
	 * accepted one, so we must clear the flags in the new descriptor
	 * and apply the requested flags.
	 */
	error = kern_fcntl(td, td->td_retval[0], F_SETFL, 0);
	if (error)
		goto out;
	error = linux_set_socket_flags(td, td->td_retval[0], flags);
	if (error)
		goto out;
	if (addr)
		error = linux_sa_put(PTRIN(addr));

out:
	if (error) {
		(void)kern_close(td, td->td_retval[0]);
		td->td_retval[0] = 0;
	}
	return (error);
}