Date: Sat, 27 Jan 2001 10:34:39 +0200 From: "Eli Zaretskii" Sender: halo1 AT zahav DOT net DOT il To: skb AT xmission DOT com (Scott Brown) Message-Id: <7458-Sat27Jan2001102214+0200-eliz@is.elta.co.il> X-Mailer: Emacs 20.6 (via feedmail 8.3.emacs20_6 I) and Blat ver 1.8.6 CC: djgpp AT delorie DOT com In-reply-to: <3a71e643.26318843@news.xmission.com> (skb@xmission.com) Subject: Re: getdfree fails & long longs interfere with DOS interrupt call References: <3a71e643 DOT 26318843 AT news DOT xmission DOT com> Reply-To: djgpp AT delorie DOT com Errors-To: nobody AT delorie DOT com X-Mailing-List: djgpp AT delorie DOT com X-Unsubscribes-To: listserv AT delorie DOT com Precedence: bulk > From: skb AT xmission DOT com (Scott Brown) > Newsgroups: comp.os.msdos.djgpp > Date: Fri, 26 Jan 2001 21:57:09 GMT > > First off, is getdfree really broken when run against large FAT32 > drives? I can't get it to report more than 2Gb for any drive. getdfree calls function 36h of Int 21h, and that function doesn't support FAT32 drives. DJGPP v2.03 doesn't support FAT32, but the current development sources do include that support, although not in getdfree. > My first test program used doubles to calculate and display the total > space/free space reported by my getdfree function. When I changed > main to use 'long long' instead of 'double', my getdfree function > stopped working -- __dpmi_int succeeds, but the returned cflag > indicates an error, and AX contains an invalid error code. > > I don't understand what's happening. Your program has a bug, which makes it behave unpredictably, depending on what random garbage do you have in memory. Changing the type of a variable shifts the other variables in memory, so the random garbage is different and you get different behavior. On my machine, your program doesn't work even with float's. See below. > I found an article indicating that long long isn't well-supported by > djgpp's COFF output I'm not aware of any problems with long long support in DJGPP. > *(unsigned short *)(buffer) = 0; > > dosmemput(path, sizeof(path), __tb); > dosmemput(buffer, sizeof(buffer), __tb + sizeof(path)); > > r.x.ax = 0x7303; > r.x.dx = __tb; > r.x.di = __tb + sizeof(path); > r.x.cx = sizeof(buffer); > if (__dpmi_int(0x21, &r)) return; This is wrong. Function 7303h needs the _second_ 16-bit word of the buffer to be zeroed out, but you only zero out the first 16-bit word of your buffer[] variable. This leaves the second word at random value (whatever was on the stack). In addition, 7303h needs DS:DX to point to the drive string in the transfer buffer, and ES:DI to point to the data buffer in the transfer buffer, but your program didn't assign anything to DS and ES. Here's the correct way of doing this: buffer[2] = buffer[3] = 0; dosmemput(path, sizeof(path), __tb); dosmemput(buffer, sizeof(buffer), __tb + sizeof(path)); r.x.ax = 0x7303; r.x.ds = r.x.es = __tb >> 4; r.x.dx = __tb & 15; r.x.di = (__tb & 15) + sizeof(path); r.x.cx = sizeof(buffer); if (__dpmi_int(0x21, &r)) return; This works for me, both with float's and with long long's. Note that on some Windows 9X systems, if the DOS box loads a TSR that hooks Int 21h, the reported values will never exceed 2GB. This is a Windows misfeature/bug, mentioned in RBIL.