X-Authentication-Warning: new-smtp1.ihug.com.au: Host p56-max18.syd.ihug.com.au [203.173.153.56] claimed to be acceleron Message-ID: <015401c124c4$d13fbdd0$0a02a8c0@acceleron> From: "Andrew Cottrell" To: , "Eli Zaretskii" Cc: "Charles Sandmann" References: <00fe01c12311$92957890$0a02a8c0 AT acceleron> <4331-Mon13Aug2001125532+0300-eliz AT is DOT elta DOT co DOT il> <019701c123f9$6febae70$0a02a8c0 AT acceleron> <557-Mon13Aug2001165656+0300-eliz AT is DOT elta DOT co DOT il> <028c01c12405$d1b326e0$0a02a8c0 AT acceleron> <013d01c124bc$b4b1fe60$0a02a8c0 AT acceleron> Subject: Re: Fw: Fstat.c patch Date: Tue, 14 Aug 2001 23:27:06 +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 > 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:. info from debugging link.c: statbuf1: stat => {st_atime = 997793254, st_ctime = 997514192, st_dev = 3, statbuf2: fstat => {st_atime = 997793324, st_ctime = 997793324, st_dev = 0, ctd: statbuf1: st_gid = 42, st_ino = 268435457, st_mode = 420, st_mtime = 997531106 statbuf2: st_gid = 42, st_ino = 268435458, st_mode = 420, st_mtime = 997793324 ctd: statbuf1: st_nlink = 1, st_size = 279, st_blksize = 16384, st_uid = 42, st_rdev = 0} statbuf2: st_nlink = 1, st_size = 0, st_blksize = 16384, st_uid = 42, st_rdev = 0} where dev_t st_dev; /* The drive number (0 = a:) */ You are correct in that it is exactly what Charles indicated previously that this is an issue with _get_dev_info(). Why do stat() and lstat()/fstat() use a different methods to get st_dev? Note that fstat() calles lstat(). The issue below is a different issue. > > > 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. > > >