uipc_mqueue.c (1ee774f614e70c52baafdf8b7e9013b545d36f2b) uipc_mqueue.c (afde2b65938c86eaf4906998b5e9641ef5db62dc)
1/*-
2 * Copyright (c) 2005 David Xu <davidxu@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 31 unchanged lines hidden (view full) ---

40 * 2) Standard POSIX message queue API. The syscalls do not use vfs layer,
41 * but directly operate on internal data structure, this allows user to
42 * use the IPC facility without having to mount mqueue file system.
43 */
44
45#include <sys/cdefs.h>
46__FBSDID("$FreeBSD$");
47
1/*-
2 * Copyright (c) 2005 David Xu <davidxu@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 31 unchanged lines hidden (view full) ---

40 * 2) Standard POSIX message queue API. The syscalls do not use vfs layer,
41 * but directly operate on internal data structure, this allows user to
42 * use the IPC facility without having to mount mqueue file system.
43 */
44
45#include <sys/cdefs.h>
46__FBSDID("$FreeBSD$");
47
48#include "opt_compat.h"
49
48#include <sys/param.h>
49#include <sys/kernel.h>
50#include <sys/systm.h>
51#include <sys/limits.h>
52#include <sys/buf.h>
53#include <sys/dirent.h>
54#include <sys/event.h>
55#include <sys/eventhandler.h>

--- 1561 unchanged lines hidden (view full) ---

1617 * time will be checked.
1618 */
1619int
1620mqueue_send(struct mqueue *mq, const char *msg_ptr,
1621 size_t msg_len, unsigned msg_prio, int waitok,
1622 const struct timespec *abs_timeout)
1623{
1624 struct mqueue_msg *msg;
50#include <sys/param.h>
51#include <sys/kernel.h>
52#include <sys/systm.h>
53#include <sys/limits.h>
54#include <sys/buf.h>
55#include <sys/dirent.h>
56#include <sys/event.h>
57#include <sys/eventhandler.h>

--- 1561 unchanged lines hidden (view full) ---

1619 * time will be checked.
1620 */
1621int
1622mqueue_send(struct mqueue *mq, const char *msg_ptr,
1623 size_t msg_len, unsigned msg_prio, int waitok,
1624 const struct timespec *abs_timeout)
1625{
1626 struct mqueue_msg *msg;
1625 struct timespec ets, ts, ts2;
1627 struct timespec ts, ts2;
1626 struct timeval tv;
1627 int error;
1628
1629 if (msg_prio >= MQ_PRIO_MAX)
1630 return (EINVAL);
1631 if (msg_len > mq->mq_msgsize)
1632 return (EMSGSIZE);
1633 msg = mqueue_loadmsg(msg_ptr, msg_len, msg_prio);

--- 19 unchanged lines hidden (view full) ---

1653 /* send it before checking time */
1654 error = _mqueue_send(mq, msg, -1);
1655 if (error == 0)
1656 return (0);
1657
1658 if (error != EAGAIN)
1659 goto bad;
1660
1628 struct timeval tv;
1629 int error;
1630
1631 if (msg_prio >= MQ_PRIO_MAX)
1632 return (EINVAL);
1633 if (msg_len > mq->mq_msgsize)
1634 return (EMSGSIZE);
1635 msg = mqueue_loadmsg(msg_ptr, msg_len, msg_prio);

--- 19 unchanged lines hidden (view full) ---

1655 /* send it before checking time */
1656 error = _mqueue_send(mq, msg, -1);
1657 if (error == 0)
1658 return (0);
1659
1660 if (error != EAGAIN)
1661 goto bad;
1662
1661 error = copyin(abs_timeout, &ets, sizeof(ets));
1662 if (error != 0)
1663 goto bad;
1664 if (ets.tv_nsec >= 1000000000 || ets.tv_nsec < 0) {
1663 if (abs_timeout->tv_nsec >= 1000000000 || abs_timeout->tv_nsec < 0) {
1665 error = EINVAL;
1666 goto bad;
1667 }
1668 for (;;) {
1664 error = EINVAL;
1665 goto bad;
1666 }
1667 for (;;) {
1669 ts2 = ets;
1668 ts2 = *abs_timeout;
1670 getnanotime(&ts);
1671 timespecsub(&ts2, &ts);
1672 if (ts2.tv_sec < 0 || (ts2.tv_sec == 0 && ts2.tv_nsec <= 0)) {
1673 error = ETIMEDOUT;
1674 break;
1675 }
1676 TIMESPEC_TO_TIMEVAL(&tv, &ts2);
1677 error = _mqueue_send(mq, msg, tvtohz(&tv));

--- 90 unchanged lines hidden (view full) ---

1768 * time will be checked.
1769 */
1770int
1771mqueue_receive(struct mqueue *mq, char *msg_ptr,
1772 size_t msg_len, unsigned *msg_prio, int waitok,
1773 const struct timespec *abs_timeout)
1774{
1775 struct mqueue_msg *msg;
1669 getnanotime(&ts);
1670 timespecsub(&ts2, &ts);
1671 if (ts2.tv_sec < 0 || (ts2.tv_sec == 0 && ts2.tv_nsec <= 0)) {
1672 error = ETIMEDOUT;
1673 break;
1674 }
1675 TIMESPEC_TO_TIMEVAL(&tv, &ts2);
1676 error = _mqueue_send(mq, msg, tvtohz(&tv));

--- 90 unchanged lines hidden (view full) ---

1767 * time will be checked.
1768 */
1769int
1770mqueue_receive(struct mqueue *mq, char *msg_ptr,
1771 size_t msg_len, unsigned *msg_prio, int waitok,
1772 const struct timespec *abs_timeout)
1773{
1774 struct mqueue_msg *msg;
1776 struct timespec ets, ts, ts2;
1775 struct timespec ts, ts2;
1777 struct timeval tv;
1778 int error;
1779
1780 if (msg_len < mq->mq_msgsize)
1781 return (EMSGSIZE);
1782
1783 /* O_NONBLOCK case */
1784 if (!waitok) {

--- 14 unchanged lines hidden (view full) ---

1799 /* try to get a message before checking time */
1800 error = _mqueue_recv(mq, &msg, -1);
1801 if (error == 0)
1802 goto received;
1803
1804 if (error != EAGAIN)
1805 return (error);
1806
1776 struct timeval tv;
1777 int error;
1778
1779 if (msg_len < mq->mq_msgsize)
1780 return (EMSGSIZE);
1781
1782 /* O_NONBLOCK case */
1783 if (!waitok) {

--- 14 unchanged lines hidden (view full) ---

1798 /* try to get a message before checking time */
1799 error = _mqueue_recv(mq, &msg, -1);
1800 if (error == 0)
1801 goto received;
1802
1803 if (error != EAGAIN)
1804 return (error);
1805
1807 error = copyin(abs_timeout, &ets, sizeof(ets));
1808 if (error != 0)
1809 return (error);
1810 if (ets.tv_nsec >= 1000000000 || ets.tv_nsec < 0) {
1806 if (abs_timeout->tv_nsec >= 1000000000 || abs_timeout->tv_nsec < 0) {
1811 error = EINVAL;
1812 return (error);
1813 }
1814
1815 for (;;) {
1807 error = EINVAL;
1808 return (error);
1809 }
1810
1811 for (;;) {
1816 ts2 = ets;
1812 ts2 = *abs_timeout;
1817 getnanotime(&ts);
1818 timespecsub(&ts2, &ts);
1819 if (ts2.tv_sec < 0 || (ts2.tv_sec == 0 && ts2.tv_nsec <= 0)) {
1820 error = ETIMEDOUT;
1821 return (error);
1822 }
1823 TIMESPEC_TO_TIMEVAL(&tv, &ts2);
1824 error = _mqueue_recv(mq, &msg, tvtohz(&tv));

--- 104 unchanged lines hidden (view full) ---

1929 if (mq->mq_notifier == nt)
1930 mq->mq_notifier = NULL;
1931 sigqueue_take(&nt->nt_ksi);
1932 notifier_delete(p, nt);
1933 }
1934 PROC_UNLOCK(p);
1935}
1936
1813 getnanotime(&ts);
1814 timespecsub(&ts2, &ts);
1815 if (ts2.tv_sec < 0 || (ts2.tv_sec == 0 && ts2.tv_nsec <= 0)) {
1816 error = ETIMEDOUT;
1817 return (error);
1818 }
1819 TIMESPEC_TO_TIMEVAL(&tv, &ts2);
1820 error = _mqueue_recv(mq, &msg, tvtohz(&tv));

--- 104 unchanged lines hidden (view full) ---

1925 if (mq->mq_notifier == nt)
1926 mq->mq_notifier = NULL;
1927 sigqueue_take(&nt->nt_ksi);
1928 notifier_delete(p, nt);
1929 }
1930 PROC_UNLOCK(p);
1931}
1932
1937/*
1938 * Syscall to open a message queue.
1939 */
1940int
1941kmq_open(struct thread *td, struct kmq_open_args *uap)
1933static int
1934kern_kmq_open(struct thread *td, const char *upath, int flags, mode_t mode,
1935 const struct mq_attr *attr)
1942{
1943 char path[MQFS_NAMELEN + 1];
1936{
1937 char path[MQFS_NAMELEN + 1];
1944 struct mq_attr attr, *pattr;
1945 struct mqfs_node *pn;
1946 struct filedesc *fdp;
1947 struct file *fp;
1948 struct mqueue *mq;
1938 struct mqfs_node *pn;
1939 struct filedesc *fdp;
1940 struct file *fp;
1941 struct mqueue *mq;
1949 int fd, error, len, flags, cmode;
1942 int fd, error, len, cmode;
1950
1943
1951 if ((uap->flags & O_ACCMODE) == O_ACCMODE)
1952 return (EINVAL);
1953
1954 fdp = td->td_proc->p_fd;
1944 fdp = td->td_proc->p_fd;
1955 flags = FFLAGS(uap->flags);
1956 cmode = (((uap->mode & ~fdp->fd_cmask) & ALLPERMS) & ~S_ISTXT);
1945 cmode = (((mode & ~fdp->fd_cmask) & ALLPERMS) & ~S_ISTXT);
1957 mq = NULL;
1946 mq = NULL;
1958 if ((flags & O_CREAT) && (uap->attr != NULL)) {
1959 error = copyin(uap->attr, &attr, sizeof(attr));
1960 if (error)
1961 return (error);
1962 if (attr.mq_maxmsg <= 0 || attr.mq_maxmsg > maxmsg)
1947 if ((flags & O_CREAT) != 0 && attr != NULL) {
1948 if (attr->mq_maxmsg <= 0 || attr->mq_maxmsg > maxmsg)
1963 return (EINVAL);
1949 return (EINVAL);
1964 if (attr.mq_msgsize <= 0 || attr.mq_msgsize > maxmsgsize)
1950 if (attr->mq_msgsize <= 0 || attr->mq_msgsize > maxmsgsize)
1965 return (EINVAL);
1951 return (EINVAL);
1966 pattr = &attr;
1967 } else
1968 pattr = NULL;
1952 }
1969
1953
1970 error = copyinstr(uap->path, path, MQFS_NAMELEN + 1, NULL);
1954 error = copyinstr(upath, path, MQFS_NAMELEN + 1, NULL);
1971 if (error)
1972 return (error);
1973
1974 /*
1975 * The first character of name must be a slash (/) character
1976 * and the remaining characters of name cannot include any slash
1977 * characters.
1978 */

--- 6 unchanged lines hidden (view full) ---

1985 return (error);
1986
1987 sx_xlock(&mqfs_data.mi_lock);
1988 pn = mqfs_search(mqfs_data.mi_root, path + 1, len - 1);
1989 if (pn == NULL) {
1990 if (!(flags & O_CREAT)) {
1991 error = ENOENT;
1992 } else {
1955 if (error)
1956 return (error);
1957
1958 /*
1959 * The first character of name must be a slash (/) character
1960 * and the remaining characters of name cannot include any slash
1961 * characters.
1962 */

--- 6 unchanged lines hidden (view full) ---

1969 return (error);
1970
1971 sx_xlock(&mqfs_data.mi_lock);
1972 pn = mqfs_search(mqfs_data.mi_root, path + 1, len - 1);
1973 if (pn == NULL) {
1974 if (!(flags & O_CREAT)) {
1975 error = ENOENT;
1976 } else {
1993 mq = mqueue_alloc(pattr);
1977 mq = mqueue_alloc(attr);
1994 if (mq == NULL) {
1995 error = ENFILE;
1996 } else {
1997 pn = mqfs_create_file(mqfs_data.mi_root,
1998 path + 1, len - 1, td->td_ucred,
1999 cmode);
2000 if (pn == NULL) {
2001 error = ENOSPC;

--- 38 unchanged lines hidden (view full) ---

2040 fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
2041 FILEDESC_XUNLOCK(fdp);
2042 td->td_retval[0] = fd;
2043 fdrop(fp, td);
2044 return (0);
2045}
2046
2047/*
1978 if (mq == NULL) {
1979 error = ENFILE;
1980 } else {
1981 pn = mqfs_create_file(mqfs_data.mi_root,
1982 path + 1, len - 1, td->td_ucred,
1983 cmode);
1984 if (pn == NULL) {
1985 error = ENOSPC;

--- 38 unchanged lines hidden (view full) ---

2024 fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
2025 FILEDESC_XUNLOCK(fdp);
2026 td->td_retval[0] = fd;
2027 fdrop(fp, td);
2028 return (0);
2029}
2030
2031/*
2032 * Syscall to open a message queue.
2033 */
2034int
2035kmq_open(struct thread *td, struct kmq_open_args *uap)
2036{
2037 struct mq_attr attr;
2038 int flags, error;
2039
2040 if ((uap->flags & O_ACCMODE) == O_ACCMODE)
2041 return (EINVAL);
2042 flags = FFLAGS(uap->flags);
2043 if ((flags & O_CREAT) != 0 && uap->attr != NULL) {
2044 error = copyin(uap->attr, &attr, sizeof(attr));
2045 if (error)
2046 return (error);
2047 }
2048 return (kern_kmq_open(td, uap->path, flags, uap->mode,
2049 uap->attr != NULL ? &attr : NULL));
2050}
2051
2052/*
2048 * Syscall to unlink a message queue.
2049 */
2050int
2051kmq_unlink(struct thread *td, struct kmq_unlink_args *uap)
2052{
2053 char path[MQFS_NAMELEN+1];
2054 struct mqfs_node *pn;
2055 int error, len;

--- 59 unchanged lines hidden (view full) ---

2115
2116static __inline int
2117getmq_write(struct thread *td, int fd, struct file **fpp,
2118 struct mqfs_node **ppn, struct mqueue **pmq)
2119{
2120 return _getmq(td, fd, fget_write, fpp, ppn, pmq);
2121}
2122
2053 * Syscall to unlink a message queue.
2054 */
2055int
2056kmq_unlink(struct thread *td, struct kmq_unlink_args *uap)
2057{
2058 char path[MQFS_NAMELEN+1];
2059 struct mqfs_node *pn;
2060 int error, len;

--- 59 unchanged lines hidden (view full) ---

2120
2121static __inline int
2122getmq_write(struct thread *td, int fd, struct file **fpp,
2123 struct mqfs_node **ppn, struct mqueue **pmq)
2124{
2125 return _getmq(td, fd, fget_write, fpp, ppn, pmq);
2126}
2127
2123int
2124kmq_setattr(struct thread *td, struct kmq_setattr_args *uap)
2128static int
2129kern_kmq_setattr(struct thread *td, int mqd, const struct mq_attr *attr,
2130 struct mq_attr *oattr)
2125{
2126 struct mqueue *mq;
2127 struct file *fp;
2131{
2132 struct mqueue *mq;
2133 struct file *fp;
2128 struct mq_attr attr, oattr;
2129 u_int oflag, flag;
2130 int error;
2131
2134 u_int oflag, flag;
2135 int error;
2136
2132 if (uap->attr) {
2133 error = copyin(uap->attr, &attr, sizeof(attr));
2134 if (error)
2135 return (error);
2136 if (attr.mq_flags & ~O_NONBLOCK)
2137 return (EINVAL);
2138 }
2139 error = getmq(td, uap->mqd, &fp, NULL, &mq);
2137 if (attr != NULL && (attr->mq_flags & ~O_NONBLOCK) != 0)
2138 return (EINVAL);
2139 error = getmq(td, mqd, &fp, NULL, &mq);
2140 if (error)
2141 return (error);
2140 if (error)
2141 return (error);
2142 oattr.mq_maxmsg = mq->mq_maxmsg;
2143 oattr.mq_msgsize = mq->mq_msgsize;
2144 oattr.mq_curmsgs = mq->mq_curmsgs;
2145 if (uap->attr) {
2142 oattr->mq_maxmsg = mq->mq_maxmsg;
2143 oattr->mq_msgsize = mq->mq_msgsize;
2144 oattr->mq_curmsgs = mq->mq_curmsgs;
2145 if (attr != NULL) {
2146 do {
2147 oflag = flag = fp->f_flag;
2148 flag &= ~O_NONBLOCK;
2146 do {
2147 oflag = flag = fp->f_flag;
2148 flag &= ~O_NONBLOCK;
2149 flag |= (attr.mq_flags & O_NONBLOCK);
2149 flag |= (attr->mq_flags & O_NONBLOCK);
2150 } while (atomic_cmpset_int(&fp->f_flag, oflag, flag) == 0);
2151 } else
2152 oflag = fp->f_flag;
2150 } while (atomic_cmpset_int(&fp->f_flag, oflag, flag) == 0);
2151 } else
2152 oflag = fp->f_flag;
2153 oattr.mq_flags = (O_NONBLOCK & oflag);
2153 oattr->mq_flags = (O_NONBLOCK & oflag);
2154 fdrop(fp, td);
2154 fdrop(fp, td);
2155 if (uap->oattr)
2155 return (error);
2156}
2157
2158int
2159kmq_setattr(struct thread *td, struct kmq_setattr_args *uap)
2160{
2161 struct mq_attr attr, oattr;
2162 int error;
2163
2164 if (uap->attr != NULL) {
2165 error = copyin(uap->attr, &attr, sizeof(attr));
2166 if (error != 0)
2167 return (error);
2168 }
2169 error = kern_kmq_setattr(td, uap->mqd, uap->attr != NULL ? &attr : NULL,
2170 &oattr);
2171 if (error != 0)
2172 return (error);
2173 if (uap->oattr != NULL)
2156 error = copyout(&oattr, uap->oattr, sizeof(oattr));
2157 return (error);
2158}
2159
2160int
2161kmq_timedreceive(struct thread *td, struct kmq_timedreceive_args *uap)
2162{
2163 struct mqueue *mq;
2164 struct file *fp;
2174 error = copyout(&oattr, uap->oattr, sizeof(oattr));
2175 return (error);
2176}
2177
2178int
2179kmq_timedreceive(struct thread *td, struct kmq_timedreceive_args *uap)
2180{
2181 struct mqueue *mq;
2182 struct file *fp;
2183 struct timespec *abs_timeout, ets;
2165 int error;
2166 int waitok;
2167
2168 error = getmq_read(td, uap->mqd, &fp, NULL, &mq);
2169 if (error)
2170 return (error);
2184 int error;
2185 int waitok;
2186
2187 error = getmq_read(td, uap->mqd, &fp, NULL, &mq);
2188 if (error)
2189 return (error);
2190 if (uap->abs_timeout != NULL) {
2191 error = copyin(uap->abs_timeout, &ets, sizeof(ets));
2192 if (error != 0)
2193 return (error);
2194 abs_timeout = &ets;
2195 } else
2196 abs_timeout = NULL;
2171 waitok = !(fp->f_flag & O_NONBLOCK);
2172 error = mqueue_receive(mq, uap->msg_ptr, uap->msg_len,
2197 waitok = !(fp->f_flag & O_NONBLOCK);
2198 error = mqueue_receive(mq, uap->msg_ptr, uap->msg_len,
2173 uap->msg_prio, waitok, uap->abs_timeout);
2199 uap->msg_prio, waitok, abs_timeout);
2174 fdrop(fp, td);
2175 return (error);
2176}
2177
2178int
2179kmq_timedsend(struct thread *td, struct kmq_timedsend_args *uap)
2180{
2181 struct mqueue *mq;
2182 struct file *fp;
2200 fdrop(fp, td);
2201 return (error);
2202}
2203
2204int
2205kmq_timedsend(struct thread *td, struct kmq_timedsend_args *uap)
2206{
2207 struct mqueue *mq;
2208 struct file *fp;
2209 struct timespec *abs_timeout, ets;
2183 int error, waitok;
2184
2185 error = getmq_write(td, uap->mqd, &fp, NULL, &mq);
2186 if (error)
2187 return (error);
2210 int error, waitok;
2211
2212 error = getmq_write(td, uap->mqd, &fp, NULL, &mq);
2213 if (error)
2214 return (error);
2215 if (uap->abs_timeout != NULL) {
2216 error = copyin(uap->abs_timeout, &ets, sizeof(ets));
2217 if (error != 0)
2218 return (error);
2219 abs_timeout = &ets;
2220 } else
2221 abs_timeout = NULL;
2188 waitok = !(fp->f_flag & O_NONBLOCK);
2189 error = mqueue_send(mq, uap->msg_ptr, uap->msg_len,
2222 waitok = !(fp->f_flag & O_NONBLOCK);
2223 error = mqueue_send(mq, uap->msg_ptr, uap->msg_len,
2190 uap->msg_prio, waitok, uap->abs_timeout);
2224 uap->msg_prio, waitok, abs_timeout);
2191 fdrop(fp, td);
2192 return (error);
2193}
2194
2195int
2196kmq_notify(struct thread *td, struct kmq_notify_args *uap)
2197{
2198 struct sigevent ev;

--- 307 unchanged lines hidden (view full) ---

2506 .vfs_init = mqfs_init,
2507 .vfs_uninit = mqfs_uninit,
2508 .vfs_mount = mqfs_mount,
2509 .vfs_unmount = mqfs_unmount,
2510 .vfs_root = mqfs_root,
2511 .vfs_statfs = mqfs_statfs,
2512};
2513
2225 fdrop(fp, td);
2226 return (error);
2227}
2228
2229int
2230kmq_notify(struct thread *td, struct kmq_notify_args *uap)
2231{
2232 struct sigevent ev;

--- 307 unchanged lines hidden (view full) ---

2540 .vfs_init = mqfs_init,
2541 .vfs_uninit = mqfs_uninit,
2542 .vfs_mount = mqfs_mount,
2543 .vfs_unmount = mqfs_unmount,
2544 .vfs_root = mqfs_root,
2545 .vfs_statfs = mqfs_statfs,
2546};
2547
2514SYSCALL_MODULE_HELPER(kmq_open);
2515SYSCALL_MODULE_HELPER(kmq_setattr);
2516SYSCALL_MODULE_HELPER(kmq_timedsend);
2517SYSCALL_MODULE_HELPER(kmq_timedreceive);
2518SYSCALL_MODULE_HELPER(kmq_notify);
2519SYSCALL_MODULE_HELPER(kmq_unlink);
2548static struct vfsconf mqueuefs_vfsconf = {
2549 .vfc_version = VFS_VERSION,
2550 .vfc_name = "mqueuefs",
2551 .vfc_vfsops = &mqfs_vfsops,
2552 .vfc_typenum = -1,
2553 .vfc_flags = VFCF_SYNTHETIC
2554};
2520
2555
2521VFS_SET(mqfs_vfsops, mqueuefs, VFCF_SYNTHETIC);
2556static struct syscall_helper_data mq_syscalls[] = {
2557 SYSCALL_INIT_HELPER(kmq_open),
2558 SYSCALL_INIT_HELPER(kmq_setattr),
2559 SYSCALL_INIT_HELPER(kmq_timedsend),
2560 SYSCALL_INIT_HELPER(kmq_timedreceive),
2561 SYSCALL_INIT_HELPER(kmq_notify),
2562 SYSCALL_INIT_HELPER(kmq_unlink),
2563 SYSCALL_INIT_LAST
2564};
2565
2566#ifdef COMPAT_FREEBSD32
2567#include <compat/freebsd32/freebsd32.h>
2568#include <compat/freebsd32/freebsd32_proto.h>
2569#include <compat/freebsd32/freebsd32_syscall.h>
2570#include <compat/freebsd32/freebsd32_util.h>
2571
2572static void
2573mq_attr_from32(const struct mq_attr32 *from, struct mq_attr *to)
2574{
2575
2576 to->mq_flags = from->mq_flags;
2577 to->mq_maxmsg = from->mq_maxmsg;
2578 to->mq_msgsize = from->mq_msgsize;
2579 to->mq_curmsgs = from->mq_curmsgs;
2580}
2581
2582static void
2583mq_attr_to32(const struct mq_attr *from, struct mq_attr32 *to)
2584{
2585
2586 to->mq_flags = from->mq_flags;
2587 to->mq_maxmsg = from->mq_maxmsg;
2588 to->mq_msgsize = from->mq_msgsize;
2589 to->mq_curmsgs = from->mq_curmsgs;
2590}
2591
2592int
2593freebsd32_kmq_open(struct thread *td, struct freebsd32_kmq_open_args *uap)
2594{
2595 struct mq_attr attr;
2596 struct mq_attr32 attr32;
2597 int flags, error;
2598
2599 if ((uap->flags & O_ACCMODE) == O_ACCMODE)
2600 return (EINVAL);
2601 flags = FFLAGS(uap->flags);
2602 if ((flags & O_CREAT) != 0 && uap->attr != NULL) {
2603 error = copyin(uap->attr, &attr32, sizeof(attr32));
2604 if (error)
2605 return (error);
2606 mq_attr_from32(&attr32, &attr);
2607 }
2608 return (kern_kmq_open(td, uap->path, flags, uap->mode,
2609 uap->attr != NULL ? &attr : NULL));
2610}
2611
2612int
2613freebsd32_kmq_setattr(struct thread *td, struct freebsd32_kmq_setattr_args *uap)
2614{
2615 struct mq_attr attr, oattr;
2616 struct mq_attr32 attr32, oattr32;
2617 int error;
2618
2619 if (uap->attr != NULL) {
2620 error = copyin(uap->attr, &attr32, sizeof(attr32));
2621 if (error != 0)
2622 return (error);
2623 mq_attr_from32(&attr32, &attr);
2624 }
2625 error = kern_kmq_setattr(td, uap->mqd, uap->attr != NULL ? &attr : NULL,
2626 &oattr);
2627 if (error != 0)
2628 return (error);
2629 if (uap->oattr != NULL) {
2630 mq_attr_to32(&oattr, &oattr32);
2631 error = copyout(&oattr32, uap->oattr, sizeof(oattr32));
2632 }
2633 return (error);
2634}
2635
2636int
2637freebsd32_kmq_timedsend(struct thread *td,
2638 struct freebsd32_kmq_timedsend_args *uap)
2639{
2640 struct mqueue *mq;
2641 struct file *fp;
2642 struct timespec32 ets32;
2643 struct timespec *abs_timeout, ets;
2644 int error;
2645 int waitok;
2646
2647 error = getmq_read(td, uap->mqd, &fp, NULL, &mq);
2648 if (error)
2649 return (error);
2650 if (uap->abs_timeout != NULL) {
2651 error = copyin(uap->abs_timeout, &ets32, sizeof(ets32));
2652 if (error != 0)
2653 return (error);
2654 CP(ets32, ets, tv_sec);
2655 CP(ets32, ets, tv_nsec);
2656 abs_timeout = &ets;
2657 } else
2658 abs_timeout = NULL;
2659 waitok = !(fp->f_flag & O_NONBLOCK);
2660 error = mqueue_send(mq, uap->msg_ptr, uap->msg_len,
2661 uap->msg_prio, waitok, abs_timeout);
2662 fdrop(fp, td);
2663 return (error);
2664}
2665
2666int
2667freebsd32_kmq_timedreceive(struct thread *td,
2668 struct freebsd32_kmq_timedreceive_args *uap)
2669{
2670 struct mqueue *mq;
2671 struct file *fp;
2672 struct timespec32 ets32;
2673 struct timespec *abs_timeout, ets;
2674 int error, waitok;
2675
2676 error = getmq_write(td, uap->mqd, &fp, NULL, &mq);
2677 if (error)
2678 return (error);
2679 if (uap->abs_timeout != NULL) {
2680 error = copyin(uap->abs_timeout, &ets32, sizeof(ets32));
2681 if (error != 0)
2682 return (error);
2683 CP(ets32, ets, tv_sec);
2684 CP(ets32, ets, tv_nsec);
2685 abs_timeout = &ets;
2686 } else
2687 abs_timeout = NULL;
2688 waitok = !(fp->f_flag & O_NONBLOCK);
2689 error = mqueue_receive(mq, uap->msg_ptr, uap->msg_len,
2690 uap->msg_prio, waitok, abs_timeout);
2691 fdrop(fp, td);
2692 return (error);
2693}
2694
2695static struct syscall_helper_data mq32_syscalls[] = {
2696 SYSCALL32_INIT_HELPER(freebsd32_kmq_open),
2697 SYSCALL32_INIT_HELPER(freebsd32_kmq_setattr),
2698 SYSCALL32_INIT_HELPER(freebsd32_kmq_timedsend),
2699 SYSCALL32_INIT_HELPER(freebsd32_kmq_timedreceive),
2700 SYSCALL32_INIT_HELPER(kmq_notify),
2701 SYSCALL32_INIT_HELPER(kmq_unlink),
2702 SYSCALL_INIT_LAST
2703};
2704#endif
2705
2706static int
2707mqinit(void)
2708{
2709 int error;
2710
2711 error = syscall_helper_register(mq_syscalls);
2712 if (error != 0)
2713 return (error);
2714#ifdef COMPAT_FREEBSD32
2715 error = syscall32_helper_register(mq32_syscalls);
2716 if (error != 0)
2717 return (error);
2718#endif
2719 return (0);
2720}
2721
2722static int
2723mqunload(void)
2724{
2725
2726#ifdef COMPAT_FREEBSD32
2727 syscall32_helper_unregister(mq32_syscalls);
2728#endif
2729 syscall_helper_unregister(mq_syscalls);
2730 return (0);
2731}
2732
2733static int
2734mq_modload(struct module *module, int cmd, void *arg)
2735{
2736 int error = 0;
2737
2738 error = vfs_modevent(module, cmd, arg);
2739 if (error != 0)
2740 return (error);
2741
2742 switch (cmd) {
2743 case MOD_LOAD:
2744 error = mqinit();
2745 if (error != 0)
2746 mqunload();
2747 break;
2748 case MOD_UNLOAD:
2749 error = mqunload();
2750 break;
2751 default:
2752 break;
2753 }
2754 return (error);
2755}
2756
2757static moduledata_t mqueuefs_mod = {
2758 "mqueuefs",
2759 mq_modload,
2760 &mqueuefs_vfsconf
2761};
2762DECLARE_MODULE(mqueuefs, mqueuefs_mod, SI_SUB_VFS, SI_ORDER_MIDDLE);
2522MODULE_VERSION(mqueuefs, 1);
2763MODULE_VERSION(mqueuefs, 1);