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 <sys/stat.h>
 #include <sys/vfs.h> /* 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;
