* autoload.cc (NtQueryVolumeInformationFile): Add.

* fhandler.cc (fhandler_base::raw_write): Don't touch has_changed flag.
	* fhandler.h (enum change_state): Remove.
	(fhandler_base::status): Revert has_changed to a simple bit.
	(fhandler_base::fstat_helper): Add nAllocSize parameter.  Rename
	ftCreationTime to ftChangeTime.
	* fhandler_disk_file.cc:
	Call fstat_helper with additional
	allocation size throughout.
	(fhandler_base::fstat_by_handle): Use NT native functions to get
	full file information on NT.  Call fstat_helper with LastWriteTime
	as ctime, if ChangeTime is not available.
	(fhandler_base::fstat_by_name): Call fstat_helper with LastWriteTime
	as ctime.
	(fhandler_base::fstat_helper): Add comment. Drop special FAT
	handling since it's useless. Use nAllocSize for st_blocks if available.
	(fhandler_disk_file::touch_ctime): Only touch LastWriteTime.
	(fhandler_disk_file::fchmod): Set has_changed on 9x only.
	(fhandler_disk_file::fchown): Don't set has_changed.
	(fhandler_disk_file::facl): Ditto.
	(fhandler_disk_file::ftruncate): Ditto.
	(fhandler_disk_file::link): Set has_changed on 9x only and on original
	file only.
	(fhandler_base::open_fs): Don't set has_changed in O_TRUNC case.
	* ntdll.h (FILE_BASIC_INFORMATION): Define.
	(FILE_STANDARD_INFORMATION): Define.
	(FILE_INTERNAL_INFORMATION): Define.
	(FILE_EA_INFORMATION): Define.
	(FILE_ACCESS_INFORMATION): Define.
	(FILE_POSITION_INFORMATION): Define.
	(FILE_MODE_INFORMATION): Define.
	(FILE_ALIGNMENT_INFORMATION): Define.
	(FILE_NAME_INFORMATION): Don't define with arbitrary FileName size.
	(FILE_ALL_INFORMATION): Define.
	(FILE_INFORMATION_CLASS): Add FileAllInformation.
	(FILE_FS_VOLUME_INFORMATION): Define.
	(FS_INFORMATION_CLASS): Define.
	(NtQueryVolumeInformationFile): Define.
This commit is contained in:
Corinna Vinschen 2005-04-12 14:26:31 +00:00
parent 576d455f5f
commit 2a24463d0b
6 changed files with 202 additions and 66 deletions

View File

@ -1,3 +1,44 @@
2005-04-12 Corinna Vinschen <corinna@vinschen.de>
* autoload.cc (NtQueryVolumeInformationFile): Add.
* fhandler.cc (fhandler_base::raw_write): Don't touch has_changed flag.
* fhandler.h (enum change_state): Remove.
(fhandler_base::status): Revert has_changed to a simple bit.
(fhandler_base::fstat_helper): Add nAllocSize parameter. Rename
ftCreationTime to ftChangeTime.
* fhandler_disk_file.cc:
Call fstat_helper with additional
allocation size throughout.
(fhandler_base::fstat_by_handle): Use NT native functions to get
full file information on NT. Call fstat_helper with LastWriteTime
as ctime, if ChangeTime is not available.
(fhandler_base::fstat_by_name): Call fstat_helper with LastWriteTime
as ctime.
(fhandler_base::fstat_helper): Add comment. Drop special FAT
handling since it's useless. Use nAllocSize for st_blocks if available.
(fhandler_disk_file::touch_ctime): Only touch LastWriteTime.
(fhandler_disk_file::fchmod): Set has_changed on 9x only.
(fhandler_disk_file::fchown): Don't set has_changed.
(fhandler_disk_file::facl): Ditto.
(fhandler_disk_file::ftruncate): Ditto.
(fhandler_disk_file::link): Set has_changed on 9x only and on original
file only.
(fhandler_base::open_fs): Don't set has_changed in O_TRUNC case.
* ntdll.h (FILE_BASIC_INFORMATION): Define.
(FILE_STANDARD_INFORMATION): Define.
(FILE_INTERNAL_INFORMATION): Define.
(FILE_EA_INFORMATION): Define.
(FILE_ACCESS_INFORMATION): Define.
(FILE_POSITION_INFORMATION): Define.
(FILE_MODE_INFORMATION): Define.
(FILE_ALIGNMENT_INFORMATION): Define.
(FILE_NAME_INFORMATION): Don't define with arbitrary FileName size.
(FILE_ALL_INFORMATION): Define.
(FILE_INFORMATION_CLASS): Add FileAllInformation.
(FILE_FS_VOLUME_INFORMATION): Define.
(FS_INFORMATION_CLASS): Define.
(NtQueryVolumeInformationFile): Define.
2005-04-11 Corinna Vinschen <corinna@vinschen.de>
Revert previous patch.

View File

@ -394,6 +394,7 @@ LoadDLLfuncEx2 (NtQueryObject, 20, ntdll, 1, 1)
LoadDLLfuncEx (NtQuerySystemInformation, 16, ntdll, 1)
LoadDLLfuncEx (NtQuerySecurityObject, 20, ntdll, 1)
LoadDLLfuncEx (NtQueryVirtualMemory, 24, ntdll, 1)
LoadDLLfuncEx (NtQueryVolumeInformationFile, 20, ntdll, 1)
LoadDLLfuncEx (NtSetSecurityObject, 12, ntdll, 1)
LoadDLLfuncEx (NtUnmapViewOfSection, 8, ntdll, 1)
LoadDLLfuncEx (RtlInitUnicodeString, 8, ntdll, 1)

View File

@ -295,7 +295,6 @@ fhandler_base::raw_write (const void *ptr, size_t len)
return -1;
}
written:
has_changed (data_changed);
return bytes_written;
}

View File

@ -78,12 +78,6 @@ enum query_state {
query_write_attributes = 4
};
enum change_state {
no_change = 0,
inode_changed = 1,
data_changed = 2
};
class fhandler_base
{
friend class dtable;
@ -106,14 +100,14 @@ class fhandler_base
read or write access */
unsigned close_on_exec : 1; /* close-on-exec */
unsigned need_fork_fixup : 1; /* Set if need to fixup after fork. */
unsigned has_changed : 2; /* Flag used to set ctime on close. */
unsigned has_changed : 1; /* Flag used to set ctime on close. */
public:
status_flags () :
rbinary (0), rbinset (0), wbinary (0), wbinset (0), nohandle (0),
uninterruptible_io (0), append_mode (0), did_lseek (0),
query_open (no_query), close_on_exec (0), need_fork_fixup (0),
has_changed (no_change)
has_changed (0)
{}
} status, open_status;
@ -194,7 +188,7 @@ class fhandler_base
IMPLEMENT_STATUS_FLAG (query_state, query_open)
IMPLEMENT_STATUS_FLAG (bool, close_on_exec)
IMPLEMENT_STATUS_FLAG (bool, need_fork_fixup)
IMPLEMENT_STATUS_FLAG (change_state, has_changed)
IMPLEMENT_STATUS_FLAG (bool, has_changed)
int get_default_fmode (int flags);
@ -264,12 +258,13 @@ class fhandler_base
virtual int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2)));
int __stdcall fstat_fs (struct __stat64 *buf) __attribute__ ((regparm (2)));
int __stdcall fstat_helper (struct __stat64 *buf,
FILETIME ftCreationTime,
FILETIME ftChangeTime,
FILETIME ftLastAccessTime,
FILETIME ftLastWriteTime,
DWORD dwVolumeSerialNumber,
DWORD nFileSizeHigh,
DWORD nFileSizeLow,
LONGLONG nAllocSize,
DWORD nFileIndexHigh,
DWORD nFileIndexLow,
DWORD nNumberOfLinks)

View File

@ -100,6 +100,51 @@ int __stdcall
fhandler_base::fstat_by_handle (struct __stat64 *buf)
{
BY_HANDLE_FILE_INFORMATION local;
if (wincap.is_winnt ())
{
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);
PFILE_FS_VOLUME_INFORMATION pfvi = (PFILE_FS_VOLUME_INFORMATION)
alloca (fvi_size);
PFILE_ALL_INFORMATION pfai = (PFILE_ALL_INFORMATION) alloca (fai_size);
status = NtQueryVolumeInformationFile (get_handle (), &io, pfvi, fvi_size,
FileFsVolumeInformation);
if (!NT_SUCCESS (status))
{
debug_printf ("%u = NtQueryVolumeInformationFile)",
RtlNtStatusToDosError (status));
pfvi->VolumeSerialNumber = 0; /* Set to pc.volser () in helper. */
}
status = NtQueryInformationFile (get_handle (), &io, pfai, fai_size,
FileAllInformation);
if (NT_SUCCESS (status))
/* If the change time is 0, it's a file system which doesn't
support a change timestamp. In that case use the LastWriteTime
entry, as in other calls to fstat_helper. */
return fstat_helper (buf,
pfai->BasicInformation.ChangeTime.QuadPart ?
*(FILETIME *) &pfai->BasicInformation.ChangeTime :
*(FILETIME *) &pfai->BasicInformation.LastWriteTime,
*(FILETIME *) &pfai->BasicInformation.LastAccessTime,
*(FILETIME *) &pfai->BasicInformation.LastWriteTime,
pfvi->VolumeSerialNumber,
pfai->StandardInformation.EndOfFile.HighPart,
pfai->StandardInformation.EndOfFile.LowPart,
pfai->StandardInformation.AllocationSize.QuadPart,
pfai->InternalInformation.IndexNumber.HighPart,
pfai->InternalInformation.IndexNumber.LowPart,
pfai->StandardInformation.NumberOfLinks);
debug_printf ("%u = NtQuerynformationFile)",
RtlNtStatusToDosError (status));
}
BOOL res = GetFileInformationByHandle (get_handle (), &local);
debug_printf ("%d = GetFileInformationByHandle (%s, %d)",
res, get_win32_name (), get_handle ());
@ -111,12 +156,13 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
}
return fstat_helper (buf,
local.ftCreationTime,
local.ftLastWriteTime, /* see fstat_helper comment */
local.ftLastAccessTime,
local.ftLastWriteTime,
local.dwVolumeSerialNumber,
local.nFileSizeHigh,
local.nFileSizeLow,
-1LL,
local.nFileIndexHigh,
local.nFileIndexLow,
local.nNumberOfLinks);
@ -139,12 +185,13 @@ fhandler_base::fstat_by_name (struct __stat64 *buf)
{
FindClose (handle);
res = fstat_helper (buf,
local.ftCreationTime,
local.ftLastWriteTime, /* see fstat_helper comment */
local.ftLastAccessTime,
local.ftLastWriteTime,
pc.volser (),
local.nFileSizeHigh,
local.nFileSizeLow,
-1LL,
0,
0,
1);
@ -152,7 +199,7 @@ fhandler_base::fstat_by_name (struct __stat64 *buf)
else if (pc.isdir ())
{
FILETIME ft = {};
res = fstat_helper (buf, ft, ft, ft, pc.volser (), 0, 0, 0, 0, 1);
res = fstat_helper (buf, ft, ft, ft, pc.volser (), 0, 0, -1LL, 0, 0, 1);
}
else
{
@ -213,14 +260,21 @@ fhandler_base::fstat_fs (struct __stat64 *buf)
return res;
}
/* The ftChangeTime is taken from the NTFS ChangeTime entry, if reading
the file information using NtQueryInformationFile succeeded. If not,
it's faked using the LastWriteTime entry from GetFileInformationByHandle
or FindFirstFile. We're deliberatly not using the creation time anymore
to simplify interaction with native Windows applications which choke on
creation times >= access or write times. */
int __stdcall
fhandler_base::fstat_helper (struct __stat64 *buf,
FILETIME ftCreationTime,
FILETIME ftChangeTime,
FILETIME ftLastAccessTime,
FILETIME ftLastWriteTime,
DWORD dwVolumeSerialNumber,
DWORD nFileSizeHigh,
DWORD nFileSizeLow,
LONGLONG nAllocSize,
DWORD nFileIndexHigh,
DWORD nFileIndexLow,
DWORD nNumberOfLinks)
@ -228,17 +282,9 @@ fhandler_base::fstat_helper (struct __stat64 *buf,
IO_STATUS_BLOCK st;
FILE_COMPRESSION_INFORMATION fci;
/* This is for FAT filesystems, which don't support atime/ctime */
if (ftLastAccessTime.dwLowDateTime == 0
&& ftLastAccessTime.dwHighDateTime == 0)
ftLastAccessTime = ftLastWriteTime;
if (ftCreationTime.dwLowDateTime == 0
&& ftCreationTime.dwHighDateTime == 0)
ftCreationTime = ftLastWriteTime;
to_timestruc_t (&ftLastAccessTime, &buf->st_atim);
to_timestruc_t (&ftLastWriteTime, &buf->st_mtim);
to_timestruc_t (&ftCreationTime, &buf->st_ctim);
to_timestruc_t (&ftChangeTime, &buf->st_ctim);
buf->st_dev = dwVolumeSerialNumber ?: pc.volser ();
buf->st_size = ((_off64_t) nFileSizeHigh << 32) + nFileSizeLow;
/* The number of links to a directory includes the
@ -273,15 +319,20 @@ fhandler_base::fstat_helper (struct __stat64 *buf,
buf->st_blksize = S_BLKSIZE;
/* On compressed and sparsed files, we request the actual amount of bytes
allocated on disk. */
if (pc.has_attribute (FILE_ATTRIBUTE_COMPRESSED | FILE_ATTRIBUTE_SPARSE_FILE)
if (nAllocSize >= 0LL)
/* A successful NtQueryInformationFile returns the allocation size
correctly for compressed and sparse files as well. */
buf->st_blocks = (nAllocSize + S_BLKSIZE - 1) / S_BLKSIZE;
else if (pc.has_attribute (FILE_ATTRIBUTE_COMPRESSED
| FILE_ATTRIBUTE_SPARSE_FILE)
&& get_io_handle ()
&& !NtQueryInformationFile (get_io_handle (), &st, (PVOID) &fci,
sizeof fci, FileCompressionInformation))
/* Otherwise we request the actual amount of bytes allocated for
compressed and sparsed files. */
buf->st_blocks = (fci.CompressedSize.QuadPart + S_BLKSIZE - 1) / S_BLKSIZE;
else
/* Just compute no. of blocks from file size. */
/* Otherwise compute no. of blocks from file size. */
buf->st_blocks = (buf->st_size + S_BLKSIZE - 1) / S_BLKSIZE;
buf->st_mode = 0;
@ -380,6 +431,7 @@ fhandler_base::fstat_helper (struct __stat64 *buf,
int __stdcall
fhandler_disk_file::fstat (struct __stat64 *buf)
{
/* Changing inode data requires setting ctime (only 9x). */
if (has_changed ())
touch_ctime ();
return fstat_fs (buf);
@ -393,11 +445,10 @@ fhandler_disk_file::touch_ctime (void)
GetSystemTimeAsFileTime (&ft);
/* Modification time is touched if the file data has changed as well.
This happens for instance on write() or ftruncate(). */
if (!SetFileTime (get_io_handle (), &ft, NULL,
has_changed () == data_changed ? &ft : NULL))
if (!SetFileTime (get_io_handle (), NULL, NULL, &ft))
debug_printf ("SetFileTime (%s) failed, %E", get_win32_name ());
else
has_changed (no_change);
has_changed (false);
}
int __stdcall
@ -443,8 +494,8 @@ fhandler_disk_file::fchmod (mode_t mode)
res = 0;
/* Set ctime on success. */
if (!res)
has_changed (inode_changed);
if (!res && !wincap.is_winnt ())
has_changed (true);
if (oret)
close ();
@ -476,13 +527,8 @@ fhandler_disk_file::fchown (__uid32_t uid, __gid32_t gid)
attrib |= S_IFDIR;
int res = get_file_attribute (pc.has_acls (), get_io_handle (), pc, &attrib);
if (!res)
{
res = set_file_attribute (pc.has_acls (), get_io_handle (), pc,
uid, gid, attrib);
/* Set ctime on success. */
if (!res)
has_changed (inode_changed);
}
res = set_file_attribute (pc.has_acls (), get_io_handle (), pc,
uid, gid, attrib);
if (oret)
close ();
@ -576,10 +622,6 @@ fhandler_disk_file::facl (int cmd, int nentries, __aclent32_t *aclbufp)
}
}
/* Set ctime on success. */
if (!res && cmd == SETACL)
has_changed (inode_changed);
if (oret)
close ();
@ -626,9 +668,6 @@ fhandler_disk_file::ftruncate (_off64_t length)
res = res_bug;
/* restore original file pointer location */
lseek (prev_loc, SEEK_SET);
/* Set ctime on success. */
if (!res)
has_changed (data_changed);
}
}
return res;
@ -760,8 +799,6 @@ fhandler_disk_file::link (const char *newpath)
}
success:
/* Set ctime on success. */
has_changed (inode_changed);
close ();
if (!allow_winsymlinks && pc.is_lnk_symlink ())
SetFileAttributes (newpc, (DWORD) pc
@ -776,16 +813,14 @@ docopy:
__seterrno ();
return -1;
}
/* Set ctime on success, also on the copy. */
has_changed (inode_changed);
/* Set ctime on success (copy gets it automatically). */
if (!wincap.is_winnt ())
has_changed (true);
close ();
fhandler_disk_file fh (newpc);
fh.query_open (query_write_attributes);
if (fh.open (O_BINARY, 0))
{
fh.has_changed (inode_changed);
fh.close ();
}
fh.close ();
return 0;
}
@ -897,10 +932,6 @@ fhandler_base::open_fs (int flags, mode_t mode)
&& !allow_ntsec && allow_ntea)
set_file_attribute (false, NULL, get_win32_name (), mode);
/* O_TRUNC on existing file requires setting ctime. */
if ((flags & (O_CREAT | O_TRUNC)) == O_TRUNC)
has_changed (data_changed);
set_fs_flags (pc.fs_flags ());
out:
@ -912,7 +943,7 @@ out:
int
fhandler_disk_file::close ()
{
/* Changing file data requires setting ctime. */
/* Changing inode data requires setting ctime (only 9x). */
if (has_changed ())
touch_ctime ();
return close_fs ();

View File

@ -354,11 +354,62 @@ typedef struct _MEMORY_WORKING_SET_LIST
ULONG WorkingSetList[1];
} MEMORY_WORKING_SET_LIST, *PMEMORY_WORKING_SET_LIST;
typedef struct _FILE_NAME_INFORMATION
{
DWORD FileNameLength;
WCHAR FileName[MAX_PATH + 100];
} FILE_NAME_INFORMATION;
typedef struct _FILE_BASIC_INFORMATION {
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
ULONG FileAttributes;
} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
typedef struct _FILE_STANDARD_INFORMATION {
LARGE_INTEGER AllocationSize;
LARGE_INTEGER EndOfFile;
ULONG NumberOfLinks;
BOOLEAN DeletePending;
BOOLEAN Directory;
} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;
typedef struct _FILE_INTERNAL_INFORMATION {
LARGE_INTEGER IndexNumber;
} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION;
typedef struct _FILE_EA_INFORMATION {
ULONG EaSize;
} FILE_EA_INFORMATION, *PFILE_EA_INFORMATION;
typedef struct _FILE_ACCESS_INFORMATION {
ACCESS_MASK AccessFlags;
} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION;
typedef struct _FILE_POSITION_INFORMATION {
LARGE_INTEGER CurrentByteOffset;
} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION;
typedef struct _FILE_MODE_INFORMATION {
ULONG Mode;
} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION;
typedef struct _FILE_ALIGNMENT_INFORMATION {
ULONG AlignmentRequirement;
} FILE_ALIGNMENT_INFORMATION;
typedef struct _FILE_NAME_INFORMATION {
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;
typedef struct _FILE_ALL_INFORMATION {
FILE_BASIC_INFORMATION BasicInformation;
FILE_STANDARD_INFORMATION StandardInformation;
FILE_INTERNAL_INFORMATION InternalInformation;
FILE_EA_INFORMATION EaInformation;
FILE_ACCESS_INFORMATION AccessInformation;
FILE_POSITION_INFORMATION PositionInformation;
FILE_MODE_INFORMATION ModeInformation;
FILE_ALIGNMENT_INFORMATION AlignmentInformation;
FILE_NAME_INFORMATION NameInformation;
} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION;
typedef struct _FILE_PIPE_LOCAL_INFORMATION
{
@ -385,10 +436,25 @@ typedef struct _FILE_COMPRESSION_INFORMATION
typedef enum _FILE_INFORMATION_CLASS
{
FileAllInformation = 18,
FilePipeLocalInformation = 24,
FileCompressionInformation = 28
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
typedef struct _FILE_FS_VOLUME_INFORMATION
{
LARGE_INTEGER VolumeCreationTime;
ULONG VolumeSerialNumber;
ULONG VolumeLabelLength;
BOOLEAN SupportsObjects;
WCHAR VolumeLabel[1];
} FILE_FS_VOLUME_INFORMATION, *PFILE_FS_VOLUME_INFORMATION;
typedef enum _FSINFOCLASS
{
FileFsVolumeInformation = 1
} FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS;
typedef enum _OBJECT_INFORMATION_CLASS
{
ObjectBasicInformation = 0,
@ -420,7 +486,7 @@ extern "C"
NTSTATUS NTAPI NtOpenFile (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,
PIO_STATUS_BLOCK, ULONG, ULONG);
NTSTATUS NTAPI NtOpenSection (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
NTSTATUS NTAPI NtQueryInformationFile (HANDLE, IO_STATUS_BLOCK *, VOID *,
NTSTATUS NTAPI NtQueryInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID,
ULONG, FILE_INFORMATION_CLASS);
NTSTATUS NTAPI NtQueryInformationProcess (HANDLE, PROCESSINFOCLASS,
PVOID, ULONG, PULONG);
@ -432,6 +498,9 @@ extern "C"
PSECURITY_DESCRIPTOR, ULONG, PULONG);
NTSTATUS NTAPI NtQueryVirtualMemory (HANDLE, PVOID, MEMORY_INFORMATION_CLASS,
PVOID, ULONG, PULONG);
NTSTATUS NTAPI NtQueryVolumeInformationFile (HANDLE, IO_STATUS_BLOCK *,
VOID *, ULONG,
FS_INFORMATION_CLASS);
NTSTATUS NTAPI NtSetSecurityObject (HANDLE, SECURITY_INFORMATION,
PSECURITY_DESCRIPTOR);
NTSTATUS NTAPI NtUnmapViewOfSection (HANDLE, PVOID);