summaryrefslogtreecommitdiffstats
path: root/rtemsbsd/sys/fs/devfs/devfs_devs.c
diff options
context:
space:
mode:
Diffstat (limited to 'rtemsbsd/sys/fs/devfs/devfs_devs.c')
-rw-r--r--rtemsbsd/sys/fs/devfs/devfs_devs.c177
1 files changed, 125 insertions, 52 deletions
diff --git a/rtemsbsd/sys/fs/devfs/devfs_devs.c b/rtemsbsd/sys/fs/devfs/devfs_devs.c
index 7c697b0a..39a38d62 100644
--- a/rtemsbsd/sys/fs/devfs/devfs_devs.c
+++ b/rtemsbsd/sys/fs/devfs/devfs_devs.c
@@ -35,6 +35,7 @@
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/file.h>
+#include <sys/filedesc.h>
#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/poll.h>
@@ -42,6 +43,8 @@
#include <string.h>
#include <unistd.h>
+#include <machine/rtems-bsd-libio.h>
+
#include <fs/devfs/devfs_int.h>
#include <machine/pcpu.h>
@@ -72,17 +75,25 @@ static int
devfs_imfs_open(rtems_libio_t *iop, const char *path, int oflag, mode_t mode)
{
struct cdev *cdev = devfs_imfs_get_context_by_iop(iop);
- struct file *fp = rtems_bsd_iop_to_fp(iop);
struct thread *td = rtems_bsd_get_curthread_or_null();
+ struct file *fp = NULL;
+ struct cdevsw *dsw = NULL;
struct file *fpop;
- struct cdevsw *dsw;
int error, ref;
+ int fd = -1;
if (td != NULL) {
if (cdev == NULL) {
error = ENXIO;
goto err;
}
+ error = falloc(td, &fp, &fd, oflag);
+ if (error != 0)
+ goto err;
+ finit(fp, FREAD | FWRITE, DTYPE_DEV, NULL, NULL);
+ rtems_libio_iop_hold(iop);
+ rtems_bsd_libio_iop_set_bsd_descriptor(iop, fd);
+ rtems_bsd_libio_iop_set_bsd_file(iop, fp);
if (cdev->si_flags & SI_ALIAS) {
cdev = cdev->si_parent;
}
@@ -91,11 +102,6 @@ devfs_imfs_open(rtems_libio_t *iop, const char *path, int oflag, mode_t mode)
error = ENXIO;
goto err;
}
- if (fp == NULL) {
- dev_relthread(cdev, ref);
- error = ENXIO;
- goto err;
- }
fpop = td->td_fpop;
curthread->td_fpop = fp;
fp->f_cdevpriv = NULL;
@@ -104,12 +110,19 @@ devfs_imfs_open(rtems_libio_t *iop, const char *path, int oflag, mode_t mode)
if (error != 0)
devfs_clear_cdevpriv();
curthread->td_fpop = fpop;
- dev_relthread(cdev, ref);
} else {
error = ENOMEM;
}
err:
+ if (dsw != NULL)
+ dev_relthread(cdev, ref);
+ if (td != NULL && fp != NULL) {
+ if (error != 0)
+ fdclose(td, fp, fd);
+ else
+ fdrop(fp, td);
+ }
return rtems_bsd_error_to_status_and_errno(error);
}
@@ -117,11 +130,11 @@ static int
devfs_imfs_close(rtems_libio_t *iop)
{
struct cdev *cdev = devfs_imfs_get_context_by_iop(iop);
- struct file *fp = rtems_bsd_iop_to_fp(iop);
struct thread *td = rtems_bsd_get_curthread_or_null();
int flags = rtems_libio_to_fcntl_flags(iop->flags);
+ struct file *fp = NULL;
+ struct cdevsw *dsw = NULL;
struct file *fpop;
- struct cdevsw *dsw;
int error, ref;
if (td != NULL) {
@@ -132,6 +145,11 @@ devfs_imfs_close(rtems_libio_t *iop)
if (cdev->si_flags & SI_ALIAS) {
cdev = cdev->si_parent;
}
+ fp = rtems_bsd_libio_iop_to_file_hold(iop, td);
+ if (fp == NULL) {
+ error = EBADF;
+ goto err;
+ }
dsw = dev_refthread(cdev, &ref);
if (dsw == NULL) {
error = ENXIO;
@@ -141,7 +159,6 @@ devfs_imfs_close(rtems_libio_t *iop)
curthread->td_fpop = fp;
error = dsw->d_close(cdev, flags, 0, td);
curthread->td_fpop = fpop;
- dev_relthread(cdev, ref);
if (fp->f_cdevpriv != NULL)
devfs_fpdrop(fp);
} else {
@@ -149,6 +166,10 @@ devfs_imfs_close(rtems_libio_t *iop)
}
err:
+ if (dsw != NULL)
+ dev_relthread(cdev, ref);
+ if (td != NULL && fp != NULL)
+ fdrop(fp, td);
return rtems_bsd_error_to_status_and_errno(error);
}
@@ -157,7 +178,6 @@ devfs_imfs_readv(rtems_libio_t *iop, const struct iovec *iov, int iovcnt,
ssize_t total)
{
struct cdev *cdev = devfs_imfs_get_context_by_iop(iop);
- struct file *fp = rtems_bsd_iop_to_fp(iop);
struct thread *td = rtems_bsd_get_curthread_or_null();
struct uio uio = {
.uio_iov = __DECONST(struct iovec *, iov),
@@ -168,8 +188,9 @@ devfs_imfs_readv(rtems_libio_t *iop, const struct iovec *iov, int iovcnt,
.uio_rw = UIO_READ,
.uio_td = td
};
+ struct file *fp = NULL;
+ struct cdevsw *dsw = NULL;
struct file *fpop;
- struct cdevsw *dsw;
int error, ref;
if (td != NULL) {
@@ -180,6 +201,11 @@ devfs_imfs_readv(rtems_libio_t *iop, const struct iovec *iov, int iovcnt,
if (cdev->si_flags & SI_ALIAS) {
cdev = cdev->si_parent;
}
+ fp = rtems_bsd_libio_iop_to_file_hold(iop, td);
+ if (fp == NULL) {
+ error = EBADF;
+ goto err;
+ }
dsw = dev_refthread(cdev, &ref);
if (dsw == NULL) {
error = ENXIO;
@@ -190,12 +216,15 @@ devfs_imfs_readv(rtems_libio_t *iop, const struct iovec *iov, int iovcnt,
error = dsw->d_read(cdev, &uio,
rtems_libio_to_fcntl_flags(iop->flags));
td->td_fpop = fpop;
- dev_relthread(cdev, ref);
} else {
error = ENOMEM;
}
err:
+ if (dsw != NULL)
+ dev_relthread(cdev, ref);
+ if (td != NULL && fp != NULL)
+ fdrop(fp, td);
if (error == 0) {
return (total - uio.uio_resid);
} else {
@@ -219,7 +248,6 @@ devfs_imfs_writev(rtems_libio_t *iop, const struct iovec *iov, int iovcnt,
ssize_t total)
{
struct cdev *cdev = devfs_imfs_get_context_by_iop(iop);
- struct file *fp = rtems_bsd_iop_to_fp(iop);
struct thread *td = rtems_bsd_get_curthread_or_null();
struct uio uio = {
.uio_iov = __DECONST(struct iovec *, iov),
@@ -230,8 +258,9 @@ devfs_imfs_writev(rtems_libio_t *iop, const struct iovec *iov, int iovcnt,
.uio_rw = UIO_WRITE,
.uio_td = td
};
+ struct file *fp = NULL;
+ struct cdevsw *dsw = NULL;
struct file *fpop;
- struct cdevsw *dsw;
int error, ref;
if (td != NULL) {
@@ -242,6 +271,11 @@ devfs_imfs_writev(rtems_libio_t *iop, const struct iovec *iov, int iovcnt,
if (cdev->si_flags & SI_ALIAS) {
cdev = cdev->si_parent;
}
+ fp = rtems_bsd_libio_iop_to_file_hold(iop, td);
+ if (fp == NULL) {
+ error = EBADF;
+ goto err;
+ }
dsw = dev_refthread(cdev, &ref);
if (dsw == NULL) {
error = ENXIO;
@@ -252,12 +286,15 @@ devfs_imfs_writev(rtems_libio_t *iop, const struct iovec *iov, int iovcnt,
error = dsw->d_write(cdev, &uio,
rtems_libio_to_fcntl_flags(iop->flags));
td->td_fpop = fpop;
- dev_relthread(cdev, ref);
} else {
error = ENOMEM;
}
err:
+ if (dsw != NULL)
+ dev_relthread(cdev, ref);
+ if (td != NULL && fp != NULL)
+ fdrop(fp, td);
if (error == 0) {
return (total - uio.uio_resid);
} else {
@@ -280,10 +317,10 @@ static int
devfs_imfs_ioctl(rtems_libio_t *iop, ioctl_command_t request, void *buffer)
{
struct cdev *cdev = devfs_imfs_get_context_by_iop(iop);
- struct file *fp = rtems_bsd_iop_to_fp(iop);
struct thread *td = rtems_bsd_get_curthread_or_null();
+ struct file *fp = NULL;
+ struct cdevsw *dsw = NULL;
struct file *fpop;
- struct cdevsw *dsw;
int error, ref;
int flags = rtems_libio_to_fcntl_flags(iop->flags);
@@ -295,6 +332,11 @@ devfs_imfs_ioctl(rtems_libio_t *iop, ioctl_command_t request, void *buffer)
if (cdev->si_flags & SI_ALIAS) {
cdev = cdev->si_parent;
}
+ fp = rtems_bsd_libio_iop_to_file_hold(iop, td);
+ if (fp == NULL) {
+ error = EBADF;
+ goto err;
+ }
dsw = dev_refthread(cdev, &ref);
if (dsw == NULL) {
error = ENXIO;
@@ -305,12 +347,15 @@ devfs_imfs_ioctl(rtems_libio_t *iop, ioctl_command_t request, void *buffer)
error = dsw->d_ioctl(cdev, request, buffer, flags,
td);
td->td_fpop = fpop;
- dev_relthread(cdev, ref);
} else {
error = ENOMEM;
}
err:
+ if (dsw != NULL)
+ dev_relthread(cdev, ref);
+ if (td != NULL && fp != NULL)
+ fdrop(fp, td);
return rtems_bsd_error_to_status_and_errno(error);
}
@@ -333,28 +378,43 @@ static int
devfs_imfs_poll(rtems_libio_t *iop, int events)
{
struct cdev *cdev = devfs_imfs_get_context_by_iop(iop);
- struct file *fp = rtems_bsd_iop_to_fp(iop);
struct thread *td = rtems_bsd_get_curthread_or_wait_forever();
+ struct file *fp = NULL;
+ struct cdevsw *dsw = NULL;
struct file *fpop;
- struct cdevsw *dsw;
int error, ref;
- if (cdev == NULL) {
- return POLLERR;
- }
- if (cdev->si_flags & SI_ALIAS) {
- cdev = cdev->si_parent;
- }
- dsw = dev_refthread(cdev, &ref);
- if (dsw == NULL) {
- return POLLERR;
+ if (td != 0) {
+ if (cdev == NULL) {
+ error = POLLERR;
+ goto err;
+ }
+ if (cdev->si_flags & SI_ALIAS) {
+ cdev = cdev->si_parent;
+ }
+ fp = rtems_bsd_libio_iop_to_file_hold(iop, td);
+ if (fp == NULL) {
+ error = EBADF;
+ goto err;
+ }
+ dsw = dev_refthread(cdev, &ref);
+ if (dsw == NULL) {
+ error = POLLERR;
+ goto err;
+ }
+ fpop = td->td_fpop;
+ curthread->td_fpop = fp;
+ error = dsw->d_poll(cdev, events, td);
+ td->td_fpop = fpop;
+ } else {
+ error = ENOMEM;
}
- fpop = td->td_fpop;
- curthread->td_fpop = fp;
- error = dsw->d_poll(cdev, events, td);
- td->td_fpop = fpop;
- dev_relthread(cdev, ref);
+err:
+ if (dsw != NULL)
+ dev_relthread(cdev, ref);
+ if (td != NULL && fp != NULL)
+ fdrop(fp, td);
return error;
}
@@ -362,28 +422,41 @@ static int
devfs_imfs_kqfilter(rtems_libio_t *iop, struct knote *kn)
{
struct cdev *cdev = devfs_imfs_get_context_by_iop(iop);
- struct file *fp = rtems_bsd_iop_to_fp(iop);
struct thread *td = rtems_bsd_get_curthread_or_wait_forever();
+ struct file *fp = NULL;
+ struct cdevsw *dsw = NULL;
struct file *fpop;
- struct cdevsw *dsw;
int error, ref;
- if (cdev == NULL) {
- return EINVAL;
- }
- if (cdev->si_flags & SI_ALIAS) {
- cdev = cdev->si_parent;
- }
- dsw = dev_refthread(cdev, &ref);
- if (dsw == NULL) {
- return EINVAL;
+ if (td != 0) {
+ if (cdev == NULL) {
+ error = EINVAL;
+ }
+ fp = rtems_bsd_libio_iop_to_file_hold(iop, td);
+ if (fp == NULL) {
+ error = EBADF;
+ goto err;
+ }
+ if (cdev->si_flags & SI_ALIAS) {
+ cdev = cdev->si_parent;
+ }
+ dsw = dev_refthread(cdev, &ref);
+ if (dsw == NULL) {
+ error = EINVAL;
+ }
+ fpop = td->td_fpop;
+ curthread->td_fpop = fp;
+ error = dsw->d_kqfilter(cdev, kn);
+ td->td_fpop = fpop;
+ } else {
+ error = ENOMEM;
}
- fpop = td->td_fpop;
- curthread->td_fpop = fp;
- error = dsw->d_kqfilter(cdev, kn);
- td->td_fpop = fpop;
- dev_relthread(cdev, ref);
+err:
+ if (dsw != NULL)
+ dev_relthread(cdev, ref);
+ if (td != NULL && fp != NULL)
+ fdrop(fp, td);
return error;
}