Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2006-04-26 20:51:09 +0400
committerCorinna Vinschen <corinna@vinschen.de>2006-04-26 20:51:09 +0400
commit330a2faed95927d539db8bae15748eb1e0e12a02 (patch)
tree3c343e2d30e9e0a53b2f4ec577355718fb3d0b0e /winsup
parent13ac451951ca86151fc13722216f386c8298c34b (diff)
* fhandler.h (fhandler_base): Change fstat_helper prototype
to take file size and inode number as 64 bit values. * fhandler_disk_file.cc (FS_IS_SAMBA): Move to path.cc (FS_IS_SAMBA_WITH_QUOTA): Ditto. (path_conv::hasgood_inode): Delete. (path_conv::is_samba): Delete. (path_conv::isgood_inode): Centralized function to recognize a good inode number. (fhandler_base::fstat_by_handle): Constify fvi_size and fai_size. Accomodate argument change in fstat_helper. (fhandler_base::fstat_by_name): Ditto. (fhandler_base::fstat_helper): Accomodate argument change. Call path_conv::isgood_inode to recognize good inodes. (fhandler_disk_file::opendir): Explain Samba weirdness here. Call path_conv::fs_is_samba instead of path_conv::is_samba. (fhandler_disk_file::readdir): Add STATUS_INVALID_INFO_CLASS as valid return code from NtQueryDirectoryFile to indicate that FileIdBothDirectoryInformation is not supported. Call path_conv::isgood_inode to recognize good inodes. * ntdll.h (STATUS_INVALID_INFO_CLASS): Define. * path.cc (fs_info::update): Rework file system recognition and set appropriate flags. * path.h (struct fs_info): Add is_ntfs, is_samba and is_nfs flags. Constify pure read accessors.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog27
-rw-r--r--winsup/cygwin/fhandler.h6
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc117
-rw-r--r--winsup/cygwin/ntdll.h1
-rw-r--r--winsup/cygwin/path.cc25
-rw-r--r--winsup/cygwin/path.h43
6 files changed, 124 insertions, 95 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 708c51125..b7a8f46c9 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,30 @@
+2006-04-26 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler.h (fhandler_base): Change fstat_helper prototype
+ to take file size and inode number as 64 bit values.
+ * fhandler_disk_file.cc (FS_IS_SAMBA): Move to path.cc
+ (FS_IS_SAMBA_WITH_QUOTA): Ditto.
+ (path_conv::hasgood_inode): Delete.
+ (path_conv::is_samba): Delete.
+ (path_conv::isgood_inode): Centralized function to recognize
+ a good inode number.
+ (fhandler_base::fstat_by_handle): Constify fvi_size and fai_size.
+ Accomodate argument change in fstat_helper.
+ (fhandler_base::fstat_by_name): Ditto.
+ (fhandler_base::fstat_helper): Accomodate argument change. Call
+ path_conv::isgood_inode to recognize good inodes.
+ (fhandler_disk_file::opendir): Explain Samba weirdness here.
+ Call path_conv::fs_is_samba instead of path_conv::is_samba.
+ (fhandler_disk_file::readdir): Add STATUS_INVALID_INFO_CLASS
+ as valid return code from NtQueryDirectoryFile to indicate that
+ FileIdBothDirectoryInformation is not supported.
+ Call path_conv::isgood_inode to recognize good inodes.
+ * ntdll.h (STATUS_INVALID_INFO_CLASS): Define.
+ * path.cc (fs_info::update): Rework file system recognition
+ and set appropriate flags.
+ * path.h (struct fs_info): Add is_ntfs, is_samba and is_nfs flags.
+ Constify pure read accessors.
+
2006-04-24 Christopher Faylor <cgf@timesys.com>
* environ.cc (getearly): Force correct dereference order when
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index bd068a88d..52e41e27a 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -266,11 +266,9 @@ class fhandler_base
FILETIME ftLastAccessTime,
FILETIME ftLastWriteTime,
DWORD dwVolumeSerialNumber,
- DWORD nFileSizeHigh,
- DWORD nFileSizeLow,
+ ULONGLONG nFileSize,
LONGLONG nAllocSize,
- DWORD nFileIndexHigh,
- DWORD nFileIndexLow,
+ ULONGLONG nFileIndex,
DWORD nNumberOfLinks,
DWORD dwFileAttributes)
__attribute__ ((regparm (3)));
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index 04f312b8a..7470dcb94 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -196,46 +196,15 @@ path_conv::ndisk_links (DWORD nNumberOfLinks)
return count + saw_dot;
}
-#define FS_IS_SAMBA (FILE_CASE_SENSITIVE_SEARCH \
- | FILE_CASE_PRESERVED_NAMES \
- | FILE_PERSISTENT_ACLS)
-
-#define FS_IS_SAMBA_WITH_QUOTA \
- (FILE_CASE_SENSITIVE_SEARCH \
- | FILE_CASE_PRESERVED_NAMES \
- | FILE_PERSISTENT_ACLS \
- | FILE_VOLUME_QUOTAS)
-
-inline bool
-path_conv::hasgood_inode ()
-{
- /* Assume that if a drive has ACL support it MAY have valid "inodes".
- It definitely does not have valid inodes if it does not have ACL
- support. Decouple from has_acls() which follows smbntsec setting. */
- return ((fs_flags () & FILE_PERSISTENT_ACLS)
- && drive_type () != DRIVE_UNKNOWN);
-}
-
inline bool
-path_conv::is_samba ()
+path_conv::isgood_inode (__ino64_t ino) const
{
- /* Something weird happens on Samba up to version 3.0.21c, which is
- fixed in 3.0.22. FileIdBothDirectoryInformation seems to work
- nicely, but only up to the 128th entry in the directory. After
- reaching this entry, the next call to
- NtQueryDirectoryFile(FileIdBothDirectoryInformation) returns
- STATUS_INVAILD_LEVEL. Why should we care, we can just switch to
- FileBothDirectoryInformation, isn't it? Nope! The next call to
- NtQueryDirectoryFile(FileBothDirectoryInformation) actually returns
- STATUS_NO_MORE_FILES, regardless how many files are left unread in
- the directory. This does not happen when using
- FileBothDirectoryInformation right from the start. In that case we
- can read the whole directory unmolested. So we have to excempt
- Samba from the usage of FileIdBothDirectoryInformation entirely,
- even though Samba returns valid File IDs. */
- return drive_type () == DRIVE_REMOTE
- && (fs_flags () == FS_IS_SAMBA
- || fs_flags () == FS_IS_SAMBA_WITH_QUOTA);
+ /* We can't trust remote inode numbers of only 32 bit. That means,
+ all remote inode numbers when running under NT4, as well as remote NT4
+ NTFS, as well as shares of Samba version < 3.0.
+ The known exception are SFU NFS shares, which return the valid 32 bit
+ inode number from the remote file system unchanged. */
+ return hasgood_inode () && (ino > UINT32_MAX || !isremote () || fs_is_nfs ());
}
int __stdcall
@@ -248,8 +217,9 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
NTSTATUS status;
IO_STATUS_BLOCK io;
/* The entries potentially contain a name of MAX_PATH wide characters. */
- DWORD fvi_size = 2 * CYG_MAX_PATH + sizeof (FILE_FS_VOLUME_INFORMATION);
- DWORD fai_size = 2 * CYG_MAX_PATH + sizeof (FILE_ALL_INFORMATION);
+ const DWORD fvi_size = 2 * CYG_MAX_PATH
+ + sizeof (FILE_FS_VOLUME_INFORMATION);
+ const DWORD fai_size = 2 * CYG_MAX_PATH + sizeof (FILE_ALL_INFORMATION);
PFILE_FS_VOLUME_INFORMATION pfvi = (PFILE_FS_VOLUME_INFORMATION)
alloca (fvi_size);
@@ -278,11 +248,9 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
*(FILETIME *) &pfai->BasicInformation.LastAccessTime,
*(FILETIME *) &pfai->BasicInformation.LastWriteTime,
pfvi->VolumeSerialNumber,
- pfai->StandardInformation.EndOfFile.HighPart,
- pfai->StandardInformation.EndOfFile.LowPart,
+ pfai->StandardInformation.EndOfFile.QuadPart,
pfai->StandardInformation.AllocationSize.QuadPart,
- pfai->InternalInformation.FileId.HighPart,
- pfai->InternalInformation.FileId.LowPart,
+ pfai->InternalInformation.FileId.QuadPart,
pfai->StandardInformation.NumberOfLinks,
pfai->BasicInformation.FileAttributes);
}
@@ -313,11 +281,11 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
local.ftLastAccessTime,
local.ftLastWriteTime,
local.dwVolumeSerialNumber,
- local.nFileSizeHigh,
- local.nFileSizeLow,
+ (ULONGLONG) local.nFileSizeHigh << 32
+ | local.nFileSizeLow,
-1LL,
- local.nFileIndexHigh,
- local.nFileIndexLow,
+ (ULONGLONG) local.nFileIndexHigh << 32
+ | local.nFileIndexLow,
local.nNumberOfLinks,
local.dwFileAttributes);
}
@@ -344,18 +312,17 @@ fhandler_base::fstat_by_name (struct __stat64 *buf)
local.ftLastAccessTime,
local.ftLastWriteTime,
pc.volser (),
- local.nFileSizeHigh,
- local.nFileSizeLow,
+ (ULONGLONG) local.nFileSizeHigh << 32
+ | local.nFileSizeLow,
-1LL,
- 0,
- 0,
+ 0ULL,
1,
local.dwFileAttributes);
}
else if (pc.isdir ())
{
FILETIME ft = {};
- res = fstat_helper (buf, ft, ft, ft, pc.volser (), 0, 0, -1LL, 0, 0, 1,
+ res = fstat_helper (buf, ft, ft, ft, pc.volser (), 0ULL, -1LL, 0ULL, 1,
FILE_ATTRIBUTE_DIRECTORY);
}
else
@@ -433,11 +400,9 @@ fhandler_base::fstat_helper (struct __stat64 *buf,
FILETIME ftLastAccessTime,
FILETIME ftLastWriteTime,
DWORD dwVolumeSerialNumber,
- DWORD nFileSizeHigh,
- DWORD nFileSizeLow,
+ ULONGLONG nFileSize,
LONGLONG nAllocSize,
- DWORD nFileIndexHigh,
- DWORD nFileIndexLow,
+ ULONGLONG nFileIndex,
DWORD nNumberOfLinks,
DWORD dwFileAttributes)
{
@@ -448,7 +413,7 @@ fhandler_base::fstat_helper (struct __stat64 *buf,
to_timestruc_t (&ftLastWriteTime, &buf->st_mtim);
to_timestruc_t (&ftChangeTime, &buf->st_ctim);
buf->st_dev = dwVolumeSerialNumber ?: pc.volser ();
- buf->st_size = ((_off64_t) nFileSizeHigh << 32) + nFileSizeLow;
+ buf->st_size = (_off64_t) nFileSize;
/* The number of links to a directory includes the
number of subdirectories in the directory, since all
those subdirectories point to it.
@@ -457,12 +422,9 @@ fhandler_base::fstat_helper (struct __stat64 *buf,
let's try it with `1' as link count. */
buf->st_nlink = pc.ndisk_links (nNumberOfLinks);
- /* We can't trust remote inode numbers of only 32 bit. That means,
- all remote inode numbers when running under NT4, as well as remote NT4
- NTFS, as well as shares of Samba version < 3.0. */
- if (pc.hasgood_inode () && (nFileIndexHigh || !pc.isremote ()))
- buf->st_ino = (((__ino64_t) nFileIndexHigh) << 32)
- | (__ino64_t) nFileIndexLow;
+ /* Enforce namehash as inode number on untrusted file systems. */
+ if (pc.isgood_inode (nFileIndex))
+ buf->st_ino = (__ino64_t) nFileIndex;
else
buf->st_ino = get_namehash ();
@@ -1586,7 +1548,23 @@ fhandler_disk_file::opendir ()
if (pc.hasgood_inode ())
{
dir->__flags |= dirent_set_d_ino;
- if (wincap.has_fileid_dirinfo () && !pc.is_samba ())
+ /* Something weird happens on Samba up to version 3.0.21c,
+ which is fixed in 3.0.22. FileIdBothDirectoryInformation
+ seems to work nicely, but only up to the 128th entry in
+ the directory. After reaching this entry, the next call
+ to NtQueryDirectoryFile(FileIdBothDirectoryInformation)
+ returns STATUS_INVALID_LEVEL. Why should we care, we can
+ just switch to FileBothDirectoryInformation, isn't it?
+ Nope! The next call to
+ NtQueryDirectoryFile(FileBothDirectoryInformation)
+ actually returns STATUS_NO_MORE_FILES, regardless how
+ many files are left unread in the directory. This does
+ not happen when using FileBothDirectoryInformation right
+ from the start. In that case we can read the whole
+ directory unmolested. So we have to excempt Samba from
+ the usage of FileIdBothDirectoryInformation entirely,
+ even though Samba returns valid File IDs. */
+ if (wincap.has_fileid_dirinfo () && !pc.fs_is_samba ())
dir->__flags |= dirent_get_d_ino;
}
}
@@ -1736,7 +1714,8 @@ fhandler_disk_file::readdir (DIR *dir, dirent *de)
back to using a standard directory query in this case and note
this case using the dirent_get_d_ino flag. */
if (status == STATUS_INVALID_LEVEL
- || status == STATUS_INVALID_PARAMETER)
+ || status == STATUS_INVALID_PARAMETER
+ || status == STATUS_INVALID_INFO_CLASS)
dir->__flags &= ~dirent_get_d_ino;
}
if (!(dir->__flags & dirent_get_d_ino))
@@ -1788,10 +1767,8 @@ fhandler_disk_file::readdir (DIR *dir, dirent *de)
CloseHandle (hdl);
}
}
- /* We can't trust remote inode numbers of only 32 bit. That means,
- all remote inode numbers when running under NT4, as well as
- remote NT4 NTFS, as well as shares of Samba version < 3.0. */
- if (de->d_ino <= UINT32_MAX && pc.isremote ())
+ /* Enforce namehash as inode number on untrusted file systems. */
+ if (!pc.isgood_inode (de->d_ino))
{
dir->__flags &= ~dirent_set_d_ino;
de->d_ino = 0;
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index 6cdc2ce32..265f308f6 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -8,6 +8,7 @@
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
+#define STATUS_INVALID_INFO_CLASS ((NTSTATUS) 0xc0000003)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xc0000004)
#define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xc000000d)
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS) 0xc0000023)
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 44ceb6c1c..a95d311e7 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -423,15 +423,26 @@ fs_info::update (const char *win32_path)
return false;
}
- /* FIXME: Samba by default returns "NTFS" in file system name, but
- * doesn't support Extended Attributes. If there's some fast way to
- * distinguish between samba and real ntfs, it should be implemented
- * here.
- */
- has_ea (!is_remote_drive () && strcmp (fsname, "NTFS") == 0);
+#define FS_IS_SAMBA (FILE_CASE_SENSITIVE_SEARCH \
+ | FILE_CASE_PRESERVED_NAMES \
+ | FILE_PERSISTENT_ACLS)
+#define FS_IS_SAMBA_WITH_QUOTA \
+ (FILE_CASE_SENSITIVE_SEARCH \
+ | FILE_CASE_PRESERVED_NAMES \
+ | FILE_PERSISTENT_ACLS \
+ | FILE_VOLUME_QUOTAS)
+ is_fat (strncasematch (fsname, "FAT", 3));
+ is_samba (strcmp (fsname, "NTFS") == 0 && is_remote_drive ()
+ && (flags () == FS_IS_SAMBA || flags () == FS_IS_SAMBA_WITH_QUOTA));
+ is_ntfs (strcmp (fsname, "NTFS") == 0 && !is_samba ());
+ is_nfs (strcmp (fsname, "NFS") == 0);
+
+ has_ea (is_ntfs ());
has_acls ((flags () & FS_PERSISTENT_ACLS)
&& (allow_smbntsec || !is_remote_drive ()));
- is_fat (strncasematch (fsname, "FAT", 3));
+ hasgood_inode (((flags () & FILE_PERSISTENT_ACLS)
+ && drive_type () != DRIVE_UNKNOWN)
+ || is_nfs ());
/* Known file systems with buggy open calls. Further explanation
in fhandler.cc (fhandler_disk_file::open). */
has_buggy_open (!strcmp (fsname, "SUNWNFS"));
diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h
index 233dd15b8..d432e70d3 100644
--- a/winsup/cygwin/path.h
+++ b/winsup/cygwin/path.h
@@ -92,8 +92,12 @@ struct fs_info
unsigned has_buggy_open : 1;
unsigned has_ea : 1;
unsigned has_acls : 1;
- unsigned is_fat : 1;
+ unsigned hasgood_inode : 1;
unsigned drive_type : 3;
+ unsigned is_fat : 1;
+ unsigned is_ntfs : 1;
+ unsigned is_samba : 1;
+ unsigned is_nfs : 1;
} status;
public:
void clear ()
@@ -104,18 +108,26 @@ struct fs_info
has_buggy_open (false);
has_ea (false);
has_acls (false);
- is_fat (false);
+ hasgood_inode (false);
drive_type (false);
+ is_fat (false);
+ is_ntfs (false);
+ is_samba (false);
+ is_nfs (false);
}
inline DWORD& flags () {return status.flags;};
inline DWORD& serial () {return status.serial;};
IMPLEMENT_STATUS_FLAG (bool, is_remote_drive)
IMPLEMENT_STATUS_FLAG (bool, has_buggy_open)
- IMPLEMENT_STATUS_FLAG (bool, is_fat)
IMPLEMENT_STATUS_FLAG (bool, has_ea)
IMPLEMENT_STATUS_FLAG (bool, has_acls)
+ IMPLEMENT_STATUS_FLAG (bool, hasgood_inode)
IMPLEMENT_STATUS_FLAG (DWORD, drive_type)
+ IMPLEMENT_STATUS_FLAG (bool, is_fat)
+ IMPLEMENT_STATUS_FLAG (bool, is_ntfs)
+ IMPLEMENT_STATUS_FLAG (bool, is_samba)
+ IMPLEMENT_STATUS_FLAG (bool, is_nfs)
bool update (const char *);
};
@@ -133,13 +145,13 @@ class path_conv
device dev;
bool case_clash;
- bool isremote () {return fs.is_remote_drive ();}
- int has_acls () const {return fs.has_acls (); }
+ bool isremote () const {return fs.is_remote_drive ();}
+ bool has_acls () const {return fs.has_acls (); }
+ bool hasgood_inode () const {return fs.hasgood_inode (); }
+ bool isgood_inode (__ino64_t ino) const;
int has_symlinks () const {return path_flags & PATH_HAS_SYMLINKS;}
- bool hasgood_inode (); /* Implemented in fhandler_disk_file.cc */
- bool is_samba (); /* Implemented in fhandler_disk_file.cc */
int has_buggy_open () const {return fs.has_buggy_open ();}
- bool isencoded () {return path_flags & PATH_ENC;}
+ bool isencoded () const {return path_flags & PATH_ENC;}
int binmode () const
{
if (path_flags & PATH_BINARY)
@@ -222,14 +234,17 @@ class path_conv
operator DWORD &() {return fileattr;}
operator int () {return fileattr; }
char operator [](int i) const {return path[i];}
- DWORD get_devn () {return dev.devn;}
- short get_unitn () {return dev.minor;}
- DWORD file_attributes () {return fileattr;}
+ DWORD get_devn () const {return dev.devn;}
+ short get_unitn () const {return dev.minor;}
+ DWORD file_attributes () const {return fileattr;}
void file_attributes (DWORD new_attr) {fileattr = new_attr;}
- DWORD drive_type () {return fs.drive_type ();}
+ DWORD drive_type () const {return fs.drive_type ();}
DWORD fs_flags () {return fs.flags ();}
- bool fs_has_ea () {return fs.has_ea ();}
- bool fs_is_fat () {return fs.is_fat ();}
+ bool fs_has_ea () const {return fs.has_ea ();}
+ 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 ();}
+ bool fs_is_nfs () const {return fs.is_nfs ();}
void set_path (const char *p) {strcpy (path, p);}
DWORD volser () { return fs.serial (); }
void fillin (HANDLE h);