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