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 files 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