Index: syscalls.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/syscalls.cc,v retrieving revision 1.90 diff -u -p -r1.90 syscalls.cc --- syscalls.cc 2001/03/12 14:49:29 1.90 +++ syscalls.cc 2001/03/12 21:36:31 @@ -8,6 +8,8 @@ This software is a copyrighted work lice Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ +static const char *cvsId = "$Id$ $Date$ $Revision$"; + #include "winsup.h" #include #include /* needed for statfs */ @@ -1734,19 +1736,72 @@ statfs (const char *fname, struct statfs return -1; } - path_conv full_path (fname, PC_SYM_FOLLOW | PC_FULL); + path_conv full_path(fname, PC_SYM_FOLLOW | PC_FULL); char *root = rootdir (full_path); syscall_printf ("statfs %s", root); - - DWORD spc, bps, freec, totalc; - if (!GetDiskFreeSpace (root, &spc, &bps, &freec, &totalc)) + // Check to see if the GetDiskFreeSpaceEx method is available to us + FARPROC pGetDiskFreeSpaceEx; + pGetDiskFreeSpaceEx = GetProcAddress( GetModuleHandle("kernel32.dll"), + "GetDiskFreeSpaceExA"); + + if (pGetDiskFreeSpaceEx) + { + LARGE_INTEGER freeSize, totDisk, totFree; + + if (!pGetDiskFreeSpaceEx (root, + (PLARGE_INTEGER)&freeSize, + (PLARGE_INTEGER)&totDisk, + (PLARGE_INTEGER)&totFree)) { __seterrno (); return -1; } + DWORD smallTotBlocks; + unsigned __int64 largeTotBlocks; + DWORD blkSize = 2048; // Arbirtrarily start w/ 4K blocks (fat32) + DWORD prevBlkSize = 2048; // Arbirtrarily start w/ 4K blocks (fat32) + + // Check the block size. If it isn't big enough, then it seems like we + // will get some overflow for very large disks. So, try to increase + // it until we don't get an overflow. This will fail somewhere around + // 4 billion GB (0x7FFFFFFFFFFFFFFF) (I have no idea how big that is, + // or when we'll reach it) + do + { + blkSize *= 2; + if (blkSize < prevBlkSize) // overflow/wrap + return -1; + prevBlkSize = blkSize; + smallTotBlocks = totDisk.QuadPart / blkSize; + largeTotBlocks = (unsigned __int64)totDisk.QuadPart / blkSize; + } while ((unsigned __int64) smallTotBlocks != largeTotBlocks); + + sfs->f_bsize = blkSize; + sfs->f_blocks = (long) (totDisk.QuadPart / sfs->f_bsize); + sfs->f_bavail = (long) (freeSize.QuadPart / sfs->f_bsize); + sfs->f_bfree = (long) (totFree.QuadPart / sfs->f_bsize); + } // Process GetDiskFreeSpaceEx results. + else + { + DWORD spc, bps, freec, totalc; + + if (!GetDiskFreeSpace (root, &spc, &bps, &freec, &totalc)) + { + DWORD rc = GetLastError(); + if (50 != rc) + { + __seterrno (); + return -1; + } + } + sfs->f_bsize = spc*bps; + sfs->f_blocks = totalc; + sfs->f_bfree = sfs->f_bavail = freec; + } + DWORD vsn, maxlen, flags; if (!GetVolumeInformation (root, NULL, 0, &vsn, &maxlen, &flags, NULL, 0)) @@ -1755,9 +1810,6 @@ statfs (const char *fname, struct statfs return -1; } sfs->f_type = flags; - sfs->f_bsize = spc*bps; - sfs->f_blocks = totalc; - sfs->f_bfree = sfs->f_bavail = freec; sfs->f_files = -1; sfs->f_ffree = -1; sfs->f_fsid = vsn;