Mail Archives: djgpp-workers/2001/08/14/08:43:05
The plot thickens....
> > > The link problem is that the existing code fails on the following if
> > > condition as one of the stat buffers is from stat() and the other is
> from
> > > fstat().
> > > if (statbuf1.st_dev != statbuf2.st_dev)
> > > {
> > > (void)close(fd1);
> > > (void)close(fd2);
> > > (void)unlink(path2);
> > > errno = EXDEV;
> > > return -1;
> > > }
> >
> > The st_dev stuff comes from fstat, so the key for the problem is
> > there.
> >
> > I think this happens because, as Charles reported earlier,
> > _get_dev_info always returns zero for LFN handles, so all files look
> > as if they were on drive A:.
> >
> > If I'm right, setting LFN=n should cure this problem (of course, this
> > is not the solution I propose for the library, just something to test).
> No the solution that I found worked was to change the stat() calls to
> fstat() calls and the code in link.c then works. If this sounds okay then
I
> can produce a patch tomorrow night. It's 12:30 AM at the moment.
>
> > > The flaw in the existing fstat() code is that the dos_major vaiable is
> > > not setup on Win 98 with LFN enabled.
> >
> > Hmm? Are you sure? Could you please step with a debugger into fstat
> > and see why doesn't dos_major get set? I've just tried that on my
> > Windows 98 system, and dos_major's value was 7.
> I put a printf before the check and it printed 0. I will do this tomorrow
> night. I suspect that the following code did not call get_sft_entry(). I
> will check this tomorrow night.
Sorry, but I have verified that the code does work correctly depending on
what you test. Le me exaplain as best I can and then ask some queries to
help me resolve some of the issues.
If I recompile the fstat.c code and define TEST then the test function
included works and sets up the dos_major variable correctly. So if you test
the code by itself it works.
If I recompile CP from fileutils using only the relevant files and step
through the code then the code does NOT set up the dos_major variable, it's
set to zero. I have traced this to the djstart.c program which sets the
_djstat_flags to 0x34 in the static init_stat_bits() function. The
definition for _STAT_NEEDS_SFT is 0x23 and as such if I and these together I
do NOT get 0 and as such the GNUC compiler does not call the get_sft_entry()
which in turn initalises the dos_version function.
> /* Get pointer to an SFT entry which holds data for our handle. */
> if ( (_djstat_flags & _STAT_NEEDS_SFT) == 0 &&
> (sft_idx = get_sft_entry(fhandle)) == -1)
> {
> errno = EBADF;
> return -1;
> }
Now for the queries to help me try to find a correct solution:
1) Is it expected that the get_sft_entry() is not called in the scenario
above? (I think the answer is no)
2) Is it expected that the dos_major is setup even if the get_sft_entry() is
not called? (I think the answer is yes)
3) Any suggestions as to where to head with this issue? (My gut feel is to
always ensure that the init_stat() function is always called, once only of
course. This will ensure that the dos_version and other variables are setup
correctly, but I need to look at this if people think this is the way to go)
I have a potential fix, but I need to double check it and test it on Win 2K
and it also depends on the answers to the queries above if I am going in the
correct direction by calling the init_stat() function once as per quesry 3)
above.
I grepped the LIBC and found _djstat_flags variable in the posix\stat
directory and in the following applications (I don't have all the source
installed for all of the DJGPP packeges):
bash-2.05\shell.c
filutil4.0\src\djstart.c
filutil4.0\src\ls-msdos.c
I will have a quick look at the other posix\stat files to see if they are
also potentially affected by similar problems.
> > > The following code is the original code
> > > and is not executed on Win 98 with LFN enabled, got caught by wrong
> > > comments. My test app was CP from the file utils.
> >
> > I tried this with the simple test program produced from fstat.c if it
> > is compiled with -DTEST.
> >
> > > r.x.ax = 0x71a6; /* file info by handle */
> > > r.x.bx = fhandle;
> > > r.x.ds = __tb >> 4;
> > > r.x.dx = 0;
> > > __dpmi_int(0x21, &r);
> > > if ((r.x.flags & 1) == 0
> > > && (_farpeekl(dos_mem_base, __tb) & 0x07) == 0)
> > > stat_buf->st_mode |= WRITE_ACCESS; /* no R, S or H
> bits set */
> >
> > It might be a good idea to look into the file attributes returned by
> > 71A6: perhaps there's some indication of the drive letter there (my
> > references are silent about all but the low 6 bits of that DWORD.
>
> Will look at this tomorrow night.
The reason I think this failed was that the init_stat() function was not
called and as such the dos_mem_base was not setup and the _farpeekl() asm
code causes the crash. Traced it to the _farpeek SIGSEGV when dos_mem_base
is not initialised.
- Raw text -