diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 2f1865444..d054118a9 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,20 @@ +2012-04-02 Corinna Vinschen + + * fhandler.h (fhandler_dev::open): Declare. + (fhandler_dev::close): Declare. + (fhandler_dev::fstat): Declare. + (fhandler_dev::fstatvfs): Declare. + (fhandler_cygdrive::fstatvfs): Declare. + * fhandler_dev.cc (fhandler_dev::open): New method. + (fhandler_dev::close): Ditto. + (fhandler_dev::fstat): Ditto. + (fhandler_dev::fstatvfs): Ditto. + * fhandler_disk_file.cc (fhandler_base::fstat_helper): Don't fill + st_rdev. + (fhandler_cygdrive::fstatvfs): New method. + * path.h (path_conv::fs_got_fs): New method. + * mount.h (fs_info::got_fs): Change type to bool, make public. + 2012-04-02 Corinna Vinschen * mount.cc (fillout_mntent): Use "none" rather than 0 when checking diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 81e33569a..7fb374aa1 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -1022,6 +1022,10 @@ class fhandler_dev: public fhandler_disk_file bool dir_exists; public: fhandler_dev (); + int open (int flags, mode_t mode); + int close (); + int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); + int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2))); DIR *opendir (int fd) __attribute__ ((regparm (2))); int readdir (DIR *, dirent *) __attribute__ ((regparm (3))); void rewinddir (DIR *); @@ -1063,6 +1067,7 @@ class fhandler_cygdrive: public fhandler_disk_file void rewinddir (DIR *); int closedir (DIR *); int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); + int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2))); fhandler_cygdrive (void *) {} diff --git a/winsup/cygwin/fhandler_dev.cc b/winsup/cygwin/fhandler_dev.cc index 938e27db3..44061e050 100644 --- a/winsup/cygwin/fhandler_dev.cc +++ b/winsup/cygwin/fhandler_dev.cc @@ -10,6 +10,7 @@ details. */ #include "winsup.h" #include +#include #include "path.h" #include "fhandler.h" #include "dtable.h" @@ -35,6 +36,81 @@ fhandler_dev::fhandler_dev () : { } +int +fhandler_dev::open (int flags, mode_t mode) +{ + if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) + { + set_errno (EEXIST); + return 0; + } + if (flags & O_WRONLY) + { + set_errno (EISDIR); + return 0; + } + int ret = fhandler_disk_file::open (flags, mode); + if (!ret) + { + flags |= O_DIROPEN; + set_flags (flags); + nohandle (true); + } + return 1; +} + +int +fhandler_dev::close () +{ + if (nohandle ()) + return 0; + return fhandler_disk_file::close (); +} + +int +fhandler_dev::fstat (struct __stat64 *st) +{ + /* If /dev really exists on disk, return correct disk information. */ + if (pc.fs_got_fs ()) + return fhandler_disk_file::fstat (st); + /* Otherwise fake virtual filesystem. */ + fhandler_base::fstat (st); + st->st_ino = 2; + st->st_mode = S_IFDIR | STD_RBITS | STD_XBITS; + st->st_nlink = 1; + return 0; +} + +int __stdcall +fhandler_dev::fstatvfs (struct statvfs *sfs) +{ + int ret = -1, opened = 0; + HANDLE fh = get_handle (); + + if (!fh && !nohandle ()) + { + if (!open (O_RDONLY, 0)) + return -1; + opened = 1; + } + if (!nohandle ()) + { + ret = fhandler_disk_file::fstatvfs (sfs); + goto out; + } + /* 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; + ret = 0; + +out: + if (opened) + close (); + return ret; +} + DIR * fhandler_dev::opendir (int fd) { diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index 98e50914c..734d0accf 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -508,7 +508,7 @@ fhandler_base::fstat_helper (struct __stat64 *buf, : (PFILETIME) &pfnoi->LastWriteTime, &buf->st_ctim); to_timestruc_t ((PFILETIME) &pfnoi->CreationTime, &buf->st_birthtim); - buf->st_rdev = buf->st_dev = get_dev (); + buf->st_dev = get_dev (); /* CV 2011-01-13: Observations on the Cygwin mailing list point to an interesting behaviour in some Windows versions. Apparently the size of a directory is computed at the time the directory is first scanned. This @@ -2412,6 +2412,17 @@ fhandler_cygdrive::fstat (struct __stat64 *buf) return 0; } +int __stdcall +fhandler_cygdrive::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; +} + DIR * fhandler_cygdrive::opendir (int fd) { diff --git a/winsup/cygwin/mount.h b/winsup/cygwin/mount.h index 1c8a6cd5c..187972464 100644 --- a/winsup/cygwin/mount.h +++ b/winsup/cygwin/mount.h @@ -74,7 +74,6 @@ class fs_info } status; ULONG sernum; /* Volume Serial Number */ char fsn[80]; /* Windows filesystem name */ - unsigned long got_fs () const { return status.fs_type != none; } public: void clear () @@ -112,6 +111,7 @@ class fs_info IMPLEMENT_FS_FLAG (nwfs) IMPLEMENT_FS_FLAG (ncfsd) fs_info_type what_fs () const { return status.fs_type; } + bool got_fs () const { return status.fs_type != none; } ULONG serial_number () const { return sernum; } diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index 07302b6e2..3bbab4df7 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -1,7 +1,7 @@ /* path.h: path data structures Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007, 2008, 2009, 2010, 2011 Red Hat, Inc. + 2006, 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc. This file is part of Cygwin. @@ -344,6 +344,7 @@ class path_conv void file_attributes (DWORD new_attr) {fileattr = new_attr;} DWORD fs_flags () {return fs.flags ();} DWORD fs_name_len () {return fs.name_len ();} + bool fs_got_fs () const { return fs.got_fs (); } bool fs_is_fat () const {return fs.is_fat ();} bool fs_is_ntfs () const {return fs.is_ntfs ();} bool fs_is_samba () const {return fs.is_samba ();}