Front page | perl.perl5.porters |
Postings from July 2001
Followup to bug ID 20010627.004 : I have a diagnostic
Thread Next
From:
Rudif
Date:
July 2, 2001 00:50
Subject:
Followup to bug ID 20010627.004 : I have a diagnostic
Message ID:
3B3A01E700015A4E@mss2n.bluewin.ch
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.
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!
Thread Next
-
Followup to bug ID 20010627.004 : I have a diagnostic
by Rudif