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" To: "Eli Zaretskii" , "Charles Sandmann" Cc: 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 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit 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" > > 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 #include #include #include #include #include #include #include #include #include #include #include #include #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, ®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 /* 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, ®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; } 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, ®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); 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); 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); }