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