This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: fstat st_size on open files on Parallels filesystem is wrong


On Wednesday, April 23 2014, "Corinna Vinschen" wrote to "cygwin at cygwin.com" saying:

> Rather than calling GetFileInformationByHandle, try this
> 
>   #include <winternl.h>
> 
>   [...]
> 
>   NTSTATUS status;
>   IO_STATUS_BLOCK io;
>   FILE_NETWORK_OPEN_INFORMATION fnoi;
>   
>   status = NtQueryInformationFile (file, &io, &fnoi, sizeof fnoi,
>                                        FileNetworkOpenInformation);
>   if (!NT_SUCCESS (status))
>     {
>       fprintf (stderr, "NtQueryInformationFile: 0x%08x\n", status);
>       [...]
>     }
>   printf("%s: NtQueryInformationFile: nFileSize=%" PRIu64 "\n",
>    argv[i], fnoi.EndOfFile.QuadPart);
> 
> Maybe that's really the problem.  If so, either the EndOfFile info
> is wrong, or (more likely) the call to NtQueryInformationFile returns
> with a non-0 status code, which would be interesting to know.  It's
> probably not STATUS_INVALID_PARAMETER, otherwise you probably wouldn't
> have seen a problem at all.
> 
> Replacing the above call with
> 
>   FILE_STANDARD_INFORMATION fsi;
>   status = NtQueryInformationFile (file, &io, &fsi, sizeof fsi,
>                                        FileStandardInformation);
>   [...]
>   printf("%s: NtQueryInformationFile: nFileSize=%" PRIu64 "\n",
>    argv[i], fsi.EndOfFile.QuadPart);
> 
> should then give the correct result.

Okay, looks like FileNetworkOpenInformation is succeeding, but returning a
bad EndOfFile value.

$ ./win32-size-test 'z:\foo'
z:\foo: NtQueryInformationFile(FileNetworkOpenInformation): EndOfFile=0
z:\foo: NtQueryInformationFile(FileStandardInformation): EndOfFile=12

$ gdb --quiet --args ./win32-size-test.exe 'z:\foo'
Reading symbols from /cygdrive/z/Emacs-Modtime/win32-size-test.exe...done.
(gdb) break 82
Breakpoint 1 at 0x100401400: file win32-size-test.c, line 82.
(gdb) run
Starting program: /cygdrive/z/Emacs-Modtime/win32-size-test.exe z:\\foo
[New Thread 10540.0x48dc]
[New Thread 10540.0x39d4]
z:\\foo: NtQueryInformationFile(FileNetworkOpenInformation): EndOfFile=0
z:\\foo: NtQueryInformationFile(FileStandardInformation): EndOfFile=12

Breakpoint 1, main (argc=2, argv=0x22aaf0) at win32-size-test.c:82
82                      if (!CloseHandle(file)) {
(gdb) p fnoi
$1 = {CreationTime = {{LowPart = 1493948928, HighPart = 30367507}, u = {
      LowPart = 1493948928, HighPart = 30367507},
    QuadPart = 130427450920000000}, LastAccessTime = {{LowPart = 1493948928,
      HighPart = 30367507}, u = {LowPart = 1493948928, HighPart = 30367507},
    QuadPart = 130427450920000000}, LastWriteTime = {{LowPart = 1493948928,
      HighPart = 30367507}, u = {LowPart = 1493948928, HighPart = 30367507},
    QuadPart = 130427450920000000}, ChangeTime = {{LowPart = 1493948928,
      HighPart = 30367507}, u = {LowPart = 1493948928, HighPart = 30367507},
    QuadPart = 130427450920000000}, AllocationSize = {{LowPart = 12,
      HighPart = 0}, u = {LowPart = 12, HighPart = 0}, QuadPart = 12},
  EndOfFile = {{LowPart = 0, HighPart = 0}, u = {LowPart = 0, HighPart = 0},
    QuadPart = 0}, FileAttributes = 128}
(gdb) p fsi
$2 = {AllocationSize = {{LowPart = 12, HighPart = 0}, u = {LowPart = 12,
      HighPart = 0}, QuadPart = 12}, EndOfFile = {{LowPart = 12,
      HighPart = 0}, u = {LowPart = 12, HighPart = 0}, QuadPart = 12},
  NumberOfLinks = 1, DeletePending = 0 '\000', Directory = 0 '\000'}

At this point this is looking pretty clearly like a Parallels Tools bug.
I'll report it to them.


> Also, to add handling for the Parallels filesystem to Cygwin, I'd
> need the info printed by the getVolInfo tool from the csih package:
> 
>   $ /usr/lib/csih/getVolInfo /cygdrive/z

$ /usr/lib/csih/getVolInfo.exe /cygdrive/z/
Device Type        : 7
Characteristics    : 10
Volume Name        : <Shared Folders>
Serial Number      : 0
Max Filenamelength : 255
Filesystemname     : <PrlSF>
Flags              : 3
  FILE_CASE_SENSITIVE_SEARCH  : TRUE
  FILE_CASE_PRESERVED_NAMES   : TRUE
  FILE_UNICODE_ON_DISK        : FALSE
  FILE_PERSISTENT_ACLS        : FALSE
  FILE_FILE_COMPRESSION       : FALSE
  FILE_VOLUME_QUOTAS          : FALSE
  FILE_SUPPORTS_SPARSE_FILES  : FALSE
  FILE_SUPPORTS_REPARSE_POINTS: FALSE
  FILE_SUPPORTS_REMOTE_STORAGE: FALSE
  FILE_VOLUME_IS_COMPRESSED   : FALSE
  FILE_SUPPORTS_OBJECT_IDS    : FALSE
  FILE_SUPPORTS_ENCRYPTION    : FALSE
  FILE_NAMED_STREAMS          : FALSE
  FILE_READ_ONLY_VOLUME       : FALSE
  FILE_SEQUENTIAL_WRITE_ONCE  : FALSE
  FILE_SUPPORTS_TRANSACTIONS  : FALSE


Here's my test code.  Compiles with either Cygwin or mingw64 GCC, but not
classic mingw or Visual Studio due to missing headers/declarations.  Link
with -lntdll.

#include <windows.h>
#include <stdio.h>
#include <inttypes.h>
#include <winternl.h>

#if __LP64__
#define PRIuDWORD "u"
#define PRIxDWORD "x"
#else
#define PRIuDWORD "lu"
#define PRIxDWORD "lx"
#endif

static const char* geterr(DWORD err)
{
	static char msg[1024];

	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
		FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, err,
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
		(LPSTR)msg, sizeof(msg), NULL);

	return msg;
}

int main(int argc, char* argv[])
{
	int i;
	int exitstatus = 0;
	for (i = 1; i < argc; i++) {
		HANDLE file;
		DWORD err, bytesWritten;

		NTSTATUS ntstatus;
		IO_STATUS_BLOCK io;
		FILE_NETWORK_OPEN_INFORMATION fnoi;
		FILE_STANDARD_INFORMATION fsi;
  
		file = CreateFileA(argv[i], GENERIC_WRITE, FILE_SHARE_WRITE,
			NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
		if (file == INVALID_HANDLE_VALUE) {
			err = GetLastError();
			fprintf(stderr, "%s: CreateFile: %s (err 0x%08" PRIxDWORD")\n", argv[i],
				geterr(err), err);
			exitstatus++;
			continue;
		}

		if (!WriteFile(file, "Hello world!\n", 12, &bytesWritten, NULL) ||
			bytesWritten != 12) {
			err = GetLastError();
			fprintf(stderr, "%s: WriteFile: %s (err 0x%08" PRIxDWORD ")\n", argv[i],
				geterr(err), err);
			CloseHandle(file);
			exitstatus++;
			continue;
		}

		ntstatus = NtQueryInformationFile (file, &io, &fnoi, sizeof fnoi,
			FileNetworkOpenInformation);
		if (!NT_SUCCESS (ntstatus)) {
			fprintf (stderr, "%s: NtQueryInformationFile(FileNetworkOpenInformation): %s (err 0x%08" PRIxDWORD ")\n",
				argv[i], geterr(ntstatus), ntstatus);
		}
		else {
			printf("%s: NtQueryInformationFile(FileNetworkOpenInformation): EndOfFile=%" PRIu64 "\n",
				argv[i], (uint64_t)fnoi.EndOfFile.QuadPart);
		}

		ntstatus = NtQueryInformationFile (file, &io, &fsi, sizeof fsi,
			FileStandardInformation);
		if (!NT_SUCCESS (ntstatus)) {
			fprintf (stderr, "%s: NtQueryInformationFile(FileStandardInformation): %s (err 0x%08" PRIxDWORD ")\n",
				argv[i], geterr(ntstatus), ntstatus);
		}
		else {
			printf("%s: NtQueryInformationFile(FileStandardInformation): EndOfFile=%" PRIu64 "\n",
				argv[i], (uint64_t)fsi.EndOfFile.QuadPart);
		}


		if (!CloseHandle(file)) {
			err = GetLastError();
			fprintf(stderr, "%s: CloseHandle: %s (err %" PRIxDWORD ")\n", argv[i],
				geterr(err), err);
			exitstatus++;
			continue;
		}
	}
	return exitstatus;
}

-- 
Jonathan Lennox
lennox at cs.columbia.edu

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]