* 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-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.
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)
return -1;
}
written:
- has_changed (data_changed);
return bytes_written;
}
query_write_attributes = 4
};
-enum change_state {
- no_change = 0,
- inode_changed = 1,
- data_changed = 2
-};
-
class fhandler_base
{
friend class dtable;
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;
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);
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)
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 ());
}
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);
{
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);
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
{
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)
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
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;
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);
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
res = 0;
/* Set ctime on success. */
- if (!res)
- has_changed (inode_changed);
+ if (!res && !wincap.is_winnt ())
+ has_changed (true);
if (oret)
close ();
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 ();
}
}
- /* Set ctime on success. */
- if (!res && cmd == SETACL)
- has_changed (inode_changed);
-
if (oret)
close ();
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;
}
success:
- /* Set ctime on success. */
- has_changed (inode_changed);
close ();
if (!allow_winsymlinks && pc.is_lnk_symlink ())
SetFileAttributes (newpc, (DWORD) pc
__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;
}
&& !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:
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 ();
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
{
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,
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);
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);