delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2001/08/21/09:15:56

X-Authentication-Warning: new-smtp2.ihug.com.au: Host p13-max49.syd.ihug.com.au [203.173.144.77] claimed to be acceleron
Message-ID: <001101c12a42$7776d850$0a02a8c0@acceleron>
From: "Andrew Cottrell" <acottrel AT ihug DOT com DOT au>
To: "Eli Zaretskii" <eliz AT is DOT elta DOT co DOT il>,
"Charles Sandmann" <sandmann AT clio DOT rice DOT edu>
Cc: <djgpp-workers AT delorie DOT com>
References: <10108200508 DOT AA15103 AT clio DOT rice DOT edu> <2950-Mon20Aug2001093159+0300-eliz AT is DOT elta DOT co DOT il> <002501c12980$4c67fa80$0a02a8c0 AT acceleron> <2110-Mon20Aug2001172450+0300-eliz AT is DOT elta DOT co DOT il>
Subject: Re: Fseek on STDIN problem on Win 2K
Date: Tue, 21 Aug 2001 23:08:31 +1000
MIME-Version: 1.0
X-Priority: 3
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook Express 5.50.4807.1700
X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4807.1700
Reply-To: djgpp-workers AT delorie DOT com

> > From: "Andrew Cottrell" <acottrel AT ihug DOT com DOT au>
> > Date: Mon, 20 Aug 2001 23:58:40 +1000
> >
> > > If _is_executable is the suspect, it can be disabled by setting the
> > > _STAT_EXEC_MAGIC bit in _djstat_flags.
> > In my testing I found that I can "fix" the problem by one of the
following
> > methods:
> >     a) Commenting out the _is_executable() call in fstat.c
> >     b) Setting the  _STAT_EXEC_MAGIC bit in _djstat_flags
> >     b) adding a _read() to the  _is_executable() function before or
after
> > the second 4200 call.
> >     c) Debug the new sample under Rhide
>
> I don't understand the (c) above (it's probably due to the fact that
> RHIDE and GDB use FSEXT to watch handle usage by the debuggee), but
> otherwise it sounds like _is_executable is the prime suspect.  But I
> cannot figure out why: all it does is move the file pointer (which is
> actually a no-op, since stdin was not read yet), reads two bytes, and
> then moves the file pointer again.  One idea would be to selectively
> disable parts of _is_executable and see which one(s) cause the
> problem.
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.

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)

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? (I have no idea
how the STDIN handle is setup.)

> > I tried to find where STDIN is setup, but I couldn't see it. I do not
think
> > I am looking for the right thing. I searched for STDIN and couldn't see
> > anything useful, I loked in crt1.c. Could someone please point me in the
> > direction of where STDIN is setup/configured?
>
> What ``setup'' exactly are you looking for?
>
> stdin is a buffered stream, and its set up in
> src/libc/ansi/stdio/stdin.c.  But I don't think this is relevant to
> the issue at hand, since we now know the problem is with lseek, not
> with fseek.  And lseek works on the file handle, not on the FILE
> object.  File handle zero is the one which corresponds to standard
> input, and the shell connects that handle to the file when you
> redirect it.
>
> Does that answer your question?
Yes it does for the setup of the file object.

#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

/* 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, &regs);
    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, &regs);
    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
    /*
            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
   */
    /* Read 2 bytes from the file. */
    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, &regs);

    /* 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;
    }
    printf("%s %d 0x3F00 call result flags regs.x.ax = 0x%04x\n",__FILE__,
__LINE__,regs.x.ax);
#endif

    regs.x.ax = 0x4200;     /* set pointer from the beginning of file */
    regs.x.bx = fh;
    regs.x.cx = regs.x.dx = 0;    /* move to beginning of file */
    __dpmi_int(0x21, &regs);
    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);

    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, &regs);
    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);

    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;

  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 c, magic_number, seeker;

    magic_number = ac_get_magic((const char *)0, STDIN_FILENO);
printf("magic_number = 0x%04X\n",magic_number);

    seeker = seekerprint(0);       /* fail */
    seeker = seekerprint(1);        /* Fail */

    seeker = seekerprint(0);    /* Pass */
    seeker = seekerprint(1);    /* Pass */
    seeker = seekerprint(2);    /* Pass */

  return(0);
}

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019