``fd'' device driver
Chris Torek
chris at umcp-cs.UUCP
Sat Dec 22 09:18:27 AEST 1984
: Run this shell script with "sh" not "csh"
PATH=:/bin:/usr/bin:/usr/ucb
export PATH
all=FALSE
if [ $1x = -ax ]; then
all=TRUE
fi
/bin/echo 'Extracting Info'
cat <<'Foo' >Info
As promised, here is the fd driver for 4.2BSD. Beware: I just ripped
out the 4.1 manual, so it's wrong. The code now doesn't just dup() the
file, if it's an inode; it makes a whole new file pointer. (For sockets
and any other descriptor types you may happen to have lying around, it
still dup()s.)
This isn't Fred's original code either; I reformatted it and removed
a few "u.u_" assignments. Any bugs can probably be attributed to me.
To install, put dev_fd.c in sys/sys, update conf/files, configure, make
depend, and make. (I think.) dev_fd.c is a lot like tty_pty.c.
By the way, we've found /dev/fd0 especially useful with soelim.
Foo
/bin/echo 'Extracting dev_fd.c'
sed 's/^X//' <<'//go.sysin dd *' >dev_fd.c
#ifndef lint
static char rcsid[] = "@(#)$Header: /usr/sys/sys/RCS/dev_fd.c,v 1.1 84/12/01 21:38:17 chris Exp $";
#endif lint
X/*
* fd.c Fred Blonder - U of Maryland 11-Sep-1984
*
* ``File Descriptor'' pseudo-device driver, rewritten for Berkeley 4.2.
*
* Opening minor device N opens the file (if any) connected to file-descriptor
* N belonging to the calling process. Note that this driver consists of only
* the ``open()'' routine, because all subsequent references to this file will
* be direct to the other driver.
*/
#include "fd.h"
#if NFD > 0
#include "../h/param.h"
#include "../h/inode.h"
#include "../h/file.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/errno.h"
X/*
* THIS CODE NEEDS CLEANING AS SOON AS ASSIGNMENTS TO u.u_* GO AWAY
*/
fdopen(dev, mode)
dev_t dev;
int mode;
{
struct file *fp, *wfp;
struct inode *ip, *wip;
int rwmode, error;
/*
* Note the horrid kludge here: u.u_r.r_val1 contains the value
* of the new file descriptor, which has not been disturbed since
* it was allocated.
*/
if ((fp = getf(u.u_r.r_val1)) == NULL)
return (u.u_error);
if ((wfp = getf(minor(dev))) == NULL)
return (u.u_error);
/*
* We must explicitly test for this case because ufalloc() may
* have allocated us the same file desriptor we are referring
* to, if the proccess referred to an invalid (closed) descriptor.
* Ordinarily this would be caught by getf(), but by the time we
* reach this routine u_pofile[minor(dev)] could already be set
* to point to our file struct.
*/
if (fp == wfp)
return (EBADF);
ip = (struct inode *)fp->f_data;
/*
* Fake a ``dup()'' sys call if it isn't an inode.
*/
if (wfp->f_type != DTYPE_INODE) {
/*
* Check that the mode the file is being opened
* for is consistent with the mode of the existing
* descriptor. This isn't as clean as it should be,
* but this entire driver is a real kludge anyway.
*/
rwmode = mode & (FREAD|FWRITE);
if ((fp->f_flag & rwmode) != rwmode)
return (EACCES);
/* Delete references to this pseudo-device. */
irele(ip); /* Chuck the inode. */
fp->f_count = 0; /* Chuck the file structure. */
/* Dup the file descriptor. */
dupit(u.u_r.r_val1, wfp, u.u_pofile[minor(dev)]);
return (0);
}
error = 0;
wip = (struct inode *)wfp->f_data;
/*
* I'm not sure that we really need to lock the inode here,
* but why not be paranoid?
*/
ilock(wip);
/*
* Since we're opening a file again, we run through all the
* permission checks so this can't be used as a loophole to
* get access to a file we shouldn't have. (GROT)
*/
if (mode & FREAD && access(wip, IREAD))
goto bad;
if (mode & (FWRITE|FTRUNC)) {
if ((ip->i_mode&IFMT) == IFDIR) {
error = EISDIR;
goto bad;
}
if (access(wip, IWRITE))
goto bad;
}
/*
* The file must always exist, so we don't even bother testing
* for its presence.
*/
if ((mode & (FCREAT|FEXCL)) == (FCREAT|FEXCL)) {
error = EEXIST;
goto bad;
}
/*
* This may not make any sense, but I'm paranoid and figure that
* it's probably an error.
*/
if (mode & FTRUNC) {
error = EBUSY;
goto bad;
}
/* Call the device-specific open routine, if any. */
if ((error = openi(wip, mode)) != 0)
goto bad;
/*
* Made it this far, now switch the inode pointers in the
* file descriptors around, to make this file open refer
* to the other file.
*/
irele(ip); /* We don't need this anymore. */
fp->f_data = (caddr_t)wip;
wip->i_count++;
iunlock(wip);
return (0);
bad:
iunlock(wip);
return (error);
}
#endif NFD > 0
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
/bin/chmod 644 dev_fd.c
/bin/echo -n ' '; /bin/ls -ld dev_fd.c
fi
/bin/echo 'Extracting fd.4'
sed 's/^X//' <<'//go.sysin dd *' >fd.4
X.TH FD 4l "11-Jan-83 (U of Maryland)"
X.UC 4
X.SH NAME
fd \- ``file descriptor'' driver
X.SH DESCRIPTION
X.lg
X.I Fd0
-
X.I fd19
are special files that are symbolic names for a process's file descriptors.
That is, opening the file: /dev/fd\fIN\fP is equivalent to doing the system
call: dup(\fIN\fP).
This can be used to force a program which opens files by name, to connect
itself to open file descriptors (which you have thoughtfully provided) in
weird and wonderful ways. A simple use would be to force a program which
only accepts input from files, to read from its standard input.
For instance:
X.sp
X.ti +10
cat /dev/fd0
X.sp
produces the same result as:
X.sp
X.ti +10
cat -
X.sp
which would be useful if \fIcat\fP didn't use the ``-'' convention.
X.sp
The driver checks to see that the read/write mode you are attempting to open
the file with, is compatible with the mode of the existing file descriptor.
That is: if descriptor 5 is open for writing, you cannot open ``/dev/fd5''
for reading.
X.SH AUTHOR
Fred Blonder <fred at umcp-cs>
X.SH FILES
X/dev/fd*
X.SH BUGS
Since the driver fakes a ``dup'' system call rather than actually re-opening
the file, the new descriptor is a copy of the dup-ed descriptor, and shares
its properties. Specifically: it will have the same read/write mode as the
dup-ed descriptor. If descriptor 0 is open for reading and writing, opening
``/dev/fd0'' for reading will return a writeable, as well as readable, file
descriptor.
Also: the descriptors share the same read/write pointer, so seeks, reads &
writes on one will affect the other.
X.sp
While not a bug in the driver, use of these files can produce odd
interactions with programs which don't expect to have their file
descriptors surreptitiously aliased.
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
/bin/chmod 644 fd.4
/bin/echo -n ' '; /bin/ls -ld fd.4
fi
--
(This line accidently left nonblank.)
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (301) 454-7690
UUCP: {seismo,allegra,brl-bmd}!umcp-cs!chris
CSNet: chris at umcp-cs ARPA: chris at maryland
More information about the Comp.unix.wizards
mailing list