[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
MiNT 1.09 extension: /dev/fd/*
This patch implements the /dev/fd directory, denoting the open file
descriptors of the current process. This is a generalisation of
/dev/std{in,out,err}.
I have implemented this for Bash-1.13, which uses it for process
substitution; unfortunately this doesn't work because of the blocking
fork() :-(. Anyway, i think this is a nice thing.
--- orig/biosfs.c Tue Aug 17 21:23:18 1993
+++ biosfs.c Sat Nov 20 19:50:40 1993
@@ -136,6 +136,7 @@
{"stdin", &fakedev, 0, 0, 0, 0}, /* handle 0 (stdin) */
{"stdout", &fakedev, 1, 0, 0, 0}, /* handle 1 (stdout) */
{"stderr", &fakedev, 2, 0, 0, 0}, /* handle 2 (stderr) */
+ {"fd", &fakedev, S_IFDIR, 0, 0, 0}, /* file descriptor directory */
/* other miscellaneous devices */
{"mouse", &mouse_device, 0, 0, 0, 0},
@@ -157,6 +158,11 @@
{"", 0, 0, 0, 0, 0}
};
+/* Does the fcookie fc refer to the \dev\fd directory? */
+#define IS_FD_DIR(fc) ((fc)->aux == S_IFDIR)
+/* Does the fcookie fc refer to a file in the \dev\fd directory? */
+#define IS_FD_ENTRY(fc) ((fc)->index > 0 && (fc)->index <= MAX_OPEN-MIN_HANDLE)
+
struct bios_file *broot, *bdevlast;
/* a file pointer for BIOS device 1, provided only for insurance
@@ -234,9 +240,41 @@
struct bios_file *b;
if (dir->index != 0) {
+ /* Check for \dev\fd directory */
+ if (!IS_FD_DIR (dir))
+ {
DEBUG(("bios_lookup: bad directory"));
return EPTHNF;
+ }
+ if (!*name || (name[0] == '.' && name[1] == 0))
+ {
+ *fc = *dir;
+ return 0;
+ }
+ if (!strcmp (name, ".."))
+ {
+ /* Root directory */
+ fc->fs = &bios_filesys;
+ fc->dev = dir->dev;
+ fc->index = 0L;
+ return 0;
+ }
+ if (isdigit (*name) || *name == '-')
+ {
+ int fd = (int) atol (name);
+ if (fd >= MIN_HANDLE && fd < MAX_OPEN)
+ {
+ fc->fs = &bios_filesys;
+ fc->dev = dir->dev;
+ fc->aux = fd;
+ fc->index = fd - MIN_HANDLE + 1;
+ return 0;
+ }
+ }
+ DEBUG (("bios_lookup: name(%s) not found", name));
+ return EFILNF;
}
+
/* special case: an empty name in a directory means that directory */
/* so does "." */
if (!*name || (name[0] == '.' && name[1] == 0)) {
@@ -270,6 +308,7 @@
{
FILEPTR *f;
struct bios_file *b = (struct bios_file *)fc->index;
+ long r;
xattr->index = fc->index;
xattr->dev = fc->dev;
@@ -279,18 +318,42 @@
xattr->blksize = 1;
xattr->mtime = xattr->atime = xattr->ctime = timestamp;
xattr->mdate = xattr->adate = xattr->cdate = datestamp;
- if (fc->index == 0) { /* root directory? */
+ if (fc->index == 0 || IS_FD_DIR (fc)) { /* root or fd directory? */
xattr->mode = S_IFDIR | DEFAULT_DIRMODE;
xattr->attr = FA_DIR;
+ }
+ else if (IS_FD_ENTRY (fc)) {
+ /* u:\dev\fd\... */
+ f = curproc->handle[(int) fc->aux];
+ if (f)
+ {
+ r = (*f->fc.fs->getxattr) (&f->fc, xattr);
+ if (r < 0)
+ return r;
+#if 0
+ /* Not sure if needed. Try without it for now */
+ xattr->index = fc->index;
+ xattr->dev = fc->dev;
+#endif
+ }
+ else
+ {
+ xattr->mode = S_IFCHR | DEFAULT_MODE;
+ xattr->attr = 0;
+ }
} else if (b->device == 0) { /* symbolic link? */
xattr->mode = S_IFLNK | DEFAULT_DIRMODE;
} else if (b->device == &fakedev &&
(f = curproc->handle[b->private]) != 0)
{
/* u:\dev\stdin, u:\dev\stdout, etc. */
- (*f->fc.fs->getxattr) (&f->fc, xattr);
+ r = (*f->fc.fs->getxattr) (&f->fc, xattr);
+ if (r < 0)
+ return r;
+#if 0
xattr->index = fc->index;
xattr->dev = fc->dev;
+#endif
} else {
xattr->mode = S_IFCHR | DEFAULT_MODE;
xattr->attr = 0;
@@ -357,7 +420,10 @@
{
struct bios_file *b, **lastb;
- UNUSED(dir);
+ /* Don't allow removal in the fd directory */
+ if (IS_FD_DIR (dir))
+ return EACCDN;
+
lastb = &broot;
for (b = broot; b; b = *(lastb = &b->next)) {
if (!stricmp(b->name, name)) break;
@@ -382,12 +448,22 @@
fcookie *root, *dir; char *pathname;
int size;
{
- char *foo = ((struct bios_file *)dir->index)->name;
+ char *foo;
- UNUSED(root);
- if (dir->index == 0 && size > 0)
- *pathname = 0;
- else if (strlen(foo) < size)
+ if (size == 0)
+ return ERANGE;
+ if (root->index == dir->index)
+ {
+ *pathname = 0;
+ return 0;
+ }
+ /* DIR must point to the fd directory */
+ if (!IS_FD_DIR (dir))
+ return EINTRN;
+ *pathname++ = '\\';
+ size--;
+ foo = ((struct bios_file *)dir->index)->name;
+ if (strlen(foo) < size)
strcpy(pathname, foo);
else
return ERANGE;
@@ -401,18 +477,22 @@
fcookie *newdir;
const char *newname;
{
- struct bios_file *b;
-
- UNUSED(olddir); UNUSED(newdir);
+ struct bios_file *b, *be = 0;
-/* BUG: we should check to see if "newname" already exists */
+ if (IS_FD_DIR (olddir) || IS_FD_DIR (newdir))
+ return EACCDN;
for (b = broot; b; b = b->next) {
- if (!stricmp(b->name, oldname)) {
- strncpy(b->name, newname, BNAME_MAX);
- return 0;
- }
- }
+ if (!stricmp(b->name, oldname))
+ be = b;
+ else if (!stricmp (b->name, newname))
+ return EACCDN;
+ }
+ if (be)
+ {
+ strncpy(be->name, newname, BNAME_MAX);
+ return 0;
+ }
return EFILNF;
}
@@ -423,7 +503,7 @@
{
UNUSED(flags);
- if (dirh->fc.index != 0) {
+ if (dirh->fc.index != 0 && !IS_FD_DIR (&dirh->fc)) {
DEBUG(("bios_opendir: bad directory"));
return EPTHNF;
}
@@ -440,6 +520,31 @@
struct bios_file *b;
int giveindex = dirh->flags == 0;
int i;
+ char buf[5];
+
+ if (IS_FD_DIR (&dirh->fc))
+ {
+ i = dirh->index++;
+ if (i + MIN_HANDLE >= MAX_OPEN)
+ return ENMFIL;
+ fc->fs = &bios_filesys;
+ fc->index = i + 1;
+ fc->aux = i + MIN_HANDLE;
+ fc->dev = dirh->fc.dev;
+ if (giveindex)
+ {
+ namelen -= (int) sizeof (long);
+ if (namelen <= 0)
+ return ERANGE;
+ *(long *) name = (long) i + 1;
+ name += sizeof (long);
+ }
+ ksprintf (buf, "%d", i + MIN_HANDLE);
+ strncpy (name, buf, namelen-1);
+ if (strlen (buf) >= namelen)
+ return ENAMETOOLONG;
+ return 0;
+ }
b = broot;
i = dirh->index++;
@@ -551,7 +656,9 @@
{
struct bios_file *b;
- UNUSED(dir);
+ if (IS_FD_DIR (dir))
+ return EINVFN;
+
if ((unsigned)cmd == DEV_INSTALL) {
struct dev_descr *d = (struct dev_descr *)arg;
@@ -609,6 +716,9 @@
long r;
fcookie fc;
+ if (IS_FD_DIR (dir))
+ return EACCDN;
+
r = bios_lookup(dir, name, &fc);
if (r == 0) return EACCDN; /* file already exists */
if (r != EFILNF) return r; /* some other error */
@@ -640,6 +750,8 @@
{
struct bios_file *b = (struct bios_file *)fc->index;
+ if (IS_FD_DIR (fc) || IS_FD_ENTRY (fc))
+ return EINVFN;
if (!b) return EINVFN;
if (b->device) return EINVFN;
@@ -758,6 +870,13 @@
{
struct bios_file *b;
+ /* Check for \dev\fd\... */
+ if (IS_FD_ENTRY (fc))
+ {
+ *devsp = (int) fc->aux;
+ return &fakedev;
+ }
+
b = (struct bios_file *)fc->index;
if (b->device && b->device != &fakedev)