From 3323df7e0ed8be20dcd1643212858399514dd158 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 27 Feb 2007 12:58:56 +0000 Subject: [PATCH] * 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. --- winsup/cygwin/ChangeLog | 32 ++++++ winsup/cygwin/fhandler.cc | 15 +++ winsup/cygwin/fhandler.h | 13 ++- winsup/cygwin/fhandler_disk_file.cc | 112 ++++++++++++++++++++- winsup/cygwin/fhandler_fifo.cc | 18 +++- winsup/cygwin/fhandler_socket.cc | 23 ++++- winsup/cygwin/fhandler_virtual.cc | 14 ++- winsup/cygwin/ntdll.h | 17 ++++ winsup/cygwin/pipe.cc | 7 ++ winsup/cygwin/syscalls.cc | 148 ++++++++++------------------ 10 files changed, 291 insertions(+), 108 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 54af60a48..1dc89f726 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,35 @@ +2007-02-27 Corinna Vinschen + + * 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 * fhandler.cc (fhandler_base::fstat): Set all file times to arbitrary diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index 864a4e66e..f92e844c0 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -15,6 +15,7 @@ details. */ #include #include #include +#include #include #include "cygerrno.h" #include "perprocess.h" @@ -486,6 +487,10 @@ fhandler_base::open (int flags, mode_t mode) switch (query_open ()) { 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; create_options = FILE_OPEN_FOR_BACKUP_INTENT; break; @@ -1144,6 +1149,16 @@ fhandler_base::fstat (struct __stat64 *buf) 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 fhandler_base::init (HANDLE f, DWORD a, mode_t bin) { diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 112ac6ecd..34b6680c3 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -82,9 +82,10 @@ enum bg_check_types enum query_state { no_query = 0, query_read_control = 1, - query_stat_control = 2, - query_write_control = 3, - query_write_attributes = 4 + query_read_attributes = 2, + query_stat_control = 3, + query_write_control = 4, + query_write_attributes = 5 }; class fhandler_base @@ -276,6 +277,7 @@ class fhandler_base __attribute__ ((regparm (3))); int __stdcall fstat_by_handle (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))); virtual int __stdcall fchmod (mode_t mode) __attribute__ ((regparm (1))); 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;} 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 fchown (__uid32_t uid, __gid32_t gid) __attribute__ ((regparm (2))); int __stdcall facl (int, int, __acl32 *) __attribute__ ((regparm (3))); @@ -540,6 +543,7 @@ public: } int dup (fhandler_base *child); 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 ftruncate (_off64_t, bool) __attribute__ ((regparm (3))); void fixup_in_child (); @@ -572,6 +576,7 @@ public: void set_output_handle (HANDLE h) { output_handle = h; } void set_use (); int dup (fhandler_base *child); + int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2))); bool is_slow () {return true;} 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 link (const char *) __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); 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 close (); 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 fchown (__uid32_t uid, __gid32_t gid) __attribute__ ((regparm (2))); int __stdcall facl (int, int, __acl32 *) __attribute__ ((regparm (3))); diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index f5dfe33aa..3e2e059f9 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -14,6 +14,7 @@ details. */ #include #include #include +#include #include #include "cygerrno.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. This allows us to determine *some* things about the file, at least. */ pc.set_exec (0); - query_open (query_read_control); + query_open (query_read_attributes); oret = open_fs (open_flags, 0); } @@ -530,6 +531,111 @@ fhandler_disk_file::fstat (struct __stat64 *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 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 ()) { - query_open (query_read_control); + query_open (query_read_attributes); if (!(oret = open (O_BINARY, 0))) return -1; } @@ -687,7 +793,7 @@ fhandler_disk_file::facl (int cmd, int nentries, __aclent32_t *aclbufp) { 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))) return -1; } diff --git a/winsup/cygwin/fhandler_fifo.cc b/winsup/cygwin/fhandler_fifo.cc index 8f5e793f7..9143be741 100644 --- a/winsup/cygwin/fhandler_fifo.cc +++ b/winsup/cygwin/fhandler_fifo.cc @@ -1,6 +1,6 @@ /* 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. @@ -12,6 +12,7 @@ #include #include #include +#include #include "cygerrno.h" #include "perprocess.h" @@ -238,3 +239,18 @@ fhandler_fifo::dup (fhandler_base *child) } 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; +} diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index d2ae0cca1..d5384fe46 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -36,6 +36,7 @@ #include "wininfo.h" #include #include +#include #include "cygtls.h" #include "cygwin/in6.h" @@ -666,6 +667,19 @@ fhandler_socket::fstat (struct __stat64 *buf) 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 fhandler_socket::fchmod (mode_t mode) { @@ -677,7 +691,8 @@ fhandler_socket::fchmod (mode_t mode) SetFileAttributes (pc, GetFileAttributes (pc) | FILE_ATTRIBUTE_SYSTEM); return ret; } - return 0; + set_errno (EBADF); + return -1; } int @@ -688,7 +703,8 @@ fhandler_socket::fchown (__uid32_t uid, __gid32_t gid) fhandler_disk_file fh (pc); return fh.fchown (uid, gid); } - return 0; + set_errno (EBADF); + return -1; } int @@ -699,7 +715,8 @@ fhandler_socket::facl (int cmd, int nentries, __aclent32_t *aclbufp) fhandler_disk_file fh (pc); return fh.facl (cmd, nentries, aclbufp); } - return fhandler_base::facl (cmd, nentries, aclbufp); + set_errno (EBADF); + return -1; } int diff --git a/winsup/cygwin/fhandler_virtual.cc b/winsup/cygwin/fhandler_virtual.cc index 98620f4cc..13f8e1fd4 100644 --- a/winsup/cygwin/fhandler_virtual.cc +++ b/winsup/cygwin/fhandler_virtual.cc @@ -1,6 +1,6 @@ /* 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. @@ -13,6 +13,7 @@ details. */ #include #include #include +#include #include "cygerrno.h" #include "security.h" #include "path.h" @@ -261,3 +262,14 @@ fhandler_virtual::facl (int cmd, int nentries, __aclent32_t *aclbufp) } 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; +} diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h index fc56ce00c..4fc5da599 100644 --- a/winsup/cygwin/ntdll.h +++ b/winsup/cygwin/ntdll.h @@ -590,6 +590,14 @@ typedef struct _FILE_COMPRESSION_INFORMATION UCHAR ClusterSizeShift; } 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 { LARGE_INTEGER VolumeCreationTime; @@ -607,6 +615,15 @@ typedef struct _FILE_FS_SIZE_INFORMATION ULONG BytesPerSector; } 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 { FileFsVolumeInformation = 1, FileFsLabelInformation, diff --git a/winsup/cygwin/pipe.cc b/winsup/cygwin/pipe.cc index b53cc2f7f..59fb4c4d9 100644 --- a/winsup/cygwin/pipe.cc +++ b/winsup/cygwin/pipe.cc @@ -451,6 +451,13 @@ fhandler_pipe::ioctl (unsigned int cmd, void *p) return 0; } +int __stdcall +fhandler_pipe::fstatvfs (struct statvfs *sfs) +{ + set_errno (EBADF); + return -1; +} + #define DEFAULT_PIPEBUFSIZE (16 * PIPE_BUF) extern "C" int diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 8e151ff55..976e66099 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -1841,113 +1841,56 @@ get_osfhandle (int fd) } 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; if (efault.faulted (EFAULT)) 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); if (cfd < 0) return -1; - return statvfs (cfd->get_name (), sfs); + return cfd->fstatvfs (sfs); } 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; 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; - int ret = statvfs (fname, &vfs); + int ret = fstatvfs (fd, &vfs); if (!ret) { sfs->f_type = vfs.f_flag; @@ -1964,12 +1907,23 @@ statfs (const char *fname, struct statfs *sfs) } extern "C" int -fstatfs (int fd, struct statfs *sfs) +statfs (const char *fname, struct statfs *sfs) { - cygheap_fdget cfd (fd); - if (cfd < 0) - return -1; - return statfs (cfd->get_name (), sfs); + struct statvfs vfs; + int ret = statvfs (fname, &vfs); + if (!ret) + { + 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 */