*
* %sccs.include.redist.c%
*
- * @(#)kern_descrip.c 7.29 (Berkeley) %G%
+ * @(#)kern_descrip.c 7.37 (Berkeley) %G%
*/
#include "param.h"
/*
* System calls on descriptors.
*/
+struct getdtablesize_args {
+ int dummy;
+};
/* ARGSUSED */
getdtablesize(p, uap, retval)
struct proc *p;
- struct args *uap;
+ struct getdtablesize_args *uap;
int *retval;
{
/*
* Duplicate a file descriptor.
*/
+struct dup_args {
+ int i;
+};
/* ARGSUSED */
dup(p, uap, retval)
struct proc *p;
- struct args {
- int i;
- } *uap;
+ struct dup_args *uap;
int *retval;
{
register struct filedesc *fdp = p->p_fd;
/*
* Duplicate a file descriptor to a particular value.
*/
+struct dup2_args {
+ u_int from;
+ u_int to;
+};
/* ARGSUSED */
dup2(p, uap, retval)
struct proc *p;
- struct args {
- u_int from;
- u_int to;
- } *uap;
+ struct dup2_args *uap;
int *retval;
{
register struct filedesc *fdp = p->p_fd;
/*
* The file control system call.
*/
+struct fcntl_args {
+ int fd;
+ int cmd;
+ int arg;
+};
/* ARGSUSED */
fcntl(p, uap, retval)
struct proc *p;
- register struct args {
- int fd;
- int cmd;
- int arg;
- } *uap;
+ register struct fcntl_args *uap;
int *retval;
{
register struct filedesc *fdp = p->p_fd;
/*
* Close a file descriptor.
*/
+struct close_args {
+ int fd;
+};
/* ARGSUSED */
close(p, uap, retval)
struct proc *p;
- struct args {
- int fd;
- } *uap;
+ struct close_args *uap;
int *retval;
{
register struct filedesc *fdp = p->p_fd;
return (closef(fp, p));
}
+#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
/*
* Return status information about a file descriptor.
*/
+struct ofstat_args {
+ int fd;
+ struct ostat *sb;
+};
+/* ARGSUSED */
+ofstat(p, uap, retval)
+ struct proc *p;
+ register struct ofstat_args *uap;
+ int *retval;
+{
+ register struct filedesc *fdp = p->p_fd;
+ register struct file *fp;
+ struct stat ub;
+ struct ostat oub;
+ int error;
+
+ if ((unsigned)uap->fd >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[uap->fd]) == NULL)
+ return (EBADF);
+ switch (fp->f_type) {
+
+ case DTYPE_VNODE:
+ error = vn_stat((struct vnode *)fp->f_data, &ub, p);
+ break;
+
+ case DTYPE_SOCKET:
+ error = soo_stat((struct socket *)fp->f_data, &ub);
+ break;
+
+ default:
+ panic("ofstat");
+ /*NOTREACHED*/
+ }
+ cvtstat(&ub, &oub);
+ if (error == 0)
+ error = copyout((caddr_t)&oub, (caddr_t)uap->sb, sizeof (oub));
+ return (error);
+}
+#endif /* COMPAT_43 || COMPAT_SUNOS */
+
+/*
+ * Return status information about a file descriptor.
+ */
+struct fstat_args {
+ int fd;
+ struct stat *sb;
+};
/* ARGSUSED */
fstat(p, uap, retval)
struct proc *p;
- register struct args {
- int fd;
- struct stat *sb;
- } *uap;
+ register struct fstat_args *uap;
int *retval;
{
register struct filedesc *fdp = p->p_fd;
* Just attempt to get a record lock of the requested type on
* the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
*/
-
+struct flock_args {
+ int fd;
+ int how;
+};
/* ARGSUSED */
flock(p, uap, retval)
struct proc *p;
- register struct args {
- int fd;
- int how;
- } *uap;
+ register struct flock_args *uap;
int *retval;
{
register struct filedesc *fdp = p->p_fd;
* references to this file will be direct to the other driver.
*/
/* ARGSUSED */
-fdopen(dev, mode, type)
+fdopen(dev, mode, type, p)
dev_t dev;
int mode, type;
+ struct proc *p;
{
/*
* actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
* will simply report the error.
*/
- curproc->p_dupfd = minor(dev); /* XXX */
+ p->p_dupfd = minor(dev);
return (ENODEV);
}
/*
* Duplicate the specified descriptor to a free descriptor.
*/
-dupfdopen(fdp, indx, dfd, mode)
+dupfdopen(fdp, indx, dfd, mode, error)
register struct filedesc *fdp;
register int indx, dfd;
int mode;
+ int error;
{
register struct file *wfp;
struct file *fp;
return (EBADF);
/*
- * Check that the mode the file is being opened for is a subset
- * of the mode of the existing descriptor.
+ * There are two cases of interest here.
+ *
+ * For ENODEV simply dup (dfd) to file descriptor
+ * (indx) and return.
+ *
+ * For ENXIO steal away the file structure from (dfd) and
+ * store it in (indx). (dfd) is effectively closed by
+ * this operation.
+ *
+ * Any other error code is just returned.
*/
- if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
- return (EACCES);
- fdp->fd_ofiles[indx] = wfp;
- fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
- wfp->f_count++;
- if (indx > fdp->fd_lastfile)
- fdp->fd_lastfile = indx;
- return (0);
+ switch (error) {
+ case ENODEV:
+ /*
+ * Check that the mode the file is being opened for is a
+ * subset of the mode of the existing descriptor.
+ */
+ if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
+ return (EACCES);
+ fdp->fd_ofiles[indx] = wfp;
+ fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
+ wfp->f_count++;
+ if (indx > fdp->fd_lastfile)
+ fdp->fd_lastfile = indx;
+ return (0);
+
+ case ENXIO:
+ /*
+ * Steal away the file pointer from dfd, and stuff it into indx.
+ */
+ fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd];
+ fdp->fd_ofiles[dfd] = NULL;
+ fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
+ fdp->fd_ofileflags[dfd] = 0;
+ /*
+ * Complete the clean up of the filedesc structure by
+ * recomputing the various hints.
+ */
+ if (indx > fdp->fd_lastfile)
+ fdp->fd_lastfile = indx;
+ else
+ while (fdp->fd_lastfile > 0 &&
+ fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
+ fdp->fd_lastfile--;
+ if (dfd < fdp->fd_freefile)
+ fdp->fd_freefile = dfd;
+ return (0);
+
+ default:
+ return (error);
+ }
+ /* NOTREACHED */
}