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); }
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); }
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); }
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); }
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); }