source: rtems-libbsd/rtemsbsd/sys/fs/devfs/devfs_devs.c @ 774f19f

55-freebsd-126-freebsd-12
Last change on this file since 774f19f was 774f19f, checked in by Sebastian Huber <sebastian.huber@…>, on Jan 10, 2017 at 1:40:29 PM

devfs: Fix typo

  • Property mode set to 100755
File size: 8.2 KB
Line 
1/*
2 * Copyright (c) 2016 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <machine/rtems-bsd-kernel-space.h>
33
34#include <sys/types.h>
35#include <sys/conf.h>
36#include <sys/kernel.h>
37#include <sys/file.h>
38#include <sys/malloc.h>
39#include <stdlib.h>
40#include <string.h>
41#include <unistd.h>
42
43#include <fs/devfs/devfs_int.h>
44
45#include <machine/pcpu.h>
46
47#include <rtems/imfs.h>
48
49#define DEVFS_ROOTINO 2
50
51const char rtems_cdev_directory[] = RTEMS_CDEV_DIRECTORY;
52
53struct unrhdr *devfs_inos;
54
55static struct cdev *
56devfs_imfs_get_context_by_iop(rtems_libio_t *iop)
57{
58        return IMFS_generic_get_context_by_iop(iop);
59}
60
61static int
62devfs_imfs_open(rtems_libio_t *iop, const char *path, int oflag, mode_t mode)
63{
64        struct cdev *cdev = devfs_imfs_get_context_by_iop(iop);
65        struct thread *td = rtems_bsd_get_curthread_or_null();
66        int error;
67
68        if (td != NULL) {
69                error = cdev->si_devsw->d_open(cdev, oflag, 0, td);
70        } else {
71                error = ENOMEM;
72        }
73
74        return rtems_bsd_error_to_status_and_errno(error);
75}
76
77static int
78devfs_imfs_close(rtems_libio_t *iop)
79{
80        struct cdev *cdev = devfs_imfs_get_context_by_iop(iop);
81        struct thread *td = rtems_bsd_get_curthread_or_null();
82        int flags = rtems_libio_to_fcntl_flags(iop->flags);
83        int error;
84
85        if (td != NULL) {
86                error = cdev->si_devsw->d_close(cdev, flags, 0, td);
87        } else {
88                error = ENOMEM;
89        }
90
91        return rtems_bsd_error_to_status_and_errno(error);
92}
93
94static ssize_t
95devfs_imfs_readv(rtems_libio_t *iop, const struct iovec *iov, int iovcnt,
96    ssize_t total)
97{
98        struct cdev *cdev = devfs_imfs_get_context_by_iop(iop);
99        struct thread *td = rtems_bsd_get_curthread_or_null();
100        struct uio uio = {
101                .uio_iov = __DECONST(struct iovec *, iov),
102                .uio_iovcnt = iovcnt,
103                .uio_offset = 0,
104                .uio_resid = total,
105                .uio_segflg = UIO_USERSPACE,
106                .uio_rw = UIO_READ,
107                .uio_td = td
108        };
109        int error;
110
111        if (td != NULL) {
112                error = cdev->si_devsw->d_read(cdev, &uio,
113                    rtems_libio_to_fcntl_flags(iop->flags));
114        } else {
115                error = ENOMEM;
116        }
117
118        if (error == 0) {
119                return (total - uio.uio_resid);
120        } else {
121                rtems_set_errno_and_return_minus_one(error);
122        }
123}
124
125static ssize_t
126devfs_imfs_read(rtems_libio_t *iop, void *buffer, size_t count)
127{
128        struct iovec iov = {
129                .iov_base = buffer,
130                .iov_len = count
131        };
132
133        return (devfs_imfs_readv(iop, &iov, 1, count));
134}
135
136static ssize_t
137devfs_imfs_writev(rtems_libio_t *iop, const struct iovec *iov, int iovcnt,
138    ssize_t total)
139{
140        struct cdev *cdev = devfs_imfs_get_context_by_iop(iop);
141        struct thread *td = rtems_bsd_get_curthread_or_null();
142        struct uio uio = {
143                .uio_iov = __DECONST(struct iovec *, iov),
144                .uio_iovcnt = iovcnt,
145                .uio_offset = 0,
146                .uio_resid = total,
147                .uio_segflg = UIO_USERSPACE,
148                .uio_rw = UIO_WRITE,
149                .uio_td = td
150        };
151        int error;
152
153        if (td != NULL) {
154                error = cdev->si_devsw->d_write(cdev, &uio,
155                    rtems_libio_to_fcntl_flags(iop->flags));
156        } else {
157                error = ENOMEM;
158        }
159
160        if (error == 0) {
161                return (total - uio.uio_resid);
162        } else {
163                rtems_set_errno_and_return_minus_one(error);
164        }
165}
166
167static ssize_t
168devfs_imfs_write(rtems_libio_t *iop, const void *buffer, size_t count)
169{
170        struct iovec iov = {
171                .iov_base = __DECONST(void *, buffer),
172                .iov_len = count
173        };
174
175        return (devfs_imfs_writev(iop, &iov, 1, count));
176}
177
178static int
179devfs_imfs_ioctl(rtems_libio_t *iop, ioctl_command_t request, void *buffer)
180{
181        struct cdev *cdev = devfs_imfs_get_context_by_iop(iop);
182        struct thread *td = rtems_bsd_get_curthread_or_null();
183        int error;
184        int flags = rtems_libio_to_fcntl_flags(iop->flags);
185
186        if (td != 0) {
187                error = cdev->si_devsw->d_ioctl(cdev, request, buffer, flags,
188                    td);
189        } else {
190                error = ENOMEM;
191        }
192
193        return (rtems_bsd_error_to_status_and_errno(error));
194}
195
196static int
197devfs_imfs_poll(rtems_libio_t *iop, int events)
198{
199        struct cdev *cdev = devfs_imfs_get_context_by_iop(iop);
200
201        return (cdev->si_devsw->d_poll(cdev, events,
202            rtems_bsd_get_curthread_or_wait_forever()));
203}
204
205static int
206devfs_imfs_kqfilter(rtems_libio_t *iop, struct knote *kn)
207{
208        struct cdev *cdev = devfs_imfs_get_context_by_iop(iop);
209
210        return (cdev->si_devsw->d_kqfilter(cdev, kn));
211}
212
213static const rtems_filesystem_file_handlers_r devfs_imfs_handlers = {
214        .open_h = devfs_imfs_open,
215        .close_h = devfs_imfs_close,
216        .read_h = devfs_imfs_read,
217        .write_h = devfs_imfs_write,
218        .ioctl_h = devfs_imfs_ioctl,
219        .lseek_h = rtems_filesystem_default_lseek_file,
220        .fstat_h = rtems_filesystem_default_fstat,
221        .ftruncate_h = rtems_filesystem_default_ftruncate,
222        .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
223        .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
224        .fcntl_h = rtems_filesystem_default_fcntl,
225        .poll_h = devfs_imfs_poll,
226        .kqfilter_h = devfs_imfs_kqfilter,
227        .readv_h = devfs_imfs_readv,
228        .writev_h = devfs_imfs_writev,
229};
230
231static const IMFS_node_control devfs_imfs_control = IMFS_GENERIC_INITIALIZER(
232    &devfs_imfs_handlers, IMFS_node_initialize_generic,
233    IMFS_node_destroy_default);
234
235struct cdev *
236devfs_alloc(int flags)
237{
238        struct cdev *cdev;
239
240        cdev = malloc(sizeof *cdev, M_TEMP, M_ZERO);
241        if (cdev == NULL)
242                return (NULL);
243
244        memcpy(cdev->si_path, rtems_cdev_directory, sizeof(cdev->si_path));
245        return (cdev);
246}
247
248void
249devfs_free(struct cdev *cdev)
250{
251        free(cdev, M_TEMP);
252}
253
254/*
255 * Create the directory for a device.
256 * Note: This don't uses dirname() because this function is not defined thread
257 * save in POSIX.
258 */
259static void
260devfs_create_directory(const char *devname)
261{
262        char *dir = NULL;
263        char *lastsep = NULL;
264        int rv;
265        mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO;
266
267        dir = strdup(devname, M_TEMP);
268        BSD_ASSERT(dir != NULL);
269
270        lastsep = strrchr(dir, '/');
271        if(lastsep != NULL) {
272                *lastsep = 0;
273                rv = rtems_mkdir(dir, mode);
274                BSD_ASSERT(rv == 0);
275        }
276
277        free(dir, M_TEMP);
278}
279
280/*
281 * devfs_create() and devfs_destroy() are called from kern_conf.c and
282 * in both cases the devlock() mutex is held, so no further locking
283 * is necesary and no sleeping allowed.
284 */
285
286void
287devfs_create(struct cdev *dev)
288{
289        int rv;
290        mode_t mode = S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO;
291
292        devfs_create_directory(dev->si_path);
293
294        rv = IMFS_make_generic_node(dev->si_path, mode, &devfs_imfs_control,
295            dev);
296        BSD_ASSERT(rv == 0);
297}
298
299void
300devfs_destroy(struct cdev *dev)
301{
302        int rv;
303
304        rv = unlink(dev->si_path);
305        BSD_ASSERT(rv == 0);
306
307        /* FIXME: Check if directory is empty and remove it. */
308}
309
310int
311devfs_dev_exists(const char *name)
312{
313        const size_t dirlen = sizeof(rtems_cdev_directory) - 1;
314        const size_t maxnamelen = SPECNAMELEN;
315
316        int rv;
317        char fullpath[dirlen + maxnamelen + 1];
318
319        memcpy(fullpath, rtems_cdev_directory, dirlen);
320        strncpy(fullpath + dirlen, name, maxnamelen);
321
322        rv = access(fullpath, F_OK);
323
324        if(rv == 0)
325                return 1;
326        else
327                return 0;
328}
329
330ino_t
331devfs_alloc_cdp_inode(void)
332{
333
334        return (alloc_unr(devfs_inos));
335}
336
337void
338devfs_free_cdp_inode(ino_t ino)
339{
340
341        if (ino > 0)
342                free_unr(devfs_inos, ino);
343}
344
345static void
346        devfs_devs_init(void *junk __unused)
347{
348
349        devfs_inos = new_unrhdr(DEVFS_ROOTINO + 1, INT_MAX, &devmtx);
350}
351
352SYSINIT(devfs_devs, SI_SUB_DEVFS, SI_ORDER_FIRST, devfs_devs_init, NULL);
Note: See TracBrowser for help on using the repository browser.