* fhandler.cc(fhandler_base::open): Open with READ_CONTROL only in

case of query_open flag set to query_read_control.  Add case for
	new query_read_attributes flag.
	(fhandler_base::fstatvfs): New method.
	* fhandler.h (enum query_state): Add query_read_attributes flag.
	(class fhandler_base): Declare new virtual fstatvfs method.
	(class fhandler_socket): Ditto.
	(class fhandler_pipe): Ditto.
	(class fhandler_fifo): Ditto.
	(class fhandler_disk_file): Ditto.
	(class fhandler_virtual): Ditto.
	* fhandler_disk_file.cc (fhandler_base::fstat_fs): Open with
	query_read_attributes instead of query_read_control.
	(fhandler_disk_file::fstatvfs): New method.
	(fhandler_disk_file::facl): Open with query_read_attributes instead of
	query_read_control.
	* fhandler_fifo.cc (fhandler_fifo::fstatvfs): New method.
	* fhandler_socket.cc (fhandler_socket::fstatvfs): New method.
	(fhandler_socket::fchmod): Return with EBADF in the default case.
	(fhandler_socket::fchown): Ditto.
	(fhandler_socket::facl): Ditto.
	* fhandler_virtual.cc (fhandler_virtual::fstatvfs): Ditto.
	* ntdll.h (struct _FILE_FS_ATTRIBUTE_INFORMATION): Define.
	(struct _FILE_FS_FULL_SIZE_INFORMATION): Define.
	* pipe.cc (fhandler_pipe::fstatvfs): New method.
	* syscalls.cc (fstatvfs): Just call the fhandler's fstatvfs.
	(statvfs): Ditto.
	(fstatfs): Call fstatvfs.
	(statfs): Drop EFAULT handling.
This commit is contained in:
Corinna Vinschen 2007-02-27 12:58:56 +00:00
parent 7706962caf
commit 3323df7e0e
10 changed files with 291 additions and 108 deletions

View File

@ -1,3 +1,35 @@
2007-02-27 Corinna Vinschen <corinna@vinschen.de>
* fhandler.cc(fhandler_base::open): Open with READ_CONTROL only in
case of query_open flag set to query_read_control. Add case for
new query_read_attributes flag.
(fhandler_base::fstatvfs): New method.
* fhandler.h (enum query_state): Add query_read_attributes flag.
(class fhandler_base): Declare new virtual fstatvfs method.
(class fhandler_socket): Ditto.
(class fhandler_pipe): Ditto.
(class fhandler_fifo): Ditto.
(class fhandler_disk_file): Ditto.
(class fhandler_virtual): Ditto.
* fhandler_disk_file.cc (fhandler_base::fstat_fs): Open with
query_read_attributes instead of query_read_control.
(fhandler_disk_file::fstatvfs): New method.
(fhandler_disk_file::facl): Open with query_read_attributes instead of
query_read_control.
* fhandler_fifo.cc (fhandler_fifo::fstatvfs): New method.
* fhandler_socket.cc (fhandler_socket::fstatvfs): New method.
(fhandler_socket::fchmod): Return with EBADF in the default case.
(fhandler_socket::fchown): Ditto.
(fhandler_socket::facl): Ditto.
* fhandler_virtual.cc (fhandler_virtual::fstatvfs): Ditto.
* ntdll.h (struct _FILE_FS_ATTRIBUTE_INFORMATION): Define.
(struct _FILE_FS_FULL_SIZE_INFORMATION): Define.
* pipe.cc (fhandler_pipe::fstatvfs): New method.
* syscalls.cc (fstatvfs): Just call the fhandler's fstatvfs.
(statvfs): Ditto.
(fstatfs): Call fstatvfs.
(statfs): Drop EFAULT handling.
2007-02-26 Corinna Vinschen <corinna@vinschen.de> 2007-02-26 Corinna Vinschen <corinna@vinschen.de>
* fhandler.cc (fhandler_base::fstat): Set all file times to arbitrary * fhandler.cc (fhandler_base::fstat): Set all file times to arbitrary

View File

@ -15,6 +15,7 @@ details. */
#include <sys/cygwin.h> #include <sys/cygwin.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <sys/acl.h> #include <sys/acl.h>
#include <sys/statvfs.h>
#include <signal.h> #include <signal.h>
#include "cygerrno.h" #include "cygerrno.h"
#include "perprocess.h" #include "perprocess.h"
@ -486,6 +487,10 @@ fhandler_base::open (int flags, mode_t mode)
switch (query_open ()) switch (query_open ())
{ {
case query_read_control: case query_read_control:
access = READ_CONTROL;
create_options = FILE_OPEN_FOR_BACKUP_INTENT;
break;
case query_read_attributes:
access = READ_CONTROL | FILE_READ_ATTRIBUTES; access = READ_CONTROL | FILE_READ_ATTRIBUTES;
create_options = FILE_OPEN_FOR_BACKUP_INTENT; create_options = FILE_OPEN_FOR_BACKUP_INTENT;
break; break;
@ -1144,6 +1149,16 @@ fhandler_base::fstat (struct __stat64 *buf)
return 0; return 0;
} }
int __stdcall
fhandler_base::fstatvfs (struct statvfs *sfs)
{
/* If we hit this base implementation, it's some device in /dev.
Just call statvfs on /dev for simplicity. */
path_conv pc ("/dev");
fhandler_disk_file fh (pc);
return fh.fstatvfs (sfs);
}
void void
fhandler_base::init (HANDLE f, DWORD a, mode_t bin) fhandler_base::init (HANDLE f, DWORD a, mode_t bin)
{ {

View File

@ -82,9 +82,10 @@ enum bg_check_types
enum query_state { enum query_state {
no_query = 0, no_query = 0,
query_read_control = 1, query_read_control = 1,
query_stat_control = 2, query_read_attributes = 2,
query_write_control = 3, query_stat_control = 3,
query_write_attributes = 4 query_write_control = 4,
query_write_attributes = 5
}; };
class fhandler_base class fhandler_base
@ -276,6 +277,7 @@ class fhandler_base
__attribute__ ((regparm (3))); __attribute__ ((regparm (3)));
int __stdcall fstat_by_handle (struct __stat64 *buf) __attribute__ ((regparm (2))); int __stdcall fstat_by_handle (struct __stat64 *buf) __attribute__ ((regparm (2)));
int __stdcall fstat_by_name (struct __stat64 *buf) __attribute__ ((regparm (2))); int __stdcall fstat_by_name (struct __stat64 *buf) __attribute__ ((regparm (2)));
virtual int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2)));
int utimes_fs (const struct timeval *) __attribute__ ((regparm (2))); int utimes_fs (const struct timeval *) __attribute__ ((regparm (2)));
virtual int __stdcall fchmod (mode_t mode) __attribute__ ((regparm (1))); virtual int __stdcall fchmod (mode_t mode) __attribute__ ((regparm (1)));
virtual int __stdcall fchown (__uid32_t uid, __gid32_t gid) __attribute__ ((regparm (2))); virtual int __stdcall fchown (__uid32_t uid, __gid32_t gid) __attribute__ ((regparm (2)));
@ -506,6 +508,7 @@ class fhandler_socket: public fhandler_base
char *get_sun_path () {return sun_path;} char *get_sun_path () {return sun_path;}
int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2)));
int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2)));
int __stdcall fchmod (mode_t mode) __attribute__ ((regparm (1))); int __stdcall fchmod (mode_t mode) __attribute__ ((regparm (1)));
int __stdcall fchown (__uid32_t uid, __gid32_t gid) __attribute__ ((regparm (2))); int __stdcall fchown (__uid32_t uid, __gid32_t gid) __attribute__ ((regparm (2)));
int __stdcall facl (int, int, __acl32 *) __attribute__ ((regparm (3))); int __stdcall facl (int, int, __acl32 *) __attribute__ ((regparm (3)));
@ -540,6 +543,7 @@ public:
} }
int dup (fhandler_base *child); int dup (fhandler_base *child);
int ioctl (unsigned int cmd, void *); int ioctl (unsigned int cmd, void *);
int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2)));
int __stdcall fadvise (_off64_t, _off64_t, int) __attribute__ ((regparm (3))); int __stdcall fadvise (_off64_t, _off64_t, int) __attribute__ ((regparm (3)));
int __stdcall ftruncate (_off64_t, bool) __attribute__ ((regparm (3))); int __stdcall ftruncate (_off64_t, bool) __attribute__ ((regparm (3)));
void fixup_in_child (); void fixup_in_child ();
@ -572,6 +576,7 @@ public:
void set_output_handle (HANDLE h) { output_handle = h; } void set_output_handle (HANDLE h) { output_handle = h; }
void set_use (); void set_use ();
int dup (fhandler_base *child); int dup (fhandler_base *child);
int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2)));
bool is_slow () {return true;} bool is_slow () {return true;}
void close_one_end (); void close_one_end ();
}; };
@ -692,6 +697,7 @@ class fhandler_disk_file: public fhandler_base
int __stdcall ftruncate (_off64_t, bool) __attribute__ ((regparm (3))); int __stdcall ftruncate (_off64_t, bool) __attribute__ ((regparm (3)));
int __stdcall link (const char *) __attribute__ ((regparm (2))); int __stdcall link (const char *) __attribute__ ((regparm (2)));
int __stdcall utimes (const struct timeval *) __attribute__ ((regparm (2))); int __stdcall utimes (const struct timeval *) __attribute__ ((regparm (2)));
int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2)));
HANDLE mmap (caddr_t *addr, size_t len, int prot, int flags, _off64_t off); HANDLE mmap (caddr_t *addr, size_t len, int prot, int flags, _off64_t off);
int munmap (HANDLE h, caddr_t addr, size_t len); int munmap (HANDLE h, caddr_t addr, size_t len);
@ -1228,6 +1234,7 @@ class fhandler_virtual : public fhandler_base
int open (int flags, mode_t mode = 0); int open (int flags, mode_t mode = 0);
int close (); int close ();
int __stdcall fstat (struct stat *buf) __attribute__ ((regparm (2))); int __stdcall fstat (struct stat *buf) __attribute__ ((regparm (2)));
int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2)));
int __stdcall fchmod (mode_t mode) __attribute__ ((regparm (1))); int __stdcall fchmod (mode_t mode) __attribute__ ((regparm (1)));
int __stdcall fchown (__uid32_t uid, __gid32_t gid) __attribute__ ((regparm (2))); int __stdcall fchown (__uid32_t uid, __gid32_t gid) __attribute__ ((regparm (2)));
int __stdcall facl (int, int, __acl32 *) __attribute__ ((regparm (3))); int __stdcall facl (int, int, __acl32 *) __attribute__ ((regparm (3)));

View File

@ -14,6 +14,7 @@ details. */
#include <stdlib.h> #include <stdlib.h>
#include <sys/cygwin.h> #include <sys/cygwin.h>
#include <sys/acl.h> #include <sys/acl.h>
#include <sys/statvfs.h>
#include <signal.h> #include <signal.h>
#include "cygerrno.h" #include "cygerrno.h"
#include "perprocess.h" #include "perprocess.h"
@ -340,7 +341,7 @@ fhandler_base::fstat_fs (struct __stat64 *buf)
/* If we couldn't open the file, try a query open with no permissions. /* If we couldn't open the file, try a query open with no permissions.
This allows us to determine *some* things about the file, at least. */ This allows us to determine *some* things about the file, at least. */
pc.set_exec (0); pc.set_exec (0);
query_open (query_read_control); query_open (query_read_attributes);
oret = open_fs (open_flags, 0); oret = open_fs (open_flags, 0);
} }
@ -530,6 +531,111 @@ fhandler_disk_file::fstat (struct __stat64 *buf)
return fstat_fs (buf); return fstat_fs (buf);
} }
int __stdcall
fhandler_disk_file::fstatvfs (struct statvfs *sfs)
{
int ret = -1, oret = 0;
NTSTATUS status;
IO_STATUS_BLOCK io;
const size_t fvi_size = sizeof (FILE_FS_VOLUME_INFORMATION)
+ 256 * sizeof (WCHAR);
PFILE_FS_VOLUME_INFORMATION pfvi = (PFILE_FS_VOLUME_INFORMATION)
alloca (fvi_size);
const size_t fai_size = sizeof (FILE_FS_ATTRIBUTE_INFORMATION)
+ 256 * sizeof (WCHAR);
PFILE_FS_ATTRIBUTE_INFORMATION pfai = (PFILE_FS_ATTRIBUTE_INFORMATION)
alloca (fai_size);
FILE_FS_FULL_SIZE_INFORMATION full_fsi;
FILE_FS_SIZE_INFORMATION fsi;
if (!get_io_handle ())
{
query_open (query_read_control);
oret = open_fs (O_RDONLY | O_BINARY, 0);
if (!oret)
{
/* Can't open file. Try again with rootdir. */
char root[CYG_MAX_PATH];
if (!rootdir (get_win32_name (), root))
goto out;
pc.check (root, PC_SYM_NOFOLLOW);
oret = open_fs (O_RDONLY | O_BINARY, 0);
if (!oret)
goto out;
}
}
/* Get basic volume information. */
status = NtQueryVolumeInformationFile (get_handle (), &io, pfvi, fvi_size,
FileFsVolumeInformation);
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
goto out;
}
status = NtQueryVolumeInformationFile (get_handle (), &io, pfai, fai_size,
FileFsAttributeInformation);
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
goto out;
}
sfs->f_files = ULONG_MAX;
sfs->f_ffree = ULONG_MAX;
sfs->f_favail = ULONG_MAX;
sfs->f_fsid = pfvi->VolumeSerialNumber;
sfs->f_flag = pfai->FileSystemAttributes;
sfs->f_namemax = pfai->MaximumComponentNameLength;
/* Get allocation related information. Try to get "full" information
first, which is only available since W2K. If that fails, try to
retrieve normal allocation information. */
status = NtQueryVolumeInformationFile (get_handle (), &io, &full_fsi,
sizeof full_fsi,
FileFsFullSizeInformation);
if (NT_SUCCESS (status))
{
sfs->f_bsize = full_fsi.BytesPerSector * full_fsi.SectorsPerAllocationUnit;
sfs->f_frsize = sfs->f_bsize;
sfs->f_blocks = full_fsi.TotalAllocationUnits.LowPart;
sfs->f_bfree = full_fsi.ActualAvailableAllocationUnits.LowPart;
sfs->f_bavail = full_fsi.CallerAvailableAllocationUnits.LowPart;
if (sfs->f_bfree > sfs->f_bavail)
{
/* Quotas active. We can't trust TotalAllocationUnits. */
NTFS_VOLUME_DATA_BUFFER nvdb;
DWORD bytes;
if (!DeviceIoControl (get_handle (), FSCTL_GET_NTFS_VOLUME_DATA, NULL,
0, &nvdb, sizeof nvdb, &bytes, NULL))
debug_printf ("DeviceIoControl (%s) failed, %E", get_name ());
else
sfs->f_blocks = nvdb.TotalClusters.QuadPart;
}
ret = 0;
}
else
{
status = NtQueryVolumeInformationFile (get_handle (), &io, &fsi,
sizeof fsi, FileFsSizeInformation);
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
goto out;
}
sfs->f_bsize = fsi.BytesPerSector * fsi.SectorsPerAllocationUnit;
sfs->f_frsize = sfs->f_bsize;
sfs->f_blocks = fsi.TotalAllocationUnits.LowPart;
sfs->f_bfree = fsi.AvailableAllocationUnits.LowPart;
sfs->f_bavail = sfs->f_bfree;
ret = 0;
}
out:
if (oret)
close_fs ();
syscall_printf ("%d = fstatvfs (%s, %p)", ret, get_name (), sfs);
return ret;
}
int __stdcall int __stdcall
fhandler_disk_file::fchmod (mode_t mode) fhandler_disk_file::fchmod (mode_t mode)
{ {
@ -653,7 +759,7 @@ fhandler_disk_file::facl (int cmd, int nentries, __aclent32_t *aclbufp)
{ {
if (!get_io_handle ()) if (!get_io_handle ())
{ {
query_open (query_read_control); query_open (query_read_attributes);
if (!(oret = open (O_BINARY, 0))) if (!(oret = open (O_BINARY, 0)))
return -1; return -1;
} }
@ -687,7 +793,7 @@ fhandler_disk_file::facl (int cmd, int nentries, __aclent32_t *aclbufp)
{ {
if (!get_io_handle ()) if (!get_io_handle ())
{ {
query_open (cmd == SETACL ? query_write_control : query_read_control); query_open (cmd == SETACL ? query_write_control : query_read_attributes);
if (!(oret = open (O_BINARY, 0))) if (!(oret = open (O_BINARY, 0)))
return -1; return -1;
} }

View File

@ -1,6 +1,6 @@
/* fhandler_fifo.cc - See fhandler.h for a description of the fhandler classes. /* fhandler_fifo.cc - See fhandler.h for a description of the fhandler classes.
Copyright 2002, 2003, 2004, 2005, 2006 Red Hat, Inc. Copyright 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -12,6 +12,7 @@
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/statvfs.h>
#include "cygerrno.h" #include "cygerrno.h"
#include "perprocess.h" #include "perprocess.h"
@ -238,3 +239,18 @@ fhandler_fifo::dup (fhandler_base *child)
} }
return res; return res;
} }
int __stdcall
fhandler_fifo::fstatvfs (struct statvfs *sfs)
{
/* Call statvfs on parent dir. */
char *c, dir[CYG_MAX_PATH];
strcpy (dir, get_name ());
if ((c = strrchr (dir, '/')))
{
*c = '\0';
return statvfs (dir, sfs);
}
set_errno (EBADF);
return -1;
}

View File

@ -36,6 +36,7 @@
#include "wininfo.h" #include "wininfo.h"
#include <unistd.h> #include <unistd.h>
#include <sys/acl.h> #include <sys/acl.h>
#include <sys/statvfs.h>
#include "cygtls.h" #include "cygtls.h"
#include "cygwin/in6.h" #include "cygwin/in6.h"
@ -666,6 +667,19 @@ fhandler_socket::fstat (struct __stat64 *buf)
return res; return res;
} }
int __stdcall
fhandler_socket::fstatvfs (struct statvfs *sfs)
{
if (get_device () == FH_UNIX)
{
fhandler_disk_file fh (pc);
fh.get_device () = FH_FS;
return fh.fstatvfs (sfs);
}
set_errno (EBADF);
return -1;
}
int int
fhandler_socket::fchmod (mode_t mode) fhandler_socket::fchmod (mode_t mode)
{ {
@ -677,7 +691,8 @@ fhandler_socket::fchmod (mode_t mode)
SetFileAttributes (pc, GetFileAttributes (pc) | FILE_ATTRIBUTE_SYSTEM); SetFileAttributes (pc, GetFileAttributes (pc) | FILE_ATTRIBUTE_SYSTEM);
return ret; return ret;
} }
return 0; set_errno (EBADF);
return -1;
} }
int int
@ -688,7 +703,8 @@ fhandler_socket::fchown (__uid32_t uid, __gid32_t gid)
fhandler_disk_file fh (pc); fhandler_disk_file fh (pc);
return fh.fchown (uid, gid); return fh.fchown (uid, gid);
} }
return 0; set_errno (EBADF);
return -1;
} }
int int
@ -699,7 +715,8 @@ fhandler_socket::facl (int cmd, int nentries, __aclent32_t *aclbufp)
fhandler_disk_file fh (pc); fhandler_disk_file fh (pc);
return fh.facl (cmd, nentries, aclbufp); return fh.facl (cmd, nentries, aclbufp);
} }
return fhandler_base::facl (cmd, nentries, aclbufp); set_errno (EBADF);
return -1;
} }
int int

View File

@ -1,6 +1,6 @@
/* fhandler_virtual.cc: base fhandler class for virtual filesystems /* fhandler_virtual.cc: base fhandler class for virtual filesystems
Copyright 2002, 2003, 2004, 2005 Red Hat, Inc. Copyright 2002, 2003, 2004, 2005, 2007 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -13,6 +13,7 @@ details. */
#include <stdlib.h> #include <stdlib.h>
#include <sys/cygwin.h> #include <sys/cygwin.h>
#include <sys/acl.h> #include <sys/acl.h>
#include <sys/statvfs.h>
#include "cygerrno.h" #include "cygerrno.h"
#include "security.h" #include "security.h"
#include "path.h" #include "path.h"
@ -261,3 +262,14 @@ fhandler_virtual::facl (int cmd, int nentries, __aclent32_t *aclbufp)
} }
return res; return res;
} }
int __stdcall
fhandler_virtual::fstatvfs (struct statvfs *sfs)
{
/* Virtual file system. Just return an empty buffer with a few values
set to something useful. Just as on Linux. */
memset (sfs, 0, sizeof (*sfs));
sfs->f_bsize = sfs->f_frsize = 4096;
sfs->f_namemax = NAME_MAX;
return 0;
}

View File

@ -590,6 +590,14 @@ typedef struct _FILE_COMPRESSION_INFORMATION
UCHAR ClusterSizeShift; UCHAR ClusterSizeShift;
} FILE_COMPRESSION_INFORMATION, *PFILE_COMPRESSION_INFORMATION; } FILE_COMPRESSION_INFORMATION, *PFILE_COMPRESSION_INFORMATION;
typedef struct _FILE_FS_ATTRIBUTE_INFORMATION
{
ULONG FileSystemAttributes;
ULONG MaximumComponentNameLength;
ULONG FileSystemNameLength;
WCHAR FileSystemName[1];
} FILE_FS_ATTRIBUTE_INFORMATION, *PFILE_FS_ATTRIBUTE_INFORMATION;
typedef struct _FILE_FS_VOLUME_INFORMATION typedef struct _FILE_FS_VOLUME_INFORMATION
{ {
LARGE_INTEGER VolumeCreationTime; LARGE_INTEGER VolumeCreationTime;
@ -607,6 +615,15 @@ typedef struct _FILE_FS_SIZE_INFORMATION
ULONG BytesPerSector; ULONG BytesPerSector;
} FILE_FS_SIZE_INFORMATION, *PFILE_FS_SIZE_INFORMATION; } FILE_FS_SIZE_INFORMATION, *PFILE_FS_SIZE_INFORMATION;
typedef struct _FILE_FS_FULL_SIZE_INFORMATION
{
LARGE_INTEGER TotalAllocationUnits;
LARGE_INTEGER CallerAvailableAllocationUnits;
LARGE_INTEGER ActualAvailableAllocationUnits;
ULONG SectorsPerAllocationUnit;
ULONG BytesPerSector;
} FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION;
typedef enum _FSINFOCLASS { typedef enum _FSINFOCLASS {
FileFsVolumeInformation = 1, FileFsVolumeInformation = 1,
FileFsLabelInformation, FileFsLabelInformation,

View File

@ -451,6 +451,13 @@ fhandler_pipe::ioctl (unsigned int cmd, void *p)
return 0; return 0;
} }
int __stdcall
fhandler_pipe::fstatvfs (struct statvfs *sfs)
{
set_errno (EBADF);
return -1;
}
#define DEFAULT_PIPEBUFSIZE (16 * PIPE_BUF) #define DEFAULT_PIPEBUFSIZE (16 * PIPE_BUF)
extern "C" int extern "C" int

View File

@ -1841,113 +1841,56 @@ get_osfhandle (int fd)
} }
extern "C" int extern "C" int
statvfs (const char *fname, struct statvfs *sfs) fstatvfs (int fd, struct statvfs *sfs)
{ {
int ret = -1;
char root[CYG_MAX_PATH];
myfault efault; myfault efault;
if (efault.faulted (EFAULT)) if (efault.faulted (EFAULT))
return -1; return -1;
if (!*fname)
{
set_errno (ENOENT);
return -1;
}
syscall_printf ("statfs %s", fname);
if (!sfs)
{
set_errno (EFAULT);
return -1;
}
path_conv full_path (fname, PC_SYM_FOLLOW);
if (!full_path.rootdir (root))
{
set_errno (ENOTDIR);
return -1;
}
ULARGE_INTEGER availb, freeb, totalb;
DWORD spc, bps, availc, freec, totalc, vsn, maxlen, flags;
BOOL status, statusex;
/* GetDiskFreeSpaceEx must be called before GetDiskFreeSpace on
WinME, to avoid the MS KB 314417 bug */
statusex = GetDiskFreeSpaceEx (root, &availb, &totalb, &freeb);
status = GetDiskFreeSpace (root, &spc, &bps, &freec, &totalc);
if (status)
{
if (statusex)
{
availc = availb.QuadPart / (spc*bps);
totalc = totalb.QuadPart / (spc*bps);
freec = freeb.QuadPart / (spc*bps);
if (freec > availc)
{
/* Quotas active. We can't trust totalc. */
HANDLE hdl = CreateFile (full_path, READ_CONTROL,
FILE_SHARE_VALID_FLAGS, &sec_none_nih,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (hdl == INVALID_HANDLE_VALUE)
debug_printf ("CreateFile (%s) failed, %E", (char *) full_path);
else
{
NTFS_VOLUME_DATA_BUFFER nvdb;
DWORD bytes;
if (!DeviceIoControl (hdl, FSCTL_GET_NTFS_VOLUME_DATA, NULL,
0, &nvdb, sizeof nvdb, &bytes, NULL))
debug_printf ("DeviceIoControl (%s) failed, %E", (char *) full_path);
else
totalc = nvdb.TotalClusters.QuadPart;
CloseHandle (hdl);
}
}
}
else
availc = freec;
if (GetVolumeInformation (root, NULL, 0, &vsn, &maxlen, &flags, NULL, 0))
{
sfs->f_bsize = spc*bps;
sfs->f_frsize = spc*bps;
sfs->f_blocks = totalc;
sfs->f_bfree = freec;
sfs->f_bavail = availc;
sfs->f_files = ULONG_MAX;
sfs->f_ffree = ULONG_MAX;
sfs->f_favail = ULONG_MAX;
sfs->f_fsid = vsn;
sfs->f_flag = flags;
sfs->f_namemax = maxlen;
ret = 0;
}
}
if (ret)
__seterrno ();
return ret;
}
extern "C" int
fstatvfs (int fd, struct statvfs *sfs)
{
cygheap_fdget cfd (fd); cygheap_fdget cfd (fd);
if (cfd < 0) if (cfd < 0)
return -1; return -1;
return statvfs (cfd->get_name (), sfs); return cfd->fstatvfs (sfs);
} }
extern "C" int extern "C" int
statfs (const char *fname, struct statfs *sfs) statvfs (const char *name, struct statvfs *sfs)
{ {
int res = -1;
fhandler_base *fh = NULL;
myfault efault; myfault efault;
if (efault.faulted (EFAULT)) if (efault.faulted (EFAULT))
return -1; goto error;
if (!(fh = build_fh_name (name, NULL, PC_SYM_FOLLOW, stat_suffixes)))
goto error;
if (fh->error ())
{
debug_printf ("got %d error from build_fh_name", fh->error ());
set_errno (fh->error ());
}
else if (fh->exists ())
{
debug_printf ("(%s, %p), file_attributes %d", name, sfs, (DWORD) *fh);
res = fh->fstatvfs (sfs);
}
else
set_errno (ENOENT);
delete fh;
error:
MALLOC_CHECK;
syscall_printf ("%d = (%s, %p)", res, name, sfs);
return res;
}
extern "C" int
fstatfs (int fd, struct statfs *sfs)
{
struct statvfs vfs; struct statvfs vfs;
int ret = statvfs (fname, &vfs); int ret = fstatvfs (fd, &vfs);
if (!ret) if (!ret)
{ {
sfs->f_type = vfs.f_flag; sfs->f_type = vfs.f_flag;
@ -1964,12 +1907,23 @@ statfs (const char *fname, struct statfs *sfs)
} }
extern "C" int extern "C" int
fstatfs (int fd, struct statfs *sfs) statfs (const char *fname, struct statfs *sfs)
{ {
cygheap_fdget cfd (fd); struct statvfs vfs;
if (cfd < 0) int ret = statvfs (fname, &vfs);
return -1; if (!ret)
return statfs (cfd->get_name (), sfs); {
sfs->f_type = vfs.f_flag;
sfs->f_bsize = vfs.f_bsize;
sfs->f_blocks = vfs.f_blocks;
sfs->f_bavail = vfs.f_bavail;
sfs->f_bfree = vfs.f_bfree;
sfs->f_files = -1;
sfs->f_ffree = -1;
sfs->f_fsid = vfs.f_fsid;
sfs->f_namelen = vfs.f_namemax;
}
return ret;
} }
/* setpgid: POSIX 4.3.3.1 */ /* setpgid: POSIX 4.3.3.1 */