How to test if stdout == stderr?

  • Follow


Hi!

In a C program (Mac OSX Darwin/BSD), I'd like to check whether stdout
and stderr are pointing to the same file.

When stdout and stderr are pointing to a tty, I can do the following
test:
   strcmp(ttyname(fileno(stderr)), ttyname(fileno(stdout))) == 0

But what if stdin and stderr have been both redirected to a file? How
to test whether it is the same actual file or not?

Thanks!
0
Reply jlcgull 3/5/2004 5:21:33 AM

Jonathan wrote:
> In a C program (Mac OSX Darwin/BSD), I'd like to check whether stdout
> and stderr are pointing to the same file.

fstat seems like the obvious way to do this.  This program isn't
guaranteed, but it works for me:

#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main( void )
{
        struct stat outstat = { 0 }, errstat = { 0 };

        if (fstat( 1, &outstat ) || fstat( 2, &errstat )) {
                perror( "fstat" );
                exit( EXIT_FAILURE );
        }

        printf( "stdout and stderr are %s.\n",
                memcmp( &outstat, &errstat, sizeof outstat )
                ? "different" : "equivilant" );
        
        return 0;
}

-- 
++acr@,ka"
0
Reply Sam 3/5/2004 6:40:13 AM


jlcgull@hotmail.com (Jonathan) writes:

> Hi!
> 
> In a C program (Mac OSX Darwin/BSD), I'd like to check whether stdout
> and stderr are pointing to the same file.
> 
> When stdout and stderr are pointing to a tty, I can do the following
> test:
>    strcmp(ttyname(fileno(stderr)), ttyname(fileno(stdout))) == 0
> 
> But what if stdin and stderr have been both redirected to a file? How
> to test whether it is the same actual file or not?


You're asking a silly question.

Imagine:

close(1);
close(2);
creat("/tmp/out-and-err",0600);
open("/tmp/out-and-err",O_WRONLY,0);
lseek(2,1000000,SEEK_SET);
if(0==fork()){
    exec("your-program");
}

Then you  could learn that  both stdout and  stderr write to  the same
file, but  they don't have the  same file position,  and stderr output
does not get overwritten until  more than 1000000 bytes are written on
stdout. stderr output could even be put some GB away.  But so what? If
that's what the caller wanted to use your program!


So what the purpose of trying to detect such occurence would be?



Otherwise, you can use fstat(2)  and compare both st_dev and st_ino to
know if two file descriptors point to the same inode.


I don't think  it would work thru NFS thought.   In particular, if you
have multiple  mounted a remote directory  thru NFS, I  bet you'll get
different  virtual device  ID  and  inode number  for  the same  file,
accessed thru the two mount points.


Then the only valid solution would  be to test the unicity of the file
by writting and reading a random pattern:
    - generate a random block,
    - seek to a predetermined position in fd 1,
    - write the random block,
    - seek to the same predetermined position in fd 2,
    - read the block,
    - compare to random block.

If it's the same  then there are good probabilities for fd  1 and fd 2
pointing to the same inode.  You can get the probability as close to 1
as you want by increasing the block size or repeating the operation.



-- 
__Pascal_Bourguignon__                     http://www.informatimago.com/
There is no worse tyranny than to force a man to pay for what he doesn't
want merely because you think it would be good for him.--Robert Heinlein
http://www.theadvocates.org/
0
Reply Pascal 3/5/2004 7:28:39 AM

Sam Dennis <sam@malfunction.screaming.net> writes:

> Jonathan wrote:
> > In a C program (Mac OSX Darwin/BSD), I'd like to check whether stdout
> > and stderr are pointing to the same file.
> 
> fstat seems like the obvious way to do this.  This program isn't
> guaranteed, but it works for me:
> 
> #include <sys/stat.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> 
> int main( void )
> {
>         struct stat outstat = { 0 }, errstat = { 0 };
> 
>         if (fstat( 1, &outstat ) || fstat( 2, &errstat )) {
>                 perror( "fstat" );
>                 exit( EXIT_FAILURE );
>         }
> 
>         printf( "stdout and stderr are %s.\n",
>                 memcmp( &outstat, &errstat, sizeof outstat )
>                 ? "different" : "equivilant" );
>         
>         return 0;
> }

It would break lamentaly if a write occured between the two fstat!
It's enough to compare: ((outstat.st_dev==errstat.st_dev)
                       &&(outstat.st_ino==errstat.st_ino))

But it would probably not work  if the file was accessed remotely thru
two different mount points.

-- 
__Pascal_Bourguignon__                     http://www.informatimago.com/
There is no worse tyranny than to force a man to pay for what he doesn't
want merely because you think it would be good for him.--Robert Heinlein
http://www.theadvocates.org/
0
Reply Pascal 3/5/2004 7:58:51 AM

3 Replies
519 Views

(page loaded in 0.063 seconds)

Similiar Articles:













7/23/2012 2:26:31 PM


Reply: