rac@sherpa.UUCP (Roger A. Cornelius) (02/27/89)
I've been searching for the past several days for references to this, but haven't been able to find it. I know I've read it somewhere, or maybe saw it here. Anyway, can someone tell me how to determine (in C) if output is being redirected, or more precisely, how to determine the file output is being redirected to. The cat command does this (at least the Xenix version of cat, I don't think the BSD version does), i.e.: cat catfile > catfile produces the error "cat: input catfile is output". Any help appreciated. Roger rac@sherpa uunet!sherpa!rac
klee@daisy.UUCP (Ken Lee) (02/28/89)
In article <10@sherpa.UUCP> rac@sherpa.UUCP (Roger A. Cornelius) writes: > Anyway, can someone tell me how to determine (in C) >if output is being redirected, or more precisely, how to determine the >file output is being redirected to. In BSD UNIX, you can fstat(2) stdout to determine if the output is a file or terminal (or whatever) and, what inode number it has. Since several file names can have the same inode, you can't tell exactly what file name was specified, but the inode number should be enough information for cat and other such applications. Ken Lee -- klee@daisy.uucp Daisy Systems Corp., Interactive Graphics Tools Dept.
curci@stat.uucp (Ray Curci (scri)) (02/28/89)
In article <10@sherpa.UUCP> rac@sherpa.UUCP (Roger A. Cornelius) writes: >... Anyway, can someone tell me how to determine (in C) >if output is being redirected, or more precisely, how to determine the >file output is being redirected to. >Roger rac@sherpa > uunet!sherpa!rac You may want to investigate the isatty() function call. I believe that you can use something like: isatty(stdout) which will tell you if standard out is going to a terminal (the usual case), or if it has been redirected via a pipe or into a file. ray curci florida state university supercomputer institute curci@stat.fsu.edu, curci@nu.cs.fsu.edu
gwyn@smoke.BRL.MIL (Doug Gwyn ) (02/28/89)
In article <10@sherpa.UUCP> rac@sherpa.UUCP (Roger A. Cornelius) writes: >... can someone tell me how to determine (in C) >if output is being redirected, or more precisely, how to determine the >file output is being redirected to. The cat command does this (at >least the Xenix version of cat, I don't think the BSD version does), What "cat" actually does is compare the device/inode numbers for equality; it cannot determine "the" filename because there may not be one, or it may be ambiguous (and would be expensive to figure out anyway). The device/inode numbers are obtained from the fstat() system call. These days, the system ID should also be compared. To determine a filename, assuming you can, for the inode behind a given file descriptor, is a tedious process. Your best bet is to find another solution to whatever your problem is.
guy@auspex.UUCP (Guy Harris) (02/28/89)
>Anyway, can someone tell me how to determine (in C) if output is being >redirected, or more precisely, how to determine the file output is >being redirected to. The cat command does this (at >least the Xenix version of cat, I don't think the BSD version does), Yes, the BSD version does. So does the System V Release 3 version, and I think every version since the V7 version does. However: 1) It doesn't "determine that output is being redirected"; all it does is determine that one of the input files is the same as the output file. 2) It doesn't do the latter by finding the path name for any of the files; it does an "fstat" on the file (descriptor) in question, and compares the "st_dev" and "st_ino" fields of the results. That's all it needs to do, since the "st_dev" and "st_ino" fields are sufficient to uniquely identify a file; it doesn't have to find the file's name (and that wouldn't help anyway, since the same file can have more than one name). So if you really want the name of the file, you'll have to work *very* hard to get it (you basically have to scan all mounted file systems, or at least the ones whose mount points have an "st_dev" that matches that of the file in question), and you may not get it anyway if the input is a pipe, or a file that has been unlinked.
jbayer@ispi.UUCP (Jonathan Bayer) (02/28/89)
In article <10@sherpa.UUCP> rac@sherpa.UUCP (Roger A. Cornelius) writes: >I've been searching for the past several days for references to this, >but haven't been able to find it. I know I've read it somewhere, or >maybe saw it here. Anyway, can someone tell me how to determine (in C) >if output is being redirected, or more precisely, how to determine the >file output is being redirected to. The cat command does this (at Use the stat() and fstat() functions, then compare the inode numbers in the structure. If they are the same then the two files are identical. JB -- Jonathan Bayer Beware: The light at the end of the Intelligent Software Products, Inc. tunnel may be an oncoming dragon 19 Virginia Ave. ...uunet!ispi!jbayer Rockville Centre, NY 11570 (516) 766-2867 jbayer@ispi.UUCP
frankb@usource.UUCP (Frank Bicknell) (02/28/89)
In article <10@sherpa.UUCP>, rac@sherpa.UUCP (Roger A. Cornelius) writes: > ... can someone tell me how to determine (in C) if output is > being redirected, or more precisely, how to determine the > file output is being redirected to. ... I presume you know how to determine whether the std* is directed to a terminal with isatty(). Your request seemed to hint at being able to determine whether the stdout and a file given in *argv[] were the same file. One way which comes to mind (this might be the hard way) is to use stat() on the file and fstat() on stdout. Then you compare st_ino and st_dev in both returned structures. If both sets match (ie r.st_ino == f.st_ino && r.st_dev == f.st_dev) then they must be the same file. (Network fans: is this true for remotely-mounted filesystems?) As for the general case of finding out the name of the file to which output (input) has been redirected to (from), that's more difficult, I think. The only way which comes to mind is to take that inode number and device id from fstat() and run system ("ncheck -i inode filesystem") on them. This takes a while, but beats rewriting the code to search through the directory structure (and your code would take as long as theirs, I would assume). -- Frank Bicknell; 1405 Main St, Ste 709; Sarasota, FL 34236-5701 killer!usource!frankb
md@sco.COM (Michael Davidson) (03/01/89)
In article <10@sherpa.UUCP> rac@sherpa.UUCP (Roger A. Cornelius) writes: >Anyway, can someone tell me how to determine (in C) >if output is being redirected, or more precisely, how to determine the >file output is being redirected to. You can determine the type of file associated with your standard output (or any other file descriptor) by using fstat(). This will tell you the type of file (regular, block special, character special, fifo) and the device and inode #. There is no easy way of going from a device and inode # to a pathname, short of searching through the entire directory hierarchy on the appropriate filesystem (or invoking ncheck to do it for you) - remember also that the file may have many links to it or, by the time you go looking for the path name, it may have none.... cat simply checks whether it's output has been redirected to a regular file and, if it has, does a stat() of each of it's input files, comparing device and inode # with that of the output file - if it finds a match it reports the error "cat: input foo is output".
daveh@marob.MASA.COM (Dave Hammond) (03/01/89)
In article <10@sherpa.UUCP> rac@sherpa.UUCP (Roger A. Cornelius) writes: >.................. Anyway, can someone tell me how to determine (in C) >if output is being redirected, or more precisely, how to determine the >file output is being redirected to. The cat command does this [...] > > cat catfile > catfile >produces the error "cat: input catfile is output". 1. Determine if your stdout has been redirected (isatty(fileno(stdout)) will fail if stdout is redirected). 2. Do an fstat() on fileno(stdout), and a stat() on the other file in question. 3. Compare the st_ino and st_dev members of the two stat structures. If the inode (st_ino) and device-of-directory-entry (st_dev) for the two match, your standard output and the other file are the same. Hope this helps. -- Dave Hammond daveh@marob.masa.com
arnold@mathcs.emory.edu (Arnold D. Robbins {EUCC}) (03/02/89)
>In article <10@sherpa.UUCP> rac@sherpa.UUCP (Roger A. Cornelius) writes: >> Anyway, can someone tell me how to determine (in C) >>if output is being redirected, or more precisely, how to determine the >>file output is being redirected to. The cat command does this (at In article <475@ispi.UUCP> jbayer@ispi.UUCP (Jonathan Bayer) writes: >Use the stat() and fstat() functions, then compare the inode numbers >in the structure. If they are the same then the two files are identical. Rather, compare the device and inode numbers, and if both are the same the two files are really the same file. Two files on two different filesystems (i.e. devices) can both have the same inode numbers. -- "Unix is a Registered | Arnold Robbins -- Emory University Computing Center Bell of AT&T Trademark | DOMAIN: arnold@unix.cc.emory.edu Laboratories." | UUCP: gatech!emory!arnold PHONE: +1 404 727-7636 -- Donn Seeley | BITNET: arnold@emoryu1 FAX: +1 404 727-2599
guy@auspex.UUCP (Guy Harris) (03/02/89)
>In BSD UNIX, you can fstat(2) stdout to determine if the output is a >file or terminal (or whatever) and, what inode number it has. In *any* UNIX worth of the name, you can do that; I know of none so feeble-minded that they don't allow that. >Since several file names can have the same inode, you can't tell exactly >what file name was specified, but the inode number should be enough >information for cat and other such applications. It's certainly almost enough for "cat", since all it cares about is whether any of the input files are the same as the output file or not. The inode number isn't enough, however; you also need the file system identifier, which is in the "st_dev" field. If two files have the same "st_dev" and "st_ino", they're the same file, otherwise not.
guy@auspex.UUCP (Guy Harris) (03/02/89)
>The device/inode numbers are obtained from the fstat() system call. >These days, the system ID should also be compared. The *what*? "stat" returns no system ID. RFS is, as far as I know, smart enough to ensure that the "st_dev" on a "stat" is unique on the local machine (there appears to be code that looks as if its intent is to do so); NFS does the same thing. Thus, even if file A is on a file system with major/minor 3/1 on machine A, and file B is on a file system with major/minor 3/1 on machine B, and files A and B have the same i-number, "stat" or "fstat" will reveal that they have different "st_dev"s and are thus different files. This had better be the case; otherwise, your system won't be POSIX-conformant ("File serial number (st_ino) and device ID (st_dev) taken together uniquely identify the file within the system.") This means that "st_dev"s aren't network-unique, and that "stat"ting the same file on machines A and B will give different "st_dev"s, but that's life.
guy@auspex.UUCP (Guy Harris) (03/02/89)
>You may want to investigate the isatty() function call. I believe that >you can use something like: isatty(stdout) which will tell you if >standard out is going to a terminal (the usual case), or if it has been >redirected via a pipe or into a file. We've been here before. No, "isatty(stdout)" won't tell you anything of the sort. "isatty" takes a file descriptor, *not* a standard I/O "FILE *". "isatty(fileno(stdout))", or "isatty(1)", will tell you whether the standard output is a tty or not.
guy@auspex.UUCP (Guy Harris) (03/02/89)
>Use the stat() and fstat() functions, then compare the inode numbers >in the structure. If they are the same then the two files are identical. Wrong. If the inode numbers (st_ino) *AND* the file system IDs (st_dev) are the same, then the two files are identical. If just the inode numbers are the same, you can't conclude anything about whether the files are the same or not. They could have the same inode number but be on two different file systems; inode numbers are *not* unique across file systems.
jbayer@ispi.UUCP (Jonathan Bayer) (03/02/89)
In article <1105@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes: } } }Use the stat() and fstat() functions, then compare the inode numbers } }in the structure. If they are the same then the two files are identical. } }Wrong. If the inode numbers (st_ino) *AND* the file system IDs (st_dev) }are the same, then the two files are identical. If just the inode }numbers are the same, you can't conclude anything about whether the }files are the same or not. They could have the same inode number but be }on two different file systems; inode numbers are *not* unique across }file systems. I stand corrected. Working on one filesystem for a while tends to make one forget that the inodes can come from multiple filesystems. JB -- Jonathan Bayer Beware: The light at the end of the Intelligent Software Products, Inc. tunnel may be an oncoming dragon 19 Virginia Ave. ...uunet!ispi!jbayer Rockville Centre, NY 11570 (516) 766-2867 jbayer@ispi.UUCP
gwyn@smoke.BRL.MIL (Doug Gwyn ) (03/02/89)
In article <1103@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes: >>The device/inode numbers are obtained from the fstat() system call. >>These days, the system ID should also be compared. >The *what*? I didn't say it COULD be compared.. What one ideally wants are globally-unique object handles. The kludges you described may work for the time being, but they're just sweeping the real problem under the rug. The dirt's still there, and one day it will have to be dealt with.
guy@auspex.UUCP (Guy Harris) (03/03/89)
>One way which comes to mind (this might be the hard way) is >to use stat() on the file and fstat() on stdout. The only "easier" way might be to open the file first and do an "fstat" on it as well; it's probably slightly more efficient. >Then you compare st_ino and st_dev in both returned structures. If both >sets match (ie r.st_ino == f.st_ino && r.st_dev == f.st_dev) >then they must be the same file. (Network fans: is this true >for remotely-mounted filesystems?) It's true of the SunOS NFS implementation, and probably on all NFS implementations derived from it. The AT&T S5R3 RFS implementation looks as if it attempts to preserve this property, also. Any file system implementation that *doesn't* preserve that property is broken; POSIX quite explicitly says that "st_dev" and "st_ino" uniquely identify a file.
david@wubios.wustl.edu (David J. Camp) (03/04/89)
In article <7419@pyr.gatech.EDU> curci@stat.fsu.edu (Ray Curci (scri)) writes: :>In article <10@sherpa.UUCP> rac@sherpa.UUCP (Roger A. Cornelius) writes: :>>... Anyway, can someone tell me how to determine (in C) :>>if output is being redirected, or more precisely, how to determine the :>>file output is being redirected to. :>>Roger rac@sherpa :>> uunet!sherpa!rac :> :>You may want to investigate the isatty() function call. I believe that :>you can use something like: isatty(stdout) which will tell you if :>standard out is going to a terminal (the usual case), or if it has been :>redirected via a pipe or into a file. :> :>ray curci I just received umpteen replies about this. The function call is isatty(fileno(stdout)); -David- -- Bitnet: david@wubios.wustl ^ Mr. David J. Camp Internet: david%wubios@wucs1.wustl.edu < * > Box 8067, Biostatistics uucp: uunet!wucs1!wubios!david v 660 South Euclid Washington University Medical School Saint Louis, MO 63110
les@chinet.chi.il.us (Leslie Mikesell) (03/05/89)
In article <1111@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes: >>Then you compare st_ino and st_dev in both returned structures. If both >>sets match (ie r.st_ino == f.st_ino && r.st_dev == f.st_dev) >>then they must be the same file. (Network fans: is this true >>for remotely-mounted filesystems?) >It's true of the SunOS NFS implementation, and probably on all NFS >implementations derived from it. The AT&T S5R3 RFS implementation looks >as if it attempts to preserve this property, also. Does st_dev become unique for each remote filesystem or does it just get a bit set to indicate that it is remote? If the latter case is true then the test above might falsely indicate that files on two different remote systems were the same file. Hmmm, cpio and tar might get confused also and think the files should be linked - something to consider with the versions that only store the first copy in the archive (GNUtar, PAX, perhaps others). Les Mikesell
guy@auspex.UUCP (Guy Harris) (03/06/89)
>Does st_dev become unique for each remote filesystem or does it just >get a bit set to indicate that it is remote? The SunOS version makes "st_dev" unique; it doesn't set a bit, it constructs the "st_dev" on the fly, based on local information. I don't know about the RFS version; life gets more complicated with RFS, since, as I remember, if you mount an RFS file system you also end up mounting all the file systems mounted on directories in that file system. If that's true, then you may have some headaches with those submounted file systems (and may also have RFS-mounted file systems not providing POSIX-compliant semantics; given that, AT&T will presumably fix that to work, somehow). (The same problem may exist with some of the changes that have been posted to make NFS servers do that - *caveat emptor*!)
gwyn@smoke.BRL.MIL (Doug Gwyn ) (03/06/89)
In article <1121@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes: >I don't know about the RFS version; life gets more complicated with RFS, >since, as I remember, if you mount an RFS file system you also end up >mounting all the file systems mounted on directories in that file >system. As I said, the problem looms.. One practical stopgap solution is to include a system ID in the dev_t (say, the upper half of the datum). The system ID needs to be unique across the network. Given networks such as the Internet with 32-bit host addresses, one wonders where there's going to be room in dev_t to store the host identifier. For the time being a pool of host addresses can be maintained and the pool index used locally in the dev_t to identify the site. (dev_t,ino_t) is just not big enough. I think we'd better start phasing in object handles in place of (dev_t,ino_t) at the application level, before it's too late.