[comp.unix.wizards] how can I get filename from file descriptor?

Pabbisetty.henr@xerox.com (Nagesh Pabbisetty) (08/16/89)

Hello Wizards,

If I have a descriptor to a file, how can I find out the name of the file
associated with it?

Thanks...

Nagesh
716-427-5458 / 5257

cpcahil@virtech.UUCP (Conor P. Cahill) (08/16/89)

In article <20613@adm.BRL.MIL>, Pabbisetty.henr@xerox.com (Nagesh Pabbisetty) writes:
> If I have a descriptor to a file, how can I find out the name of the file
> associated with it?

I'm not sure if this is the most efficient way, but it will work for any 
standard file descriptors. 

1. get the device and inode number using fstat(2).
2. Find the block special file that contains the file system that 
   contains the file (the device number will match).
3. Look up the device in /etc/mnttab (to find the mount point).
4. cd to the mount point
5. Search the indicated file system for a file with the same inode.

bill@twwells.com (T. William Wells) (08/18/89)

In article <20613@adm.BRL.MIL> Pabbisetty.henr@xerox.com (Nagesh Pabbisetty) writes:
: If I have a descriptor to a file, how can I find out the name of the file
: associated with it?

For most practical purposes, you don't.

1) A file descriptor may not have a path associated with it. Consider
   a file that is opened and then unlinked.

2) A file descriptor may have more than one path to it. Consider
   multiply linked files.

Assuming that neither of the above is true, the best you can do is to
get the device and inode number of the file and then search the
device's entire directory tree for the inode.

Ugh.

---
Bill                    { uunet | novavax | ankh | sunvice } !twwells!bill
bill@twwells.com

paulr@sequent.UUCP (Paul Reger) (08/22/89)

The solutions to this problems are very dissatisfying.  I think the
object oriented approach should be adopted here to file operations.
What I mean is this:

modify fopen() and the FILE structure in the following ways:

Have the FILE structure have a name field in it:

    char *name;

then when the fopen() call is made, have it fill in the field, by
malloc() and strcpy() and determine the actual name based on the
current working directory and the name passed as a parameter to
fopen().  Thereafter the *name field can be referenced directly from
the FILE, or preferably a new function:  TheName() can be made which
takes a FILE argument and returns the char *.

chris@mimsy.UUCP (Chris Torek) (08/22/89)

In article <20482@sequent.UUCP> paulr@sequent.UUCP (Paul Reger) writes:
>What I mean is this ...
>Have the FILE structure have a name field in it:
>    char *name;
>then when the fopen() call is made, have it fill in the field ....

This is all well and good, but you will have to define what happens
when you ask for the name of stdin, stdout, stderr, or a file opened
with fdopen.  (Also, but rather incidentally, I am not terribly thrilled 
with the idea of fopen having to call getwd.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

dce@Solbourne.COM (David Elliott) (08/22/89)

In article <20482@sequent.UUCP> paulr@crg3.UUCP (Paul Reger) writes:
>
>The solutions to this problems are very dissatisfying.  I think the
>object oriented approach should be adopted here to file operations.
>What I mean is this:
>
>modify fopen() and the FILE structure in the following ways:
>
>Have the FILE structure have a name field in it:
>
>    char *name;
...

But this doesn't really solve the problem in the general case, and it's
something one can easily implement without changing stdio.  I mean, if
I called fopen() to open the file, I knew the name at some point, and
could have saved it in a table myself.

Most people who ask this question want to know the name of the file
associated with a file descriptor that they inherited via redirection,
in which case the name isn't known, and there may indeed be no name
associated with the file (pipes and unlinked temp files are the
typical examples).

Also, not everyone uses stdio (whether they should or not is a separate
issue).

The reason the solutions are dissatisfying, even after talking about
them for the last 10 years, is that there really isn't a good solution
unless you fundamentally change Unix.

-- 
David Elliott		dce@Solbourne.COM
			...!{uunet,boulder,nbires,sun}!stan!dce

"I had a dream that my kids had been reparented." - Tom LaStrange

dune@cbnewsl.ATT.COM (Greg Pasquariello) (08/23/89)

In article <19208@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
:In article <20482@sequent.UUCP> paulr@sequent.UUCP (Paul Reger) writes:
::What I mean is this ...
::Have the FILE structure have a name field in it:
::    char *name;
::then when the fopen() call is made, have it fill in the field ....
:
:This is all well and good, but you will have to define what happens
:when you ask for the name of stdin, stdout, stderr, or a file opened

:In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)

You also need to take into account actions on the fd itself, such as
unlink(fileno(fd)).

Greg Pasquariello
att!picuxa!gpasq

les@chinet.chi.il.us (Leslie Mikesell) (08/24/89)

In article <19208@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:

>>Have the FILE structure have a name field in it:
>>    char *name;
>>then when the fopen() call is made, have it fill in the field ....

>This is all well and good, but you will have to define what happens
>when you ask for the name of stdin, stdout, stderr, or a file opened
>with fdopen.  (Also, but rather incidentally, I am not terribly thrilled 
>with the idea of fopen having to call getwd.)

It would _almost_ be worthwhile to have open() store the pathname of
the thing being opened so that it could be retreived by some sort
of fcntl(), just like it would almost be worthwhile to store a
per-process cwd.  The problem would be that these pathnames are
subject to change if someone mv's or rm's any of the components and
it's probably not worth the effort to keep them updated.

Les Mikesell

ams@cbnewsl.ATT.COM (andrew.m.shaw) (08/24/89)

In article <9340@chinet.chi.il.us> les@chinet.chi.il.us (Leslie Mikesell) writes:
>In article <19208@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>
>>>Have the FILE structure have a name field in it:
>>>    char *name;
>>>then when the fopen() call is made, have it fill in the field ....
>
>>This is all well and good, but you will have to define what happens
>>when you ask for the name of stdin, stdout, stderr, or a file opened
>>with fdopen.  (Also, but rather incidentally, I am not terribly thrilled 
>>with the idea of fopen having to call getwd.)
>
>It would _almost_ be worthwhile to have open() store the pathname of
>the thing being opened so that it could be retreived by some sort
>of fcntl(), just like it would almost be worthwhile to store a
>per-process cwd.  The problem would be that these pathnames are
>subject to change if someone mv's or rm's any of the components and
>it's probably not worth the effort to keep them updated.
>
>Les Mikesell

I partially disagree - when you are in the process opening the file,
you already know the name of the node.  If you are a member of a pipeline,
you probably shouldn't know the name of the file; building code that
depends on whether file descriptor 1 is /dev/console, a pipe, or nohup.out,
is not a practice to be encouraged: casual use defeats the entire "a
device is just a file" paradigm.  And as for trying to determine the
file name of an inherited file descriptor 5, well, what kind of program
is this?

What would be really nice, however, is to have some way of attaching
file descriptors from outside a process: e.g. a process could run cu(1)
and then get the file descriptor for its own use (arbitrary protocols
implemented over dial-ups without net* programming and re-implementing
uucp).  Thus:
	...
	switch (pid=fork())
	case 0:		<exec cu>
	default:	linefd = fdattach (pid, 3);
	...
This is still horrible, in that you have to know that fd=3 is what cu
has as its line, and therefore has a high break potential, but at least
it would solve the original problem and be more general besides.

		Andrew Shaw

paulr@sequent.UUCP (Paul Reger) (08/25/89)

In article <19208@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>In article <20482@sequent.UUCP> paulr@sequent.UUCP (Paul Reger) writes:
>>What I mean is this ...
>>Have the FILE structure have a name field in it:
>>    char *name;
>>then when the fopen() call is made, have it fill in the field ....
>
>This is all well and good, but you will have to define what happens
>when you ask for the name of stdin, stdout, stderr,

This being the case maybe to solve the real problem is to provide one
kernel-level mapping:

char *
Name(f)
FILE *f;  /* Or fd... */

Which would yield the name of any file (be it a pipe, stdin, stdout,
stderr, file, a psudo tty or any gawd-awful thingy that exists...
Each would have to be special cased except for the open files which
are actual disk files (posses actual file names...).

>or a file opened
>with fdopen.  (Also, but rather incidentally, I am not terribly thrilled 
>with the idea of fopen having to call getwd.)

Maybe have two sets of kernel open()'s one with 'name saving' one
without.... 

             paulr       (Paul Reger)
     Sequent Computer Systems  Beaverton, OR.
 ... {sun,ucbvax!rutgers!ogccse,uunet}!sequent!paulr

guy@auspex.auspex.com (Guy Harris) (08/25/89)

>You also need to take into account actions on the fd itself, such as
>unlink(fileno(fd)).

No, you don't; no action on the FD itself will affect any of the links
to the file referred to by that FD, at least in any of the versions of
UNIX I know about.  "unlink" takes a path name, not a file descriptor,
for obvious reasons.

You *do* have to take into account actions on the path, though; if you
open a file and then unlink it, if the name you unlink is the same as
the name remembered by standard I/O (or anybody else), that name will no
longer be valid (the same applies if you rename it from that name). 

les@chinet.chi.il.us (Leslie Mikesell) (08/25/89)

In article <1607@cbnewsl.ATT.COM> ams@cbnewsl.ATT.COM (andrew.m.shaw,580,) writes:

>>It would _almost_ be worthwhile to have open() store the pathname of
>>the thing being opened so that it could be retreived by some sort
>>of fcntl()

>I partially disagree - when you are in the process opening the file,
>you already know the name of the node.  If you are a member of a pipeline,
>you probably shouldn't know the name of the file; building code that
>depends on whether file descriptor 1 is /dev/console, a pipe, or nohup.out,
>is not a practice to be encouraged: casual use defeats the entire "a
>device is just a file" paradigm.  And as for trying to determine the
>file name of an inherited file descriptor 5, well, what kind of program
>is this?

Don't be silly - virtually every program you run checks to see if its
output is a tty in order to set its buffering behaviour appropriately.
This is a basic need that already has its solution built into stdio.

>What would be really nice, however, is to have some way of attaching
>file descriptors from outside a process: e.g. a process could run cu(1)
>and then get the file descriptor for its own use (arbitrary protocols
>implemented over dial-ups without net* programming and re-implementing
>uucp).  Thus:
>	...
>	switch (pid=fork())
>	case 0:		<exec cu>
>	default:	linefd = fdattach (pid, 3);
>	...
>This is still horrible, in that you have to know that fd=3 is what cu
>has as its line, and therefore has a high break potential, but at least
>it would solve the original problem and be more general besides.

This would be better solved by making cu able to run subshells with
their fd's redirected arbitrarily.  That should be almost trivial
to add and would not require additional OS support.

What I had in mind was the magic involved in certain open()/close()
routines.  Suppose you are a cpio-like program that wants to handle
multiple volumes.  How can you do that if some other program (the
shell) has opened the device via redirection?  What if you want to
do a verify pass on a tape device where the only way to rewind is
to close() and open()?  What if you need to twiddle the handshake
lines on a tty device?  What if you want to send EOF to something
on the other end of a FIFO without losing the ability to send more
data later?  It's all magic and you need the name of the file for
the incantations.

Les Mikesell

guy@auspex.auspex.com (Guy Harris) (08/26/89)

>This being the case maybe to solve the real problem is to provide one
>kernel-level mapping:
>
>char *
>Name(f)
>FILE *f;  /* Or fd... */

If it's kernel-level, it had better *not* be "FILE *", since I know of
nobody who stuffed the standard I/O library code into the kernel
(fortunately).

>Which would yield the name of any file (be it a pipe, stdin, stdout,
>stderr, file, a psudo tty or any gawd-awful thingy that exists...
>Each would have to be special cased except for the open files which
>are actual disk files (posses actual file names...).

Uhh, pseudo-ttys *do* possess actual file names (can you say "character
special file"?).

And, if done right, neither the standard input, output, nor error would
need to be special-cased, since of *course* you'd attach this name to
the file table entry, and thus it would be inherited by child processes,
right?

Of course, if it just saved the file name away, it would give you the
wrong answer if the file were unlinked or renamed after it was opened,
unless the system took pains to track down saved file names and update
them on a rename or blow them away on an unlink - the rename, of course,
including any rename of any directories above the file, and both
operations including any renames done on machines other than the one on
which you're running (if you have a distributed file system such as NFS
or RFS).

In addition, of course, you'd have to keep the current working directory
around as well, if you want the mapping operation to give you an
absolute pathname; if you want the name to be inherited by child
processes and be useful, you'd have to either do that or have
per-process names that are updated whenever a process does a "chdir". 
Said copy of the current working directory would *also* have to be kept
up-to-date after renames and unlinks, assuming you want the value always
to be correct....

It's not clear that all this would be worth the cost.

ams@cbnewsl.ATT.COM (andrew.m.shaw) (08/26/89)

 In article <9353@chinet.chi.il.us> les@chinet.chi.il.us (Leslie Mikesell) writes:
 >In article <1607@cbnewsl.ATT.COM> ams@cbnewsl.ATT.COM (andrew.m.shaw,580,) writes:
 >
 >>>It would _almost_ be worthwhile to have open() store the pathname of
 >>>the thing being opened so that it could be retreived by some sort
 >>>of fcntl()
 >
 >>I partially disagree - when you are in the process opening the file,
 >>you already know the name of the node.  If you are a member of a pipeline,
 >>you probably shouldn't know the name of the file; building code that
 >>depends on whether file descriptor 1 is /dev/console, a pipe, or nohup.out,
 >>is not a practice to be encouraged: casual use defeats the entire "a
 >>device is just a file" paradigm.  And as for trying to determine the
 >>file name of an inherited file descriptor 5, well, what kind of program
 >>is this?
 >
 >Don't be silly - virtually every program you run checks to see if its
 >output is a tty in order to set its buffering behaviour appropriately.
 >This is a basic need that already has its solution built into stdio.
 
 Right, and the implementation doesn't depend on the *NAME* of the thing
 at all - only its characteristics: does it respond to ioctl(TCGETA)?
 
 >>What would be really nice, however, is to have some way of attaching
 >>file descriptors from outside a process: e.g. a process could run cu(1)
 >>and then get the file descriptor for its own use (arbitrary protocols
 >>implemented over dial-ups without net* programming and re-implementing
 >>uucp).  Thus:
 >>	...
 >>	switch (pid=fork())
 >>	case 0:		<exec cu>
 >>	default:	linefd = fdattach (pid, 3);
 >>	...
 >>This is still horrible, in that you have to know that fd=3 is what cu
 >>has as its line, and therefore has a high break potential, but at least
 >>it would solve the original problem and be more general besides.
 >
 >This would be better solved by making cu able to run subshells with
 >their fd's redirected arbitrarily.  That should be almost trivial
 >to add and would not require additional OS support.
 
 So, by having the cu(1) source you have solved exactly 1 instance of the
 general problem.  A mechanism to grab arbitrary file descriptors solves
 the problem for once and for all, without requiring people to have the
 source for every utility they want to connect to.
 
 >What I had in mind was the magic involved in certain open()/close()
 >routines.  Suppose you are a cpio-like program that wants to handle
 >multiple volumes.  How can you do that if some other program (the
 >shell) has opened the device via redirection?
 
 You open() and close() the device.  Failing that, you use the ioctls
 provided by the driver and check the return code.  Why are you interested
 in the name?
 
 >...What if you need to twiddle the handshake lines on a tty device?
 
 Once, again, you use ioctl().
 
 >What if you want to send EOF to something on the other end of a FIFO
 >without losing the ability to send more data later?
 
 Please tell me how to "send EOF" to a pipe reader without closing 
 the FIFO...  To send more data later, you re-open it.  You re-open it 
 with the name you already know from opening it the first time.
 
 >It's all magic and you need the name of the file for the incantations.
 
 Maybe to you.  Are you really writing code that breaks if the special
 file you are addressing is re-named?  Ever heard of links?
 
 -- Andrew Shaw

perry@ccssrv.UUCP (Perry Hutchison) (08/26/89)

In article <9353@chinet.chi.il.us> les@chinet.chi.il.us
(Leslie Mikesell) writes:

>What I had in mind was the magic involved in certain open()/close()
>routines.  Suppose you are a cpio-like program that wants to handle
>multiple volumes.  How can you do that if some other program (the
>shell) has opened the device via redirection?  What if you want to
>do a verify pass on a tape device where the only way to rewind is
>to close() and open()?  What if you need to twiddle the handshake
>lines on a tty device?  What if you want to send EOF to something
>on the other end of a FIFO without losing the ability to send more
>data later?  It's all magic and you need the name of the file for
>the incantations.

Another case is in messages concerning I/O errors, which really ought
to include the name of the file.

Meanwhile, in article <2385@auspex.auspex.com> guy@auspex.auspex.com
(Guy Harris) writes:

>Of course, if it just saved the file name away, it would give you the
>wrong answer if the file were unlinked or renamed after it was opened
> [ discussion of complications ]
>It's not clear that all this would be worth the cost.

For error-message purposes, as well as for Leslie's examples (which seem
to involve special files and FIFO's, which are rarely renamed or removed)
the name originally passed to open should suffice.  To allow for changes
of cwd, the absolute pathname could be saved during open.

Granted that now and then the saved name may no longer be accurate, I
still think that it would be more user-helpful than no info at all.

cpcahil@virtech.UUCP (Conor P. Cahill) (08/26/89)

In article <580@ccssrv.UUCP>, perry@ccssrv.UUCP (Perry Hutchison) writes:
> In article <9353@chinet.chi.il.us> les@chinet.chi.il.us
> (Leslie Mikesell) writes:
> 
> >What I had in mind was the magic involved in certain open()/close()
> >routines.  Suppose you are a cpio-like program that wants to handle
> >multiple volumes.  How can you do that if some other program (the
> >shell) has opened the device via redirection?  What if you want to
> >do a verify pass on a tape device where the only way to rewind is
> >to close() and open()?  What if you need to twiddle the handshake
> >lines on a tty device?  What if you want to send EOF to something
> >on the other end of a FIFO without losing the ability to send more
> >data later?  It's all magic and you need the name of the file for
> >the incantations.
> 
> For error-message purposes, as well as for Leslie's examples (which seem
> to involve special files and FIFO's, which are rarely renamed or removed)
> the name originally passed to open should suffice.  To allow for changes
> of cwd, the absolute pathname could be saved during open.
> 
> Granted that now and then the saved name may no longer be accurate, I
> still think that it would be more user-helpful than no info at all.


What about the overhead caused by such a thing.  On my "little" 386 I have
configured the kernel to allow for 400 file descriptors.  If we are going
to allow for storing the full path for every open file we have to have
room for 400 * 256 (PATH_MAX in limits.h) bytes.  I could loose 100K of 
space in the kernel just for a very little used utility that could be
programmed around.  What about larger systems with more users?

If there is some special operation that you need to perform related to 
a file whose file descriptor you have, maybe a less inefficient method
would be to add yet another f* system call (fchmod, fchown, fstat...).

I worked on a project that had the same problem in that login needed to 
perform some operations on the device special file and all it gets 
from getty is the file descriptor.  We had to add additional f* system 
calls.




-- 
+-----------------------------------------------------------------------+
| Conor P. Cahill     uunet!virtech!cpcahil      	703-430-9247	!
| Virtual Technologies Inc.,    P. O. Box 876,   Sterling, VA 22170     |
+-----------------------------------------------------------------------+

gwyn@smoke.BRL.MIL (Doug Gwyn) (08/28/89)

In article <1639@cbnewsl.ATT.COM> ams@cbnewsl.ATT.COM (andrew.m.shaw,580,) writes:
> Please tell me how to "send EOF" to a pipe reader without closing 
> the FIFO...

If your pipe implementation is any good (most are not), simply write 0
bytes to it.

Kemp@DOCKMASTER.NCSC.MIL (08/28/89)

Perry Hutchison writes:
 > Granted that now and then the saved name may no longer be accurate,
 > I still think that it would be more user-helpful than no info at all.

 NO! NO! NO! ***NO***

We don't need any more functions that return accurate information *most*
of the time.  That way lies madness.

ams@cbnewsl.ATT.COM (andrew.m.shaw) (08/29/89)

In article <10850@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>In article <1639@cbnewsl.ATT.COM> ams@cbnewsl.ATT.COM (andrew.m.shaw,580,) writes:
>> Please tell me how to "send EOF" to a pipe reader without closing 
>> the FIFO...
>
>If your pipe implementation is any good (most are not), simply write 0
>bytes to it.

'Twon't work in System V, and my POSIX says (emphasis mine) (6.1.4.2):
	(1)	If no process has the pipe open for writing, read() shall
	return 0 to indicate end-of-file.
	(2)	...
	(3)	If some process has the pipe open for writing and O_NONBLOCK
	is clear, read() shall block until *some* data is written or the
	pipe is closed by all processes that opened the pipe for writing.
Now, is a null write writing *some* data?  From POSIX 6.4.2.2:
	If nbyte is zero, the write function shall return zero *and have
	no other results* if the file is a regular file; otherwise the
	results are implementation dependent. ... Write requests to a pipe
	(or FIFO) shall be handled the same as a regular file with the
	following exceptions: 
		[4 exceptions listed, none germane to topic at hand].

So my feeling is that any implementation that supports "write 0 bytes to
satisfy the read" is non-POSIX-compliant, and therefore code that relies
on it is non-portable, &c, &c.

	Andrew Shaw

rminnich@super.ORG (Ronald G Minnich) (09/16/89)

In article <10850@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>If your pipe implementation is any good (most are not), simply write 0
>bytes to it.
Well, now i am real curious. I tried this about 6 years ago on 
several unices, mostly on vaxes and 11s and such and a Fortune machine,
and i never saw a zero-length write make it through to a read.
So, anybody ever had this work? It would be kind of neat if it did...
Sign me,
Marveling in Maryland
ron

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/17/89)

In article <14280@super.ORG> rminnich@pacific.UUCP (Ronald G Minnich) writes:
-In article <10850@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
->If your pipe implementation is any good (most are not), simply write 0
->bytes to it.
-Well, now i am real curious. I tried this about 6 years ago on 
-several unices, mostly on vaxes and 11s and such and a Fortune machine,
-and i never saw a zero-length write make it through to a read.
-So, anybody ever had this work? It would be kind of neat if it did...

I did say that most pipe implementations don't support this.
Back in the days of Sixth Edition UNIX, several sites implemented
"pipe internal EOF".  It's clear that streams COULD implement this;
I don't know whether or not the various flavors of streams do.
Personally I think they should.

dhesi@sun505.UUCP (Rahul Dhesi) (09/19/89)

In article <11099@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>I did say that most pipe implementations don't support this.
>Back in the days of Sixth Edition UNIX, several sites implemented
>"pipe internal EOF".  It's clear that streams COULD implement this;
>I don't know whether or not the various flavors of streams do.
>Personally I think they should.

I think the wizards who are shaping the development of non-AT&T UNIX
should seriously consider including a general mechanism for sending an
out-of-band EOF.  Right now the concept of a zero-byte read from a tty
meaning EOF, and the zero-byte-write method describe above, are
hack-ish.

We already have out-of-band EOFs and other data here and there in
arbitrary places:  sockets have it, i'm told that TCP/IP supports some
sort of out-of-band data, and getc() supports it by returning int
instead of char.  It would be nice to have a general mechanism for
communicating a non-stick EOF (an EOF that is not a permanent EOF).
For example:

     write (fd, buf, -1);  /* write non-stick EOF */

     ...

     count = read (...);
     if (count == 0 && errno == ENSEOF) {
        ... got non-stick EOF sent by writer ... 
     }
--
Rahul Dhesi <dhesi%cirrusl@oliveb.ATC.olivetti.com>
UUCP:  oliveb!cirrusl!dhesi

les@chinet.chi.il.us (Leslie Mikesell) (09/20/89)

In article <11099@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>->If your pipe implementation is any good (most are not), simply write 0
>->bytes to it.

>I did say that most pipe implementations don't support this.
[...]
>I don't know whether or not the various flavors of streams do.
>Personally I think they should.

Better yet, make all of the "magic" properties of "first open"
and "last close" available via fcntl() or ioctl() depending on
whether it is file magic or device magic.  Then if the /dev/tty
approach is generalized to /dev/fdn, you could do anything to
an inherited file descriptor that you could if you had the name
except rename/move/remove it.  Do the current implimentations of 
/dev/fd allow you to chmod(/dev/fd4,mode)?  

Les Mikesell

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/20/89)

In article <862@cirrusl.UUCP> dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:
>I think the wizards who are shaping the development of non-AT&T UNIX
>should seriously consider including a general mechanism for sending an
>out-of-band EOF.  Right now the concept of a zero-byte read from a tty
>meaning EOF, and the zero-byte-write method describe above, are
>hack-ish.

I utterly disagree.  Out-of-band data communication is hackish.
There never HAS been an EOF in UNIX; it's always been a read()
returning 0.  At least that is properly synchronized with the
valid data.

dhesi@sun505.UUCP (Rahul Dhesi) (09/20/89)

In article <11113@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>Out-of-band data communication is hackish.

Out-of-band data communication is hackish if and only if it is designed
to be so.  In the limited case of an out-of-band EOF, only the
representation of the EOF need be out-of-band.  BSD already represents
EOF correctly in most places (so one can, for example, distinguish
between nothing read because of a non-blocking read finding nothing and
nothing read because a blocking read found something -- such as ^D --
representing EOF).  Unfortunately this mechanism is not general enough,
so a process writing to a pipe has no way of communicating the same
thing that a user at a tty can communicate by typing the EOF
character.

>There never HAS been an EOF in UNIX; it's always been a read()
>returning 0.  At least that is properly synchronized with the
>valid data.

I see no contradiction between EOF occurring and a read() returning 0
bytes.  For regular files at least EOF has a very real meaning.
Anywhere that you can have multiple logical files or messages on a
single data stream a non-stick EOF has a very useful meaning.
--
Rahul Dhesi <dhesi%cirrusl@oliveb.ATC.olivetti.com>
UUCP:  oliveb!cirrusl!dhesi

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/20/89)

In article <867@cirrusl.UUCP> dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:
>In article <11113@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>>Out-of-band data communication is hackish.
>Out-of-band data communication is hackish if and only if it is designed
>to be so.

Not according to me!

>In the limited case of an out-of-band EOF, only the
>representation of the EOF need be out-of-band.

But since it could readily be in-band, out-of-band representation
is hackish.

>BSD already represents EOF correctly in most places (so one can,
>for example, distinguish between nothing read because of a non-blocking
>read finding nothing and nothing read because a blocking read found
>something -- such as ^D -- representing EOF).

^D does NOT NOT NOT represent EOF.  It delimits the input without
being inserted as a character in the input stream, unlike newline.
Verious UNIX terminal handlers have implemented this differently,
but in general if you type ABC^DEFG^J the first read gets ABC and
the next read gets EFG^J.  If ^D is the first input immediately
after a preceding delimiter (^D or newline), then the read gets 0
bytes returned, WHICH IS CONVENTIONALLY INTERPRETED as meaning
"end of file".  UNIX, as I said, has no inherent notion of EOF.

>Unfortunately this [BSD]  mechanism is not general enough,
>so a process writing to a pipe has no way of communicating the same
>thing that a user at a tty can communicate by typing the EOF
>character.

I agree that BSD doesn't do it right.  I'm told that SVR4 stream
pipes will probably support 0-length packets correctly.

Data packet length is a fundamental notion.  Both the OS file-system
code and common applications such as the "cat" utility should preserve
this attribute.  It's a "free" side effect of the UNIX generalized
notion of "file", if implemented properly.  No special kludges are
required.

>>There never HAS been an EOF in UNIX; it's always been a read()
>>returning 0.  At least that is properly synchronized with the
>>valid data.
>I see no contradiction between EOF occurring and a read() returning 0
>bytes.  For regular files at least EOF has a very real meaning.

It merely means that there is no data currently available past the
current seek pointer position.  A subsequent read() attempt may in
fact succeed.

I don't know what contradiction you're talking about.

>Anywhere that you can have multiple logical files or messages on a
>single data stream a non-stick EOF has a very useful meaning.

Of course it does!  It's exactly because it's meaningful and useful
to have a 0-length datum that I get annoyed when it's not properly
implemented.

boyd@necisa.ho.necisa.oz (Boyd Roberts) (09/29/89)

In article <867@cirrusl.UUCP> dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:
>... Unfortunately this mechanism is not general enough,
>so a process writing to a pipe has no way of communicating the same
>thing that a user at a tty can communicate by typing the EOF
>character.
>

This is the old poor person's approach to IPC scenario.

There is no EOF in UNIX; read() returns 0 when there's nothing more to read.
Certain devices are able to return multiple read() 0 returns (ie. ttys), but
the situation is that when read() returns 0 THERE IS NO MORE DATA TO BE READ.

You are trying to avoid implementing a protocol that would provide the
_correct_ solution.  A suitable stream line discipline would solve 
whatever your problem is.

As someone once said:

    `Don't diddle the code, choose a better algorithm'


Boyd Roberts			boyd@necisa.ho.necisa.oz.au

``When the going gets wierd, the weird turn pro...''

gwyn@smoke.BRL.MIL (Doug Gwyn) (10/07/89)

In article <947@cirrusl.UUCP> dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:
>In article <1189@necisa.ho.necisa.oz> boyd@necisa.ho.necisa.oz (Boyd Roberts)
>writes:
>>There is no EOF in UNIX; ...
>>...A suitable stream line discipline would solve 
>>whatever your problem is.
>There *is* an EOF in UNIX.  Enough UNIX documentation says it that I
>believe it.  Case closed.

UNIX beginner's documentation talks in terms of EOF to keep the notion
simpler for the novice.  However, Boyd is right; there is no EOF in UNIX.
There is a 0 return from read(), which is often INTERPRETED as meaning
EOF.

>The zero-length read/write strategy, besides not working for pipes,
>also doesn't work with buffered streams.  It's a pretty poor solution
>at this time.

0 return from read() always works.  The problem is that many common
implementations do not creat a 0-length packet when you write() 0 bytes.
Thus it is IMPOSSIBLE to "read EOF" more than once from a pipe on such a
system.  There have been implementations that support writing 0-length
packets.  That's effectively what most UNIX terminal drivers do when
the "EOF" character (typically ctrl-D) is entered immediately after a
preceding delimiter ("EOF" or "newline").

The fact is, there are some pretty poor implementations of UNIX in
widespread use..

dhesi@sun505.UUCP (Rahul Dhesi) (10/07/89)

In article <1189@necisa.ho.necisa.oz> boyd@necisa.ho.necisa.oz (Boyd Roberts)
writes:
>There is no EOF in UNIX; ...
>...A suitable stream line discipline would solve 
>whatever your problem is.

There *is* an EOF in UNIX.  Enough UNIX documentation says it that I
believe it.  Case closed.

The zero-length read/write strategy, besides not working for pipes,
also doesn't work with buffered streams.  It's a pretty poor solution
at this time.

Rahul Dhesi <dhesi%cirrusl@oliveb.ATC.olivetti.com>
UUCP:  oliveb!cirrusl!dhesi

jfh@rpp386.cactus.org (John F. Haugh II) (10/07/89)

In article <947@cirrusl.UUCP> dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:
>In article <1189@necisa.ho.necisa.oz> boyd@necisa.ho.necisa.oz (Boyd Roberts)
>writes:
>>There is no EOF in UNIX; ...
>>...A suitable stream line discipline would solve 
>>whatever your problem is.
>
>There *is* an EOF in UNIX.  Enough UNIX documentation says it that I
>believe it.  Case closed.

The only EOF UNIX has this lifetime is zero-length-read.  Until
you change your name to Ken Thompson, asserting UNIX needs a new
EOF mechanism is only going to draw stares.

The zero-length convention works -very- nicely compared to others
I've had the misfortune to use.  In particular, I'm much more fond
of 'while (read (...) > 0)' over Pascals 'while not eof (hi_mom) ...'

>The zero-length read/write strategy, besides not working for pipes,
>also doesn't work with buffered streams.  It's a pretty poor solution
>at this time.

Actually I think it's the best solution any has ever dreamt up.
The only objects which I am aware of supporting multiple EOFs are
tape devices [ and terminals, but more on that some other day ... ]

The zero-length-read paradigm has a very intuitve meaning.  It
means there is nothing left to read ...
-- 
John F. Haugh II                        +-Things you didn't want to know:------
VoiceNet: (512) 832-8832   Data: -8835  | The real meaning of MACH is ...
InterNet: jfh@rpp386.cactus.org         |    ... Messages Are Crufty Hacks.
UUCPNet:  {texbell|bigtex}!rpp386!jfh   +--------------------------------------

les@chinet.chi.il.us (Leslie Mikesell) (10/09/89)

In article <17109@rpp386.cactus.org> jfh@rpp386.cactus.org (John F. Haugh II) writes:
>The only EOF UNIX has this lifetime is zero-length-read.
[....]
>Actually I think it's the best solution any has ever dreamt up.
>The only objects which I am aware of supporting multiple EOFs are
>tape devices [ and terminals, but more on that some other day ... ]

What about FIFOS, very handy objects available on SysV for the price
of typing "/etc/mknod filename p"?  If you happen to have machines
with RFS, the reader and writer need not even be on the same CPU (which
makes other forms of IPC difficult).  There are often good reasons for
wanting the process on the other end of the fd to think it received
an EOF (the same reasons you would type ^D at a terminal).  Normally,
with a FIFO, the reader receives EOF (i.e. read returns 0) when the
last process with the FIFO open for writing closes it.  However, this
scheme does not always work well, because a) multiple processes writing
to the same FIFO may not know about each other, b) the writing process
may not know the filename (the original topic of this thread) and may
wish to continue using the same channel, and c) it is often desirable to
open FIFO's for r/w to provice the correct blocking behaviour, in which
case the reader never sees a writer's close.

>The zero-length-read paradigm has a very intuitve meaning.  It
>means there is nothing left to read ...

No, it means there is nothing currently to read, even with files.  Otherwise
there would be no such thing as "tail -f".

Les Mikesell