Mail Archives: djgpp-workers/2001/08/22/08:53:40
I hope the source code below is not too large as to cause anyone any
inconveniance or problems. Sorry in advance if it does.
> > I found that the problem appears to be in the 3F00 call. I have included
a
> > sample app below that can be used to debug and test any changes.
> > If I comment out the 3F00 call and instead use _read() these also cause
the
> > problem to occur, this is expected as _read() also calls 3F00.
>
> But your annotations in the source seem to indicate that the first two
> calls to seekerprint fail, while the other 3 succeed. Do you have any
> potential explanation for this? The calls seem identical, or am I
> missing something obvious?
This is what is so puzeling in that you are 100% correct and you are not
missing anything obvious. I still cannot explain it as it is looks like one
of those Windows bugs where you need to perform a function twice so that it
works, but in this case we ned to seek to a non zero offset and then back to
zero for it to work.
I read Charles's email about adding a lseek() in the _read() function, but a
possible better solution is to add a lseek() at the end of is_executable().
We need to check and think of how people use the STDIN so that what ever
solution is done covers all potential uses for STDIN. This may mean that we
solve the STDIN issue at hand ans keep any eye out for any new issues as the
arrise.
> > The output from the sample app I am using (with allow more conditional
> > printf's and #if 0... for debugging) is:
> > seek.c 178 4200, flags = 0x02 pos = 0x0000:0000 Char at offset [0] =
(3)
> > seek.c 178 4200, flags = 0x02 pos = 0x0000:0001 Char at offset [1] =
(4)
> > seek.c 178 4200, flags = 0x02 pos = 0x0000:0000 Char at offset [0] =
(1)
> > seek.c 178 4200, flags = 0x02 pos = 0x0000:0001 Char at offset [1] =
(2)
> > seek.c 178 4200, flags = 0x02 pos = 0x0000:0002 Char at offset [2] =
(3)
>
> Thanks for the footwork. However, it is hard to track what yuo
> describe, because the above output is inconsistent with the program's
> source you posted. Could you please post a session script which shows
> output from the source of the test program you posted, including
> output from ac_get_magic?
I have included the source code I am using below and the following is the
output without the addional 4200 call as outlined below..
DJGPP_204 D:\dj204\work\seek>seek <test
seek.c 31
seek.c 42 4200, pos = 0x0000:0000
seek.c 47 4200, fh = 0, read pos = 0x0000:0000
seek.c 58 4200, goto zero pos = 0x0000:0000
seek.c 101 0x3F00 call result flags regs.x.ax = 0x0002
seek.c 118 4200, fh = 0, fpos_high= 0, fpos_low = 0
seek.c 130 4200 results, flags = 2, fh = 0, fpos_high= 0, fpos_low = 0
seek.c 150
magic_number = 0x3231
seek.c 172 4200, flags = 0x02 pos = 0x0000:0000 Char at offset [0] = (3)
seek.c 172 4200, flags = 0x02 pos = 0x0000:0000 Char at offset [0] = (4)
seek.c 172 4200, flags = 0x02 pos = 0x0000:0001 Char at offset [1] = (5)
seek.c 172 4200, flags = 0x02 pos = 0x0000:0002 Char at offset [2] = (6)
seek.c 172 4200, flags = 0x02 pos = 0x0000:0003 Char at offset [3] = (7)
seek.c 172 4200, flags = 0x02 pos = 0x0000:0004 Char at offset [4] = (8)
seek.c 172 4200, flags = 0x02 pos = 0x0000:0005 Char at offset [5] = (9)
seeker = 5
> > Taking a wild guess could this be something to do with the STDIN being
> > openned as a LFN and the 3F00 requiring a SFN type handle?
>
> So you are saying that any lseek after reading from handle 0 isn't
> working? That is, you can't seek a file if it was redirected into the
> standard input?
On the first lseek(TBA #1) is fails and then possible on some subseqent
lseek(0) it works. In my testing I have seen the following TBA numb ers, but
I suspect that there is some pattern which I need to look at to help resolve
this issue:
TBA #1 with a seek of 0 fails until a subseqent seek of 0 after a seek
of non zero
TBA #1 with a seek of 1,2,3, 4,5,6,7,8 all work
I have not had time to think of how to use this info in modifying the source
of is_executable() or other functions to work.
After I wrote the sentence above I thought that the possibel solution is to
add a seek to position 1 after the 3700 call and then to seek to zero. I
just tested this an it works. To include the change I found works change the
AC_PATCH_TEST_1 define to 1, to go back to the old code change the define
to 0.
There are other changs in the code that I am working on, for example move
the processing of the retval to just after the 3700 call so that the
additional code will not overwrite the buffer.
What do you think about this sort of solution for is_executable()?
I this is okay I could work on this patch for is_execuatable() tomorrow
night. And test it with patch to see if it works in a real world
application.
Output snippet with additonal seek is (other lines not copied):
seek.c 172 4200, flags = 0x02 pos = 0x0000:0000 Char at offset [0] = (1)
seek.c 172 4200, flags = 0x02 pos = 0x0000:0000 Char at offset [0] = (1)
seek.c 172 4200, flags = 0x02 pos = 0x0000:0001 Char at offset [1] = (2)
seek.c 172 4200, flags = 0x02 pos = 0x0000:0002 Char at offset [2] = (3)
seek.c 172 4200, flags = 0x02 pos = 0x0000:0003 Char at offset [3] = (4)
seek.c 172 4200, flags = 0x02 pos = 0x0000:0004 Char at offset [4] = (5)
seek.c 172 4200, flags = 0x02 pos = 0x0000:0005 Char at offset [5] = (6)
> If so, either they treat handle 0 specially, or the reason is deeper.
> How about if you open a file with LFN call--does lseek after read work
> then?
I will try this tomorrow night if the proposed solution above for
is_executable() does not sound okay. If it does sound okay then this will
have to wait until the weekend.
> > (I have no idea how the STDIN handle is setup.)
>
> It isn't set up by our library, itr is simply preconnected by the
> shell whcih invoked the DJGPP program. That is, when the DJGPP
> program starts, its handle 0 is already connected to the file, instead
> of being connected to the CON device.
Thanks for this as it explains how come I could not see this anywhere as it
is up to the shell used. I wonder if bash or 4DOS shell has work? I will
also try this if I have time tomorrow night.
#include <libc/stubs.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <dpmi.h>
#include <go32.h>
#include <io.h>
#include <libc/farptrgs.h>
#include <libc/dosio.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/stat.h>
#define STDIN_FILENO 0
#define AC_PATCH_TEST_1 1
/* TEST FILE IS 123456789ABCDEF */
unsigned short ac_get_magic(const char *s, int fh);
off_t aclseek(int handle, off_t offset, int whence);
unsigned short ac_get_magic(const char *s, int fh)
{
__dpmi_regs regs;
unsigned short retval;
unsigned short fpos_high = 0, fpos_low = 0;
int read_fail = 0;
int c1,c2;
printf("%s %d\n",__FILE__, __LINE__);
regs.x.ax = 0x4201; /* set pointer from current position */
regs.x.bx = fh;
regs.x.cx = regs.x.dx = 0; /* move 0 bytes (i.e., stay put) */
__dpmi_int(0x21, ®s);
if (regs.x.flags & 1)
{
printf("%s %d FAIL\n",__FILE__, __LINE__);
return 0;
}
printf("%s %d 4200, pos = 0x%04X:%04X\n",__FILE__, __LINE__,
regs.x.dx,regs.x.ax);
fpos_high = regs.x.dx; /* got current position */
fpos_low = regs.x.ax;
printf("%s %d 4200, fh = %d, read pos = 0x%04X:%04X\n",__FILE__,
__LINE__, fh, fpos_high, fpos_low);
regs.x.ax = 0x4200; /* set pointer from the beginning of file */
regs.x.cx = regs.x.dx = 0; /* move to beginning of file */
__dpmi_int(0x21, ®s);
if (regs.x.flags & 1)
{
printf("%s %d FAIL\n",__FILE__, __LINE__);
return 0;
}
printf("%s %d 4200, goto zero pos = 0x%04X:%04X\n",__FILE__, __LINE__,
regs.x.dx,regs.x.ax);
#if 1
// _read(fh,&c1,1);
// _read(fh,&c2,1);
//#else
/* Read 2 bytes from the file. */
/*
INT 21 - DOS 2+ - "READ" - READ FROM FILE OR DEVICE
AH = 3Fh
BX = file handle
CX = number of bytes to read
DS:DX -> buffer for data
Return: CF clear if successful
AX = number of bytes actually read (0 if at EOF before
call)
CF set on error
AX = error code (05h,06h) (see #01680 at
AH=59h/BX=0000h)
Notes: data is read beginning at current file position, and the
file position
is updated after a successful read
the returned AX may be smaller than the request in CX if a
partial
read occurred
if reading from CON, read stops at first CR
under the FlashTek X-32 DOS extender, the pointer is in
DS:EDX
BUG: Novell NETX.EXE v3.26 and 3.31 do not set CF if the read
fails due to
a record lock (see AH=5Ch), though it does return
AX=0005h; this
has been documented by Novell
SeeAlso: AH=27h,AH=40h,AH=93h,INT 2F/AX=1108h,INT 2F/AX=1229h
*/
regs.x.ax = 0x3f00;
regs.x.bx = fh;
regs.x.cx = 2;
regs.x.ds = __tb_segment;
regs.x.dx = __tb_offset;
__dpmi_int(0x21, ®s);
/* We can either (1) succeed, (2) read less than 2 bytes,
or (3) fail to read at all. */
if ((regs.x.ax != 2) || (regs.x.flags & 1))
{
printf("%s %d FAIL\n",__FILE__, __LINE__);
read_fail = (regs.x.flags & 1) ? regs.x.ax : -1;
}
else
{
printf("%s %d return \n",__FILE__, __LINE__,c1,c2);
#if 1
retval = (c1 << 8 ) + c2;
#else
retval = _farpeekw(_dos_ds, __tb);
#endif
}
printf("%s %d 0x3F00 call result flags regs.x.ax = 0x%04x\n",__FILE__,
__LINE__,regs.x.ax);
#endif
#if AC_PATCH_TEST_1
regs.x.ax = 0x4200; /* set pointer from the beginning of file */
regs.x.bx = fh;
regs.x.cx = 1; /* move to beginning of file */
regs.x.ds = __tb_segment;
regs.x.dx = __tb_offset;
__dpmi_int(0x21, ®s);
if (regs.x.flags & 1)
{
printf("%s %d FAIL\n",__FILE__, __LINE__);
return 0;
}
printf("%s %d 4200 goto zero results, flags = %d, fh = %d, fpos_high=
%d, fpos_low = %d\n",__FILE__, __LINE__, regs.x.flags, fh, regs.x.dx,
regs.x.ax);
#endif
printf("%s %d 4200, fh = %d, fpos_high= %d, fpos_low = %d\n",__FILE__,
__LINE__, fh, fpos_high, fpos_low);
regs.x.ax = 0x4200; /* set pointer from the beginning of file */
regs.x.bx = fh;
regs.x.cx = fpos_high;
regs.x.dx = fpos_low;
__dpmi_int(0x21, ®s);
if (regs.x.flags & 1)
{
printf("%s %d Failure code = %d\n",__FILE__, __LINE__,regs.x.ax);
return 0;
}
printf("%s %d 4200 results, flags = %d, fh = %d, fpos_high= %d, fpos_low
= %d\n",__FILE__, __LINE__, regs.x.flags, fh, regs.x.dx, regs.x.ax);
//_read(0,&c,1);
//printf("First char is: (%c)\n", c); /* If given a pathname, open the
file. */
if (read_fail == 0)
{
printf("%s %d return \n",__FILE__, __LINE__,c1,c2);
#if 1
retval = (c1 << 8 ) + c2;
#else
retval = _farpeekw(_dos_ds, __tb);
#endif
}
else
{
/* The file couldn't be read: assume non-executable. If the file
*is* executable, but was passed as a file-handle, and the user
opened it in write-only mode, they lose... */
printf("%s %d\n",__FILE__, __LINE__);
retval = 0;
if (read_fail != -1)
{
printf("%s %d FAIL\n",__FILE__, __LINE__);
errno = __doserr_to_errno(read_fail);
}
}
printf("%s %d\n",__FILE__, __LINE__);
return retval;
}
off_t aclseek(int handle, off_t offset, int whence)
{
__dpmi_regs r;
memset(&r,0,sizeof(r));
r.h.ah = 0x42;
r.h.al = whence;
r.x.bx = handle;
r.x.cx = offset >> 16;
r.x.dx = offset & 0xffff;
__dpmi_int(0x21, &r);
if (r.x.flags & 1)
{
printf("%s %d FAIL\n",__FILE__, __LINE__);
return -1;
}
printf("%s %d 42%02d, flags = 0x%02X pos = 0x%04X:%04X ",__FILE__,
__LINE__, whence, r.x.flags, r.x.dx,r.x.ax);
return (r.x.dx << 16) + r.x.ax;
}
int seekerprint(int offset)
{
int c, seeker;
seeker = aclseek(STDIN_FILENO,offset,SEEK_SET);
_read(STDIN_FILENO,&c,1);
printf("Char at offset [%d] = (%c)\n", offset, c);
return seeker;
}
int main (void)
{
int char_counter;
int c, magic_number, seeker;
long stdin_pos;
struct stat st;
FILE *pfp;
#if 1
// seeker = aclseek(STDIN_FILENO,0,SEEK_SET);
magic_number = ac_get_magic((const char *)0, STDIN_FILENO);
printf("magic_number = 0x%04X\n",magic_number);
seeker = seekerprint(0);
seeker = seekerprint(0);
seeker = seekerprint(1);
seeker = seekerprint(2);
seeker = seekerprint(3);
seeker = seekerprint(4);
seeker = seekerprint(5);
printf("seeker = %d\n",seeker);
#else
if (acfstat (STDIN_FILENO, &st) != 0)
{
printf("Error fstat");
return(-1);
}
if (S_ISREG (st.st_mode) && ((stdin_pos = ftell (stdin)) != -1))
{
pfp = stdin;
}
else
{
printf("Error fstmode");
return(-1);
}
if (!pfp)
return (-1);
fseek(pfp,0,SEEK_SET);
printf("%s %d file pos = %d\n", __FILE__, __LINE__, ftell(pfp));
for (char_counter=0;char_counter<5;char_counter++)
{
c = getc (pfp);
printf("Count = %02d, char = (%c), line = <%d>, file position=
[%d]\n", char_counter,c,__LINE__,ftell(pfp));
if (c == EOF)
{
return 0;
}
}
if (pfp)
fclose(pfp);
#endif
return(0);
}
- Raw text -