develooper Front page | perl.perl5.porters | Postings from July 2001

Re: Followup to bug ID 20010627.004 : I have a diagnostic

Thread Previous
From:
Nick Ing-Simmons
Date:
July 2, 2001 10:46
Subject:
Re: Followup to bug ID 20010627.004 : I have a diagnostic
Message ID:
20010702174619.506.5@dromedary.ni-s.u-net.com
<Rudif@bluemail.ch> writes:
>Hello
>
>I investigated some more the bug ID 20010627.004 that I reported recently
>and now I have a diagnostic.
>
>
>1. Summary
>I found that the failure of Perl filetest operator -x _ on Win2k 
>to report an executable file as executable after a -T _ 
>is due to discrepancy in st_mode values returned by Microsoft
>functions _stat() and _fstat(). Specifically, I found that _stat() sets
>the 3
>Execute bits (mask 0111 octal) to 1 when it sees an executable file, while
>_fstat() sets these bits to 0 when looking at the same file. 
>The C program below demonstrates.

This is understandable. On Win32 executable-ness is determined by 
file having an extension which is recognised as such e.g. .bat .com .exe
_stat() gets a pathname so can set the bit. _fstat just gets a number
and I am not certain there is a way to get name back given that number
or even the Handle (which can be obtained).



>
>
>2. Simplified test case
>Here is my simplified perl script that demonstrates the problem, in Active
>Perl build 626
>as well as in my local build of Perl from sources currently (Jun 2001) 
>distributed by ActiveState:
>
><code>
>#!perl -w
>
>use strict;
>
>my $exe = '../perl.exe';
>stat($exe);
>printf "BAD $exe text=%d, executable=%d\n", -T _, -x _;
>stat($exe);
>printf "OK  $exe executable=%d, text=%d\n", -x _, -T _;
>stat($exe);
>printf "OK  $exe text=%d, executable=%d\n", -T _, -x $exe;
>
>__END__
>
>BAD ../perl.exe text=0, executable=0
>OK  ../perl.exe executable=1, text=0
>OK  ../perl.exe text=0, executable=1
></code>
>
>It demonstrates that doing -T _ after stat() and before -x _ 
>produces erroneous -x result.
>
>
>3. Results of my investigation
>
>I looked into the implementation of Perl stat() and -T _.
>In fact, I ran the debugger windbg on my local build 
>while running above test script.
>
>I found this:
>
>  Perl_pp_stat() in pp_sys.c implements Perl stat()
>    calls PerlLIONameStat()
>      calls win32_stat()
>	    calls stat(path, sbuf) // Win32 library call
>		  sbuf.st_mode == 0100777 octal, for perl.exe, GOOD
>
>  Perl_pp_fttext() in pp_sys.c implements Perl -T 
>    calls PerlLIOFileStat()
>	  calls win32_fstat()
>	    calls my_fstat()
>		  calls fstat(fd, sbuf)  // Win32 library call
>		    sbuf.st_mode == 0100666 octal, for perl.exe, BAD
>
>which explains the misbehavior that I am complaining about.
>
>I wrote a test program that demonstrates the misbehavior (IMO) of Win32
>fstat():
>
><code>
>// _stattest.cpp : compare MS implementation of functions stat() and fstat()
>// rudif@bluemail.ch 1 Jul 2001
>
>
>#include <time.h>
>#include <sys/types.h>
>#include <sys/stat.h>
>#include <stdio.h>
>
>#include <io.h>
>#include <fcntl.h>
>
>void main( void )
>{
>	const char *filename = "c:\\perl\\bin\\perl.exe";
>	printf( "File name         : %s\n", filename );
>
>    {
>		static struct stat buf; // initializes to 0
>
>		if ( stat( filename, &buf ) != 0 )
>			perror( "Problem with stat()" );
>		else
>		{
>            printf( 
>				"\nFrom MSDN page on _stat():\n"
>                "    Get status information on a file.\n"
>                "    st_mode\n"
>				"    Bit mask for file-mode information.\n"
>				"    The _S_IFDIR bit is set if path specifies a directory;\n"
>				"    the _S_IFREG bit is set if path specifies an ordinary file or a
>device.\n"
>				"    User read/write bits are set according to the file’s permission
>mode;\n"
>				"    user execute bits are set according to the filename extension.\n"
>			);
>			printf( "Mode (oct)        : 0%06o\n", (unsigned short)buf.st_mode );
>			printf( "Mode (hex)        : 0x%04x\n", (unsigned short)buf.st_mode );
>         
>       }
>    }
>
>    {   
>        int fh;
>        static struct stat buf;    // initializes to 0
>
>		if ( (fh = open(filename, _O_RDONLY)) ==  -1 )
>			perror( "Problem with open()" );
>		else if ( fstat( fh, &buf ) != 0 )
>			perror( "Problem with fstat()" );
>		else
>		{
>			printf( 
>				"\nFrom MSDN page on _fstat():\n"
>                "   Get information about an open file.\n"
>                "   st_mode\n"
>                "   Bit mask for file-mode information.\n"
>                "   The _S_IFCHR bit is set if handle refers to a device.\n"
>                "   The _S_IFREG bit is set if handle refers to an ordinary
>file.\n"
>                "   The read/write bits are set according to the file's
>permission mode.\n"
>                "   _S_IFCHR and other constants are defined in SYS\\STAT.H.\n"
>            );
>			printf( "Mode (oct)        : 0%06o\n", (unsigned short)buf.st_mode );
>			printf( "Mode (hex)        : 0x%04x\n", (unsigned short)buf.st_mode );
>         
>		}
>    }
>}
>
></code>
>
>
>I included wording from MSDN doc pages on _stat() and _fstat().
>The _stat() doc says that "user execute bits are set according to the filename
>extension.",
>while the _fstat() doc does NOT mention the "user execute bits".
>
>My observation is that _stat() does what the doc says, while _fstat() silently
>
>sets the "user execute bits" to 0. OUCH.
>
>I have found that above code compiles and produces that same results when
>I replace
>  stat()      by _stat()
>  fstat()     by _fstat()
>  struct stat by struct _stat
>
>The later forms are documented in MSDN, while the former are not AFAICS.
>I am not clear on how does this relate (or not) to the ANSI C standard -
>IANAL.
>
>
>HTH
>
>Rudi Farkas
>
>
>
>
>
>
>________________________________________
>E-Mail for everyone! http://www.bluemail.ch/ powered by Bluewin!
-- 
Nick Ing-Simmons
http://www.ni-s.u-net.com/


Thread Previous


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About