df and ls for root directories on Win9X

Pierre A. Humblet Pierre.Humblet@ieee.org
Fri May 23 22:33:00 GMT 2003


On Win9X, ls reports incorrect date and size (aliasing 
with those from a file) for Windows filesystem root dirs.  

~: ls -ld /c /c/MSDOS.SYS 
drwxr-xr-x   12 pierre   unknown      1660 Jul 18  2001 /c/
-r--r--r--    1 pierre   unknown      1660 Jul 18  2001 /c/MSDOS.SYS

Also UNC pathnames of root directories cannot be stat. 

~: ls -ld //hpn5170x/c //hpn5170x/c/msdos.sys
ls: //hpn5170x/c: No such file or directory
-r--r--r--    1 pierre   unknown      1660 Jul 18  2001 //hpn5170x/c/msdos.sys

Both problems stem from incorrect use of FindFirstFile
(FindFirstFile(c:\*) does not return a handle to c:\ )

Also df is known to be broken for disks > 2 GB. A patch has been
submitted long ago, but was never completed:
<http://cygwin.com/ml/cygwin-patches/2001-q1/msg00183.html>
I have been in touch with the author, without looking at his patch.
He told me that he never got someone to sign the release.
I thus wrote a new patch from scratch.

2003-05-23  Pierre Humblet  <pierre.humblet@ieee.org>

	* autoload.cc (GetDiskFreeSpaceEx): Add.
	* syscalls.cc (statfs): Call full_path.root_dir() instead of
	rootdir(full_path). Use GetDiskFreeSpaceEx when available and
	report space available in addition to free space.
	* fhandler_disk_file.cc (fhandler_disk_file::fstat_by_name):
	Do not call FindFirstFile for disk root directories.
-------------- next part --------------
Index: autoload.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/autoload.cc,v
retrieving revision 1.69
diff -u -p -r1.69 autoload.cc
--- autoload.cc	20 Apr 2003 08:56:42 -0000	1.69
+++ autoload.cc	23 May 2003 22:11:09 -0000
@@ -502,6 +502,7 @@ LoadDLLfuncEx (CreateHardLinkA, 12, kern
 LoadDLLfuncEx (CreateToolhelp32Snapshot, 8, kernel32, 1)
 LoadDLLfuncEx2 (GetCompressedFileSizeA, 8, kernel32, 1, 0xffffffff)
 LoadDLLfuncEx (GetConsoleWindow, 0, kernel32, 1)
+LoadDLLfuncEx (GetDiskFreeSpaceEx, 16, kernel32, 1)
 LoadDLLfuncEx (GetSystemTimes, 12, kernel32, 1)
 LoadDLLfuncEx2 (IsDebuggerPresent, 0, kernel32, 1, 1)
 LoadDLLfunc (IsProcessorFeaturePresent, 4, kernel32);
Index: syscalls.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/syscalls.cc,v
retrieving revision 1.269
diff -u -p -r1.269 syscalls.cc
--- syscalls.cc	21 May 2003 08:01:57 -0000	1.269
+++ syscalls.cc	23 May 2003 22:11:29 -0000
@@ -1871,11 +1871,12 @@ statfs (const char *fname, struct statfs
     }

   path_conv full_path (fname, PC_SYM_FOLLOW | PC_FULL);
-  char *root = rootdir (full_path);
+
+  const char *root = full_path.root_dir();

   syscall_printf ("statfs %s", root);

-  DWORD spc, bps, freec, totalc;
+  DWORD spc, bps, availc, freec, totalc;

   if (!GetDiskFreeSpace (root, &spc, &bps, &freec, &totalc))
     {
@@ -1883,6 +1884,17 @@ statfs (const char *fname, struct statfs
       return -1;
     }

+  ULARGE_INTEGER availb, freeb, totalb;
+
+  if (GetDiskFreeSpaceEx (root, &availb, &totalb, &freeb))
+    {
+      availc = availb.QuadPart / (spc*bps);
+      totalc = totalb.QuadPart / (spc*bps);
+      freec = freeb.QuadPart / (spc*bps);
+    }
+  else
+    availc = freec;
+
   DWORD vsn, maxlen, flags;

   if (!GetVolumeInformation (root, NULL, 0, &vsn, &maxlen, &flags, NULL, 0))
@@ -1893,7 +1905,8 @@ statfs (const char *fname, struct statfs
   sfs->f_type = flags;
   sfs->f_bsize = spc*bps;
   sfs->f_blocks = totalc;
-  sfs->f_bfree = sfs->f_bavail = freec;
+  sfs->f_bavail = availc;
+  sfs->f_bfree = freec;
   sfs->f_files = -1;
   sfs->f_ffree = -1;
   sfs->f_fsid = vsn;
Index: fhandler_disk_file.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler_disk_file.cc,v
retrieving revision 1.50
diff -u -p -r1.50 fhandler_disk_file.cc
--- fhandler_disk_file.cc	11 May 2003 21:52:09 -0000	1.50
+++ fhandler_disk_file.cc	23 May 2003 22:11:42 -0000
@@ -109,39 +109,26 @@ fhandler_disk_file::fstat_by_name (struc
       set_errno (ENOENT);
       res = -1;
     }
+  else if (pc->isdir () && strlen (*pc) <= strlen (pc->root_dir ()))
+    {
+      FILETIME ft = {};
+      res = fstat_helper (buf, pc, ft, ft, ft, 0, 0);
+    }
+  else if ((handle = FindFirstFile (*pc, &local)) == INVALID_HANDLE_VALUE)
+    {
+      debug_printf ("FindFirstFile failed for '%s', %E", (char *) *pc);
+      __seterrno ();
+      res = -1;
+    }
   else
     {
-      char drivebuf[5];
-      char *name;
-      if ((*pc)[3] != '\0' || !isalpha ((*pc)[0]) || (*pc)[1] != ':' || (*pc)[2] != '\\')
-	name = *pc;
-      else
-	{
-	  /* FIXME: Does this work on empty disks? */
-	  drivebuf[0] = (*pc)[0];
-	  drivebuf[1] = (*pc)[1];
-	  drivebuf[2] = (*pc)[2];
-	  drivebuf[3] = '*';
-	  drivebuf[4] = '\0';
-	  name = drivebuf;
-	}
-
-      if ((handle = FindFirstFile (name, &local)) == INVALID_HANDLE_VALUE)
-      {
-	debug_printf ("FindFirstFile failed for '%s', %E", name);
-	__seterrno ();
-	res = -1;
-      }
-    else
-      {
-	FindClose (handle);
-	res = fstat_helper (buf, pc,
-			    local.ftCreationTime,
-			    local.ftLastAccessTime,
-			    local.ftLastWriteTime,
-			    local.nFileSizeHigh,
-			    local.nFileSizeLow);
-      }
+      FindClose (handle);
+      res = fstat_helper (buf, pc,
+			  local.ftCreationTime,
+			  local.ftLastAccessTime,
+			  local.ftLastWriteTime,
+			  local.nFileSizeHigh,
+			  local.nFileSizeLow);
     }
   return res;
 }


More information about the Cygwin-patches mailing list