* autoload.cc (LoadFuncEx): Define via new LoadFuncEx2 macro.
(LoadFuncEx2): Adapted from LoadFuncEx.  Provides control of return value for
nonexistent function.
(NtQueryObject): Declare.
(IsDebuggerPresent): Declare via LoadFuncEx2 and always return true if not
available.
* debug.h (being_debugged): Just rely on IsDebuggerPresent return value.
* dtable.cc (handle_to_fn): New function.
(dtable::init_std_file_from_handle): Attempt to derive std handle's name via
handle_to_fn.
(dtable::build_fhandler_from_name): Fill in what we can in path_conv structure
when given a handle and path doesn't exist.
* fhandler.cc (fhandler_base::open): Don't set the file pointer here.  Use
pc->exists () to determine if file exists rather than calling GetFileAttributes
again.
* fhandler.h (fhandler_base::exec_state_isknown): New method.
(fhandler_base::fstat_helper): Add extra arguments to declaration.
(fhandler_base::fstat_by_handle): Declare new method.
(fhandler_base::fstat_by_name): Declare new method.
* fhandler_disk_file (num_entries): Make __stdcall.
(fhandler_base::fstat_by_handle): Define new method.
(fhandler_base::fstat_by_name): Define new method.
(fhandler_base:fstat): Call fstat_by_{handle,name} as appropriate.
(fhandler_disk_file::fstat_helper): Accept extra arguments for filling out stat
structure.  Move handle or name specific stuff to new methods above.
(fhandler_disk_file::open): Use real_path->exists rather than calling
GetFileAttributes again.
* ntdll.h (FILE_NAME_INFORMATION): Define new structure.
(OBJECT_INFORMATION_CLASS): Partially define new enum.
(OBJECT_NAME_INFORMATION): Define new structure.
(NtQueryInformationFile): New declaration.
(NtQueryObject): New declaration.
* path.cc (path_conv::fillin): Define new method.
* path.h (path_conv::fillin): Declare new method.
(path_conv::drive_thpe): Rename from 'get_drive_type'.
(path_conv::volser): Declare new method.
(path_conv::volname): Declare new method.
(path_conv::root_dir): Declare new method.
* syscalls.cc (fstat64): Send real path_conv to fstat as second argument.
			
			
This commit is contained in:
		| @@ -10,7 +10,6 @@ | |||||||
| Cygwin license.  Please consult the file "CYGWIN_LICENSE" for | Cygwin license.  Please consult the file "CYGWIN_LICENSE" for | ||||||
| details. */ | details. */ | ||||||
|  |  | ||||||
|  |  | ||||||
| #ifdef __OUTSIDE_CYGWIN__ | #ifdef __OUTSIDE_CYGWIN__ | ||||||
| #undef __INSIDE_CYGWIN__ | #undef __INSIDE_CYGWIN__ | ||||||
| #else | #else | ||||||
|   | |||||||
| @@ -1,3 +1,48 @@ | |||||||
|  | 2002-05-27  Christopher Faylor  <cgf@redhat.com> | ||||||
|  |  | ||||||
|  | 	* autoload.cc (LoadFuncEx): Define via new LoadFuncEx2 macro. | ||||||
|  | 	(LoadFuncEx2): Adapted from LoadFuncEx.  Provides control of return | ||||||
|  | 	value for nonexistent function. | ||||||
|  | 	(NtQueryObject): Declare. | ||||||
|  | 	(IsDebuggerPresent): Declare via LoadFuncEx2 and always return true if | ||||||
|  | 	not available. | ||||||
|  | 	* debug.h (being_debugged): Just rely on IsDebuggerPresent return | ||||||
|  | 	value. | ||||||
|  | 	* dtable.cc (handle_to_fn): New function. | ||||||
|  | 	(dtable::init_std_file_from_handle): Attempt to derive std handle's | ||||||
|  | 	name via handle_to_fn. | ||||||
|  | 	(dtable::build_fhandler_from_name): Fill in what we can in path_conv | ||||||
|  | 	structure when given a handle and path doesn't exist. | ||||||
|  | 	* fhandler.cc (fhandler_base::open): Don't set the file pointer here. | ||||||
|  | 	Use pc->exists () to determine if file exists rather than calling | ||||||
|  | 	GetFileAttributes again. | ||||||
|  | 	* fhandler.h (fhandler_base::exec_state_isknown): New method. | ||||||
|  | 	(fhandler_base::fstat_helper): Add extra arguments to declaration. | ||||||
|  | 	(fhandler_base::fstat_by_handle): Declare new method. | ||||||
|  | 	(fhandler_base::fstat_by_name): Declare new method. | ||||||
|  | 	* fhandler_disk_file (num_entries): Make __stdcall. | ||||||
|  | 	(fhandler_base::fstat_by_handle): Define new method. | ||||||
|  | 	(fhandler_base::fstat_by_name): Define new method. | ||||||
|  | 	(fhandler_base:fstat): Call fstat_by_{handle,name} as appropriate. | ||||||
|  | 	(fhandler_disk_file::fstat_helper): Accept extra arguments for filling | ||||||
|  | 	out stat structure.  Move handle or name specific stuff to new methods | ||||||
|  | 	above. | ||||||
|  | 	(fhandler_disk_file::open): Use real_path->exists rather than calling | ||||||
|  | 	GetFileAttributes again. | ||||||
|  | 	* ntdll.h (FILE_NAME_INFORMATION): Define new structure. | ||||||
|  | 	(OBJECT_INFORMATION_CLASS): Partially define new enum. | ||||||
|  | 	(OBJECT_NAME_INFORMATION): Define new structure. | ||||||
|  | 	(NtQueryInformationFile): New declaration. | ||||||
|  | 	(NtQueryObject): New declaration. | ||||||
|  | 	* path.cc (path_conv::fillin): Define new method. | ||||||
|  | 	* path.h (path_conv::fillin): Declare new method. | ||||||
|  | 	(path_conv::drive_thpe): Rename from 'get_drive_type'. | ||||||
|  | 	(path_conv::volser): Declare new method. | ||||||
|  | 	(path_conv::volname): Declare new method. | ||||||
|  | 	(path_conv::root_dir): Declare new method. | ||||||
|  | 	* syscalls.cc (fstat64): Send real path_conv to fstat as second | ||||||
|  | 	argument. | ||||||
|  |  | ||||||
| 2002-05-24  Pierre Humblet <pierre.humblet@ieee.org> | 2002-05-24  Pierre Humblet <pierre.humblet@ieee.org> | ||||||
|  |  | ||||||
| 	* security.cc (lsa2str): New function. | 	* security.cc (lsa2str): New function. | ||||||
|   | |||||||
| @@ -72,9 +72,10 @@ details. */ | |||||||
| /* Standard DLL load macro.  Invokes a fatal warning if the function isn't | /* Standard DLL load macro.  Invokes a fatal warning if the function isn't | ||||||
|    found. */ |    found. */ | ||||||
| #define LoadDLLfunc(name, n, dllname) LoadDLLfuncEx (name, n, dllname, 0) | #define LoadDLLfunc(name, n, dllname) LoadDLLfuncEx (name, n, dllname, 0) | ||||||
|  | #define LoadDLLfuncEx(name, n, dllname, notimp) LoadDLLfuncEx2(name, n, dllname, notimp, 0) | ||||||
|  |  | ||||||
| /* Main DLL setup stuff. */ | /* Main DLL setup stuff. */ | ||||||
| #define LoadDLLfuncEx(name, n, dllname, notimp) \ | #define LoadDLLfuncEx2(name, n, dllname, notimp, err) \ | ||||||
|   LoadDLLprime (dllname, dll_func_load)			\ |   LoadDLLprime (dllname, dll_func_load)			\ | ||||||
|   __asm__ ("						\n\ |   __asm__ ("						\n\ | ||||||
|   .section	." #dllname "_text,\"wx\"		\n\ |   .section	." #dllname "_text,\"wx\"		\n\ | ||||||
| @@ -86,7 +87,7 @@ _win32_" mangle (name, n) ":				\n\ | |||||||
|   movl		(1f),%eax				\n\ |   movl		(1f),%eax				\n\ | ||||||
|   call		*(%eax)					\n\ |   call		*(%eax)					\n\ | ||||||
| 1:.long		." #dllname "_info			\n\ | 1:.long		." #dllname "_info			\n\ | ||||||
|   .long		" #n "+" #notimp "			\n\ |   .long		(" #n "+" #notimp ") | " #err "<<16	\n\ | ||||||
|   .asciz	\"" #name "\"				\n\ |   .asciz	\"" #name "\"				\n\ | ||||||
|   .text							\n\ |   .text							\n\ | ||||||
| "); | "); | ||||||
| @@ -121,11 +122,14 @@ noload:									\n\ | |||||||
| 	jz	1f		# Nope.					\n\ | 	jz	1f		# Nope.					\n\ | ||||||
| 	decl	%eax		# Yes.  This is the # of bytes + 1	\n\ | 	decl	%eax		# Yes.  This is the # of bytes + 1	\n\ | ||||||
| 	popl	%edx		# Caller's caller			\n\ | 	popl	%edx		# Caller's caller			\n\ | ||||||
|  | 	pushl	%eax		# Save for later			\n\ | ||||||
|  | 	xorl	$0xffff,%eax	# Only want lower word			\n\ | ||||||
| 	addl	%eax,%esp	# Pop off bytes				\n\ | 	addl	%eax,%esp	# Pop off bytes				\n\ | ||||||
| 	movl	$127,%eax	# ERROR_PROC_NOT_FOUND			\n\ | 	movl	$127,%eax	# ERROR_PROC_NOT_FOUND			\n\ | ||||||
| 	pushl	%eax		# First argument			\n\ | 	pushl	%eax		# First argument			\n\ | ||||||
| 	call	_SetLastError@4	# Set it				\n\ | 	call	_SetLastError@4	# Set it				\n\ | ||||||
| 	xor	%eax,%eax	# Zero functional return		\n\ | 	popl	%eax		# Get back argument			\n\ | ||||||
|  | 	shrl	$16,%eax	# return value in high order word	\n\ | ||||||
| 	jmp	*%edx		# Return				\n\ | 	jmp	*%edx		# Return				\n\ | ||||||
| 1:									\n\ | 1:									\n\ | ||||||
| 	movl	(%edx),%eax	# Handle value				\n\ | 	movl	(%edx),%eax	# Handle value				\n\ | ||||||
| @@ -373,6 +377,8 @@ LoadDLLfunc (NetUserGetGroups, 28, netapi32) | |||||||
| LoadDLLfunc (NetUserGetInfo, 16, netapi32) | LoadDLLfunc (NetUserGetInfo, 16, netapi32) | ||||||
| LoadDLLfunc (NetWkstaUserGetInfo, 12, netapi32) | LoadDLLfunc (NetWkstaUserGetInfo, 12, netapi32) | ||||||
|  |  | ||||||
|  | LoadDLLfuncEx (NtQueryInformationFile, 20, ntdll, 1) | ||||||
|  | LoadDLLfuncEx2 (NtQueryObject, 20, ntdll, 1, 1) | ||||||
| LoadDLLfuncEx (NtCreateToken, 52, ntdll, 1) | LoadDLLfuncEx (NtCreateToken, 52, ntdll, 1) | ||||||
| LoadDLLfuncEx (NtMapViewOfSection, 40, ntdll, 1) | LoadDLLfuncEx (NtMapViewOfSection, 40, ntdll, 1) | ||||||
| LoadDLLfuncEx (NtOpenFile, 24, ntdll, 1) | LoadDLLfuncEx (NtOpenFile, 24, ntdll, 1) | ||||||
| @@ -483,7 +489,7 @@ LoadDLLfunc (CoCreateInstance, 20, ole32) | |||||||
| LoadDLLfuncEx (CancelIo, 4, kernel32, 1) | LoadDLLfuncEx (CancelIo, 4, kernel32, 1) | ||||||
| LoadDLLfuncEx (CreateHardLinkA, 12, kernel32, 1) | LoadDLLfuncEx (CreateHardLinkA, 12, kernel32, 1) | ||||||
| LoadDLLfuncEx (CreateToolhelp32Snapshot, 8, kernel32, 1) | LoadDLLfuncEx (CreateToolhelp32Snapshot, 8, kernel32, 1) | ||||||
| LoadDLLfuncEx (IsDebuggerPresent, 0, kernel32, 1) | LoadDLLfuncEx2 (IsDebuggerPresent, 0, kernel32, 1, 1) | ||||||
| LoadDLLfuncEx (Process32First, 8, kernel32, 1) | LoadDLLfuncEx (Process32First, 8, kernel32, 1) | ||||||
| LoadDLLfuncEx (Process32Next, 8, kernel32, 1) | LoadDLLfuncEx (Process32Next, 8, kernel32, 1) | ||||||
| LoadDLLfuncEx (SignalObjectAndWait, 16, kernel32, 1) | LoadDLLfuncEx (SignalObjectAndWait, 16, kernel32, 1) | ||||||
|   | |||||||
| @@ -10,7 +10,6 @@ | |||||||
| Cygwin license.  Please consult the file "CYGWIN_LICENSE" for | Cygwin license.  Please consult the file "CYGWIN_LICENSE" for | ||||||
| details. */ | details. */ | ||||||
|  |  | ||||||
|  |  | ||||||
| #ifdef __OUTSIDE_CYGWIN__ | #ifdef __OUTSIDE_CYGWIN__ | ||||||
| #undef __INSIDE_CYGWIN__ | #undef __INSIDE_CYGWIN__ | ||||||
| #else | #else | ||||||
|   | |||||||
| @@ -29,7 +29,7 @@ DWORD __stdcall WFMO (DWORD, CONST HANDLE *, BOOL, DWORD) __attribute__ ((regpar | |||||||
| #define _DEBUG_H_ | #define _DEBUG_H_ | ||||||
|  |  | ||||||
| #define being_debugged() \ | #define being_debugged() \ | ||||||
|   (IsDebuggerPresent () || GetLastError () == ERROR_PROC_NOT_FOUND) |   (IsDebuggerPresent () /* || GetLastError () == ERROR_PROC_NOT_FOUND*/) | ||||||
|  |  | ||||||
| void threadname_init (); | void threadname_init (); | ||||||
| HANDLE __stdcall makethread (LPTHREAD_START_ROUTINE, LPVOID, DWORD, const char *) __attribute__ ((regparm(3))); | HANDLE __stdcall makethread (LPTHREAD_START_ROUTINE, LPVOID, DWORD, const char *) __attribute__ ((regparm(3))); | ||||||
|   | |||||||
| @@ -19,6 +19,8 @@ details. */ | |||||||
| #include <fcntl.h> | #include <fcntl.h> | ||||||
| #include <sys/cygwin.h> | #include <sys/cygwin.h> | ||||||
| #include <assert.h> | #include <assert.h> | ||||||
|  | #include <ntdef.h> | ||||||
|  | #include <winnls.h> | ||||||
|  |  | ||||||
| #define USE_SYS_TYPES_FD_SET | #define USE_SYS_TYPES_FD_SET | ||||||
| #include <winsock.h> | #include <winsock.h> | ||||||
| @@ -31,10 +33,13 @@ details. */ | |||||||
| #include "path.h" | #include "path.h" | ||||||
| #include "dtable.h" | #include "dtable.h" | ||||||
| #include "cygheap.h" | #include "cygheap.h" | ||||||
|  | #include "ntdll.h" | ||||||
|  |  | ||||||
| static const NO_COPY DWORD std_consts[] = {STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, | static const NO_COPY DWORD std_consts[] = {STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, | ||||||
| 					   STD_ERROR_HANDLE}; | 					   STD_ERROR_HANDLE}; | ||||||
|  |  | ||||||
|  | static char *handle_to_fn (HANDLE, char *); | ||||||
|  |  | ||||||
| /* Set aside space for the table of fds */ | /* Set aside space for the table of fds */ | ||||||
| void | void | ||||||
| dtable_init (void) | dtable_init (void) | ||||||
| @@ -267,7 +272,7 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle, DWORD myaccess) | |||||||
|   else if (GetCommState (handle, &dcb)) |   else if (GetCommState (handle, &dcb)) | ||||||
|     name = "/dev/ttyS0"; // FIXME - determine correct device |     name = "/dev/ttyS0"; // FIXME - determine correct device | ||||||
|   else |   else | ||||||
|     name = "unknown disk file"; |     name = handle_to_fn (handle, (char *) alloca (MAX_PATH + 100)); | ||||||
|  |  | ||||||
|   path_conv pc; |   path_conv pc; | ||||||
|   build_fhandler_from_name (fd, name, handle, pc)->init (handle, myaccess, bin); |   build_fhandler_from_name (fd, name, handle, pc)->init (handle, myaccess, bin); | ||||||
| @@ -286,6 +291,9 @@ dtable::build_fhandler_from_name (int fd, const char *name, HANDLE handle, | |||||||
|       return NULL; |       return NULL; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |   if (!pc.exists () && handle) | ||||||
|  |     pc.fillin (handle); | ||||||
|  |  | ||||||
|   fhandler_base *fh = build_fhandler (fd, pc.get_devn (), |   fhandler_base *fh = build_fhandler (fd, pc.get_devn (), | ||||||
| 				      pc.return_and_clear_normalized_path (), | 				      pc.return_and_clear_normalized_path (), | ||||||
| 				      pc, pc.get_unitn ()); | 				      pc, pc.get_unitn ()); | ||||||
| @@ -688,3 +696,84 @@ dtable::vfork_child_fixup () | |||||||
|  |  | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
|  | static char * | ||||||
|  | handle_to_fn (HANDLE h, char *posix_fn) | ||||||
|  | { | ||||||
|  |   IO_STATUS_BLOCK io; | ||||||
|  |   FILE_NAME_INFORMATION ntfn; | ||||||
|  |  | ||||||
|  |   io.Status = 0; | ||||||
|  |   io.Information = 0; | ||||||
|  |  | ||||||
|  |   SetLastError (0); | ||||||
|  |   DWORD res = NtQueryInformationFile (h, &io, &ntfn, sizeof (ntfn), 9); | ||||||
|  |   if (res || GetLastError () == ERROR_PROC_NOT_FOUND) | ||||||
|  |     { | ||||||
|  |       strcpy (posix_fn, "some disk file"); | ||||||
|  |       return posix_fn; | ||||||
|  |     } | ||||||
|  |   ntfn.FileName[ntfn.FileNameLength / sizeof (WCHAR)] = 0; | ||||||
|  |  | ||||||
|  |   char win32_fn[MAX_PATH + 100]; | ||||||
|  |   sys_wcstombs (win32_fn, ntfn.FileName, ntfn.FileNameLength); | ||||||
|  |   cygwin_conv_to_full_posix_path (win32_fn, posix_fn); | ||||||
|  |   return posix_fn; | ||||||
|  | } | ||||||
|  | #else | ||||||
|  | #define DEVICE_PREFIX "\\device\\" | ||||||
|  | #define DEVICE_PREFIX_LEN sizeof(DEVICE_PREFIX) - 1 | ||||||
|  | static char * | ||||||
|  | handle_to_fn (HANDLE h, char *posix_fn) | ||||||
|  | { | ||||||
|  |   OBJECT_NAME_INFORMATION *ntfn; | ||||||
|  |   char fnbuf[32768]; | ||||||
|  |  | ||||||
|  |   memset (fnbuf, 0, sizeof (fnbuf)); | ||||||
|  |   ntfn = (OBJECT_NAME_INFORMATION *) fnbuf; | ||||||
|  |   ntfn->Name.MaximumLength = sizeof (fnbuf); | ||||||
|  |   ntfn->Name.Buffer = (WCHAR *) ntfn + 1; | ||||||
|  |  | ||||||
|  |   DWORD res = NtQueryObject (h, ObjectNameInformation, ntfn, sizeof (fnbuf), NULL); | ||||||
|  |   if (res) | ||||||
|  |     { | ||||||
|  |       strcpy (posix_fn, "some disk file"); | ||||||
|  |       return posix_fn; | ||||||
|  |     } | ||||||
|  |   ntfn->Name.Buffer[ntfn->Name.Length / sizeof (WCHAR)] = 0; | ||||||
|  |  | ||||||
|  |   char win32_fn[MAX_PATH + 100]; | ||||||
|  |   sys_wcstombs (win32_fn, ntfn->Name.Buffer, ntfn->Name.Length); | ||||||
|  |   if (!strncasematch (win32_fn, DEVICE_PREFIX, DEVICE_PREFIX_LEN) | ||||||
|  |       || !QueryDosDevice (NULL, fnbuf, sizeof (fnbuf))) | ||||||
|  |     return strcpy (posix_fn, win32_fn); | ||||||
|  |    | ||||||
|  |   char *p = strchr (win32_fn + DEVICE_PREFIX_LEN, '\\'); | ||||||
|  |   if (!p) | ||||||
|  |     p = strchr (win32_fn + DEVICE_PREFIX_LEN, '\0'); | ||||||
|  |  | ||||||
|  |   int n = p - win32_fn; | ||||||
|  |   char *w32 = win32_fn; | ||||||
|  |   for (char *s = fnbuf; *s; s = strchr (s, '\0') + 1) | ||||||
|  |     { | ||||||
|  |       char device[MAX_PATH + 10]; | ||||||
|  |       device[MAX_PATH + 9] = '\0'; | ||||||
|  |       if (strchr (s, ':') == NULL) | ||||||
|  | 	continue; | ||||||
|  |       if (!QueryDosDevice (s, device, sizeof (device) - 1)) | ||||||
|  | 	continue; | ||||||
|  |       if (!strncasematch (device, win32_fn, n) || | ||||||
|  | 	  (device[n] != '\0' && (device[n] != '\\' || device[n + 1] != ';'))) | ||||||
|  | 	continue; | ||||||
|  |       n = strlen (s); | ||||||
|  |       w32 = p - (n + 1); | ||||||
|  |       memcpy (w32, s, n); | ||||||
|  |       p[-1] = '\\'; | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   cygwin_conv_to_full_posix_path (w32, posix_fn); | ||||||
|  |   return posix_fn; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|   | |||||||
| @@ -309,7 +309,7 @@ fhandler_base::get_default_fmode (int flags) | |||||||
|  |  | ||||||
| /* Open system call handler function. */ | /* Open system call handler function. */ | ||||||
| int | int | ||||||
| fhandler_base::open (path_conv *, int flags, mode_t mode) | fhandler_base::open (path_conv *pc, int flags, mode_t mode) | ||||||
| { | { | ||||||
|   int res = 0; |   int res = 0; | ||||||
|   HANDLE x; |   HANDLE x; | ||||||
| @@ -318,7 +318,7 @@ fhandler_base::open (path_conv *, int flags, mode_t mode) | |||||||
|   int creation_distribution; |   int creation_distribution; | ||||||
|   SECURITY_ATTRIBUTES sa = sec_none; |   SECURITY_ATTRIBUTES sa = sec_none; | ||||||
|  |  | ||||||
|   syscall_printf ("(%s, %p)", get_win32_name (), flags); |   syscall_printf ("(%s, %p) query_open %d", get_win32_name (), flags, get_query_open ()); | ||||||
|  |  | ||||||
|   if (get_win32_name () == NULL) |   if (get_win32_name () == NULL) | ||||||
|     { |     { | ||||||
| @@ -385,7 +385,7 @@ fhandler_base::open (path_conv *, int flags, mode_t mode) | |||||||
|   if (get_query_open () && |   if (get_query_open () && | ||||||
|       isremote () && |       isremote () && | ||||||
|       creation_distribution == OPEN_EXISTING && |       creation_distribution == OPEN_EXISTING && | ||||||
|       GetFileAttributes (get_win32_name ()) == INVALID_FILE_ATTRIBUTES) |       !pc->exists ()) | ||||||
|     { |     { | ||||||
|       set_errno (ENOENT); |       set_errno (ENOENT); | ||||||
|       goto done; |       goto done; | ||||||
| @@ -447,16 +447,6 @@ fhandler_base::open (path_conv *, int flags, mode_t mode) | |||||||
|   set_w_binary (bin); |   set_w_binary (bin); | ||||||
|   syscall_printf ("filemode set to %s", bin ? "binary" : "text"); |   syscall_printf ("filemode set to %s", bin ? "binary" : "text"); | ||||||
|  |  | ||||||
|   if (get_device () != FH_TAPE |  | ||||||
|       && get_device () != FH_FLOPPY |  | ||||||
|       && get_device () != FH_SERIAL) |  | ||||||
|     { |  | ||||||
|       if (flags & O_APPEND) |  | ||||||
| 	SetFilePointer (get_handle(), 0, 0, FILE_END); |  | ||||||
|       else |  | ||||||
| 	SetFilePointer (get_handle(), 0, 0, FILE_BEGIN); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|   res = 1; |   res = 1; | ||||||
|   set_open_status (); |   set_open_status (); | ||||||
| done: | done: | ||||||
|   | |||||||
| @@ -246,13 +246,14 @@ class fhandler_base | |||||||
|   } |   } | ||||||
|   void set_execable_p () { FHSETF (EXECABL); } |   void set_execable_p () { FHSETF (EXECABL); } | ||||||
|   bool dont_care_if_execable () { return FHISSETF (DCEXEC); } |   bool dont_care_if_execable () { return FHISSETF (DCEXEC); } | ||||||
|  |   bool exec_state_isknown () { return FHISSETF (DCEXEC) || FHISSETF (EXECABL); } | ||||||
|  |  | ||||||
|   bool get_append_p () { return FHISSETF (APPEND); } |   bool get_append_p () { return FHISSETF (APPEND); } | ||||||
|   void set_append_p (int val) { FHCONDSETF (val, APPEND); } |   void set_append_p (int val) { FHCONDSETF (val, APPEND); } | ||||||
|   void set_append_p () { FHSETF (APPEND); } |   void set_append_p () { FHSETF (APPEND); } | ||||||
|  |  | ||||||
|   bool get_query_open () { return FHISSETF (QUERYOPEN); } |   bool get_query_open () { return FHISSETF (QUERYOPEN); } | ||||||
|   void set_query_open (int val) { FHCONDSETF (val, QUERYOPEN); } |   void set_query_open (bool val) { FHCONDSETF (val, QUERYOPEN); } | ||||||
|  |  | ||||||
|   bool get_readahead_valid () { return raixget < ralen; } |   bool get_readahead_valid () { return raixget < ralen; } | ||||||
|   int puts_readahead (const char *s, size_t len = (size_t) -1); |   int puts_readahead (const char *s, size_t len = (size_t) -1); | ||||||
| @@ -552,7 +553,18 @@ class fhandler_disk_file: public fhandler_base | |||||||
|   int lock (int, struct flock *); |   int lock (int, struct flock *); | ||||||
|   BOOL is_device () { return FALSE; } |   BOOL is_device () { return FALSE; } | ||||||
|   int __stdcall fstat (struct __stat64 *buf, path_conv *pc) __attribute__ ((regparm (3))); |   int __stdcall fstat (struct __stat64 *buf, path_conv *pc) __attribute__ ((regparm (3))); | ||||||
|   int __stdcall fstat_helper (struct __stat64 *buf) __attribute__ ((regparm (2))); |   int __stdcall fstat_helper (struct __stat64 *buf, path_conv *pc, | ||||||
|  | 			      FILETIME ftCreateionTime, | ||||||
|  | 			      FILETIME ftLastAccessTime, | ||||||
|  | 			      FILETIME ftLastWriteTime, | ||||||
|  | 			      DWORD nFileSizeHigh, | ||||||
|  | 			      DWORD nFileSizeLow, | ||||||
|  | 			      DWORD nFileIndexHigh = 0, | ||||||
|  | 			      DWORD nFileIndexLow = 0, | ||||||
|  | 			      DWORD nNumberOfLinks = 1) | ||||||
|  |     __attribute__ ((regparm (3))); | ||||||
|  |   int __stdcall fstat_by_handle (struct __stat64 *buf, path_conv *pc) __attribute__ ((regparm (3))); | ||||||
|  |   int __stdcall fstat_by_name (struct __stat64 *buf, path_conv *pc) __attribute__ ((regparm (3))); | ||||||
|  |  | ||||||
|   HANDLE mmap (caddr_t *addr, size_t len, DWORD access, int flags, __off64_t off); |   HANDLE mmap (caddr_t *addr, size_t len, DWORD access, int flags, __off64_t off); | ||||||
|   int munmap (HANDLE h, caddr_t addr, size_t len); |   int munmap (HANDLE h, caddr_t addr, size_t len); | ||||||
|   | |||||||
| @@ -31,7 +31,7 @@ details. */ | |||||||
| #define _COMPILING_NEWLIB | #define _COMPILING_NEWLIB | ||||||
| #include <dirent.h> | #include <dirent.h> | ||||||
|  |  | ||||||
| static int | static int __stdcall | ||||||
| num_entries (const char *win32_name) | num_entries (const char *win32_name) | ||||||
| { | { | ||||||
|   WIN32_FIND_DATA buf; |   WIN32_FIND_DATA buf; | ||||||
| @@ -60,7 +60,68 @@ num_entries (const char *win32_name) | |||||||
|   return count; |   return count; | ||||||
| } | } | ||||||
|  |  | ||||||
| int | int __stdcall | ||||||
|  | fhandler_disk_file::fstat_by_handle (struct __stat64 *buf, path_conv *pc) | ||||||
|  | { | ||||||
|  |   int res; | ||||||
|  |   BY_HANDLE_FILE_INFORMATION local; | ||||||
|  |  | ||||||
|  |   /* NT 3.51 seems to have a bug when attempting to get vol serial | ||||||
|  |      numbers.  This loop gets around this. */ | ||||||
|  |   for (int i = 0; i < 2; i++) | ||||||
|  |     { | ||||||
|  |       if (!(res = GetFileInformationByHandle (get_handle (), &local))) | ||||||
|  | 	break; | ||||||
|  |       if (local.dwVolumeSerialNumber && (long) local.dwVolumeSerialNumber != -1) | ||||||
|  | 	break; | ||||||
|  |     } | ||||||
|  |   debug_printf ("%d = GetFileInformationByHandle (%s, %d)", | ||||||
|  | 		res, get_win32_name (), get_handle ()); | ||||||
|  |   if (res == 0) | ||||||
|  |     /* GetFileInformationByHandle will fail if it's given stdin/out/err | ||||||
|  |        or a pipe*/ | ||||||
|  |     { | ||||||
|  |       memset (&local, 0, sizeof (local)); | ||||||
|  |       local.nFileSizeLow = GetFileSize (get_handle (), &local.nFileSizeHigh); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   return fstat_helper (buf, pc, | ||||||
|  | 		       local.ftCreationTime, | ||||||
|  | 		       local.ftLastAccessTime, | ||||||
|  | 		       local.ftLastWriteTime, | ||||||
|  | 		       local.nFileSizeHigh, | ||||||
|  | 		       local.nFileSizeLow, | ||||||
|  | 		       local.nFileIndexHigh, | ||||||
|  | 		       local.nFileIndexLow, | ||||||
|  | 		       local.nNumberOfLinks); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int __stdcall | ||||||
|  | fhandler_disk_file::fstat_by_name (struct __stat64 *buf, path_conv *pc) | ||||||
|  | { | ||||||
|  |   int res; | ||||||
|  |   HANDLE handle; | ||||||
|  |   WIN32_FIND_DATA local; | ||||||
|  |  | ||||||
|  |   if ((handle = FindFirstFile (pc->get_win32 (), &local)) == INVALID_HANDLE_VALUE) | ||||||
|  |     { | ||||||
|  |       __seterrno (); | ||||||
|  |       res = -1; | ||||||
|  |     } | ||||||
|  |   else | ||||||
|  |     { | ||||||
|  |       FindClose (handle); | ||||||
|  |       res = fstat_helper (buf, pc, | ||||||
|  | 			  local.ftCreationTime, | ||||||
|  | 			  local.ftLastAccessTime, | ||||||
|  | 			  local.ftLastWriteTime, | ||||||
|  | 			  local.nFileSizeHigh, | ||||||
|  | 			  local.nFileSizeLow); | ||||||
|  |     } | ||||||
|  |   return res; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int __stdcall | ||||||
| fhandler_disk_file::fstat (struct __stat64 *buf, path_conv *pc) | fhandler_disk_file::fstat (struct __stat64 *buf, path_conv *pc) | ||||||
| { | { | ||||||
|   int res = -1; |   int res = -1; | ||||||
| @@ -68,19 +129,29 @@ fhandler_disk_file::fstat (struct __stat64 *buf, path_conv *pc) | |||||||
|   __uid16_t uid; |   __uid16_t uid; | ||||||
|   __gid16_t gid; |   __gid16_t gid; | ||||||
|   int open_flags = O_RDONLY | O_BINARY | O_DIROPEN; |   int open_flags = O_RDONLY | O_BINARY | O_DIROPEN; | ||||||
|  |   bool query_open_already; | ||||||
|  |  | ||||||
|   if (!pc) |   if (get_io_handle ()) | ||||||
|     return fstat_helper (buf); |     return fstat_by_handle (buf, pc); | ||||||
|  |  | ||||||
|   if ((oret = open (pc, open_flags, 0))) |   /* If we don't care if the file is executable or we already know if it is, | ||||||
|  |      then just do a "query open" as it is apparently much faster. */ | ||||||
|  |   if (pc->exec_state () != dont_know_if_executable) | ||||||
|  |     set_query_open (query_open_already = true); | ||||||
|  |   else | ||||||
|  |     query_open_already = false; | ||||||
|  |  | ||||||
|  |   if (query_open_already && strncasematch (pc->volname (), "FAT", 3)) | ||||||
|  |     oret = 0; | ||||||
|  |   else if ((oret = open (pc, open_flags, 0))) | ||||||
|     /* ok */; |     /* ok */; | ||||||
|   else |   else | ||||||
|     { |     { | ||||||
|       int ntsec_atts = 0; |       int ntsec_atts = 0; | ||||||
|       /* If we couldn't open the file, try a "query open" with no permissions. |       /* If we couldn't open the file, try a "query open" with no permissions. | ||||||
| 	 This will allow us to determine *some* things about the file, at least. */ | 	 This will allow us to determine *some* things about the file, at least. */ | ||||||
|       set_query_open (TRUE); |       set_query_open (true); | ||||||
|       if ((oret = open (pc, open_flags, 0))) |       if (!query_open_already && (oret = open (pc, open_flags, 0))) | ||||||
| 	/* ok */; | 	/* ok */; | ||||||
|       else if (allow_ntsec && pc->has_acls () && get_errno () == EACCES |       else if (allow_ntsec && pc->has_acls () && get_errno () == EACCES | ||||||
| 		&& !get_file_attribute (TRUE, get_win32_name (), &ntsec_atts, &uid, &gid) | 		&& !get_file_attribute (TRUE, get_win32_name (), &ntsec_atts, &uid, &gid) | ||||||
| @@ -96,150 +167,49 @@ fhandler_disk_file::fstat (struct __stat64 *buf, path_conv *pc) | |||||||
| 	  set_file_attribute (TRUE, get_win32_name (), ntsec_atts); | 	  set_file_attribute (TRUE, get_win32_name (), ntsec_atts); | ||||||
| 	} | 	} | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   if (oret) |   if (oret) | ||||||
|     { |     { | ||||||
|       res = fstat_helper (buf); |       res = fstat_by_handle (buf, pc); | ||||||
|       /* The number of links to a directory includes the |  | ||||||
| 	 number of subdirectories in the directory, since all |  | ||||||
| 	 those subdirectories point to it. |  | ||||||
| 	 This is too slow on remote drives, so we do without it and |  | ||||||
| 	 set the number of links to 2. */ |  | ||||||
|       /* Unfortunately the count of 2 confuses `find (1)' command. So |  | ||||||
| 	 let's try it with `1' as link count. */ |  | ||||||
|       if (pc->isdir ()) |  | ||||||
| 	buf->st_nlink = pc->isremote () ? 1 : num_entries (pc->get_win32 ()); |  | ||||||
|       close (); |       close (); | ||||||
|     } |     } | ||||||
|   else if (pc->exists ()) |   else if (pc->exists ()) | ||||||
|     { |     res = fstat_by_name (buf, pc); | ||||||
|       /* Unfortunately, the above open may fail if the file exists, though. |  | ||||||
| 	 So we have to care for this case here, too. */ |  | ||||||
|       WIN32_FIND_DATA wfd; |  | ||||||
|       HANDLE handle; |  | ||||||
|       buf->st_nlink = 1; |  | ||||||
|       if (pc->isdir ()) |  | ||||||
| 	buf->st_nlink = pc->isremote () ? 1 : num_entries (pc->get_win32 ()); |  | ||||||
|       buf->st_dev = FHDEVN (FH_DISK) << 8; |  | ||||||
|       buf->st_ino = hash_path_name (0, pc->get_win32 ()); |  | ||||||
|       if (pc->isdir ()) |  | ||||||
| 	buf->st_mode = S_IFDIR; |  | ||||||
|       else if (pc->issymlink ()) |  | ||||||
| 	buf->st_mode = S_IFLNK; |  | ||||||
|       else if (pc->issocket ()) |  | ||||||
| 	buf->st_mode = S_IFSOCK; |  | ||||||
|       else |  | ||||||
| 	buf->st_mode = S_IFREG; |  | ||||||
|       if (!pc->has_acls () |  | ||||||
| 	  || get_file_attribute (TRUE, pc->get_win32 (), |  | ||||||
| 				 &buf->st_mode, &uid, &gid)) |  | ||||||
| 	{ |  | ||||||
| 	  buf->st_mode |= STD_RBITS | STD_XBITS; |  | ||||||
| 	  if (!(pc->has_attribute (FILE_ATTRIBUTE_READONLY))) |  | ||||||
| 	    buf->st_mode |= STD_WBITS; |  | ||||||
| 	  if (pc->issymlink ()) |  | ||||||
| 	    buf->st_mode |= S_IRWXU | S_IRWXG | S_IRWXO; |  | ||||||
| 	  get_file_attribute (FALSE, pc->get_win32 (), NULL, &uid, &gid); |  | ||||||
| 	} |  | ||||||
|       buf->st_uid = uid; |  | ||||||
|       buf->st_gid = gid; |  | ||||||
|       if ((handle = FindFirstFile (pc->get_win32 (), &wfd)) |  | ||||||
| 	  != INVALID_HANDLE_VALUE) |  | ||||||
| 	{ |  | ||||||
| 	  /* This is for FAT filesystems, which don't support atime/ctime */ |  | ||||||
| 	  if (wfd.ftLastAccessTime.dwLowDateTime == 0 |  | ||||||
| 	      && wfd.ftLastAccessTime.dwHighDateTime == 0) |  | ||||||
| 	    wfd.ftLastAccessTime = wfd.ftLastWriteTime; |  | ||||||
| 	  if (wfd.ftCreationTime.dwLowDateTime == 0 |  | ||||||
| 	      && wfd.ftCreationTime.dwHighDateTime == 0) |  | ||||||
| 	    wfd.ftCreationTime = wfd.ftLastWriteTime; |  | ||||||
|  |  | ||||||
| 	  buf->st_atime   = to_time_t (&wfd.ftLastAccessTime); |  | ||||||
| 	  buf->st_mtime   = to_time_t (&wfd.ftLastWriteTime); |  | ||||||
| 	  buf->st_ctime   = to_time_t (&wfd.ftCreationTime); |  | ||||||
| 	  buf->st_size    = wfd.nFileSizeLow; |  | ||||||
| 	  buf->st_size    = ((__off64_t)wfd.nFileSizeHigh << 32) |  | ||||||
| 			    + wfd.nFileSizeLow; |  | ||||||
| 	  buf->st_blksize = S_BLKSIZE; |  | ||||||
| 	  buf->st_blocks  = (buf->st_size + S_BLKSIZE-1) / S_BLKSIZE; |  | ||||||
| 	  FindClose (handle); |  | ||||||
| 	} |  | ||||||
|       res = 0; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|   return res; |   return res; | ||||||
| } | } | ||||||
|  |  | ||||||
| int | int __stdcall | ||||||
| fhandler_disk_file::fstat_helper (struct __stat64 *buf) | fhandler_disk_file::fstat_helper (struct __stat64 *buf, path_conv *pc, | ||||||
|  | 				  FILETIME ftCreationTime, | ||||||
|  | 				  FILETIME ftLastAccessTime, | ||||||
|  | 				  FILETIME ftLastWriteTime, | ||||||
|  | 				  DWORD nFileSizeHigh, | ||||||
|  | 				  DWORD nFileSizeLow, | ||||||
|  | 				  DWORD nFileIndexHigh, | ||||||
|  | 				  DWORD nFileIndexLow, | ||||||
|  | 				  DWORD nNumberOfLinks) | ||||||
| { | { | ||||||
|   int res = 0;	// avoid a compiler warning |  | ||||||
|   BY_HANDLE_FILE_INFORMATION local; |  | ||||||
|   save_errno saved_errno; |  | ||||||
|  |  | ||||||
|   /* NT 3.51 seems to have a bug when attempting to get vol serial |  | ||||||
|      numbers.  This loop gets around this. */ |  | ||||||
|   for (int i = 0; i < 2; i++) |  | ||||||
|     { |  | ||||||
|       if (!(res = GetFileInformationByHandle (get_handle (), &local))) |  | ||||||
| 	break; |  | ||||||
|       if (local.dwVolumeSerialNumber && (long) local.dwVolumeSerialNumber != -1) |  | ||||||
| 	break; |  | ||||||
|     } |  | ||||||
|   debug_printf ("%d = GetFileInformationByHandle (%s, %d)", |  | ||||||
| 		res, get_win32_name (), get_handle ()); |  | ||||||
|   if (res == 0) |  | ||||||
|     { |  | ||||||
|       /* GetFileInformationByHandle will fail if it's given stdin/out/err |  | ||||||
| 	 or a pipe*/ |  | ||||||
|       DWORD lsize, hsize; |  | ||||||
|  |  | ||||||
|       if (GetFileType (get_handle ()) != FILE_TYPE_DISK) |  | ||||||
| 	buf->st_mode = S_IFCHR; |  | ||||||
|  |  | ||||||
|       lsize = GetFileSize (get_handle (), &hsize); |  | ||||||
|       if (lsize == 0xffffffff && GetLastError () != NO_ERROR) |  | ||||||
| 	buf->st_mode = S_IFCHR; |  | ||||||
|       else |  | ||||||
| 	buf->st_size = ((__off64_t)hsize << 32) + lsize; |  | ||||||
|       /* We expect these to fail! */ |  | ||||||
|       buf->st_mode |= STD_RBITS | STD_WBITS; |  | ||||||
|       buf->st_blksize = S_BLKSIZE; |  | ||||||
|       buf->st_ino = get_namehash (); |  | ||||||
|       syscall_printf ("0 = fstat (, %p)",  buf); |  | ||||||
|       return 0; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|   if (!get_win32_name ()) |  | ||||||
|     { |  | ||||||
|       saved_errno.set (ENOENT); |  | ||||||
|       return -1; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|   /* This is for FAT filesystems, which don't support atime/ctime */ |   /* This is for FAT filesystems, which don't support atime/ctime */ | ||||||
|   if (local.ftLastAccessTime.dwLowDateTime == 0 |   if (ftLastAccessTime.dwLowDateTime == 0 | ||||||
|       && local.ftLastAccessTime.dwHighDateTime == 0) |       && ftLastAccessTime.dwHighDateTime == 0) | ||||||
|     local.ftLastAccessTime = local.ftLastWriteTime; |     ftLastAccessTime = ftLastWriteTime; | ||||||
|   if (local.ftCreationTime.dwLowDateTime == 0 |   if (ftCreationTime.dwLowDateTime == 0 | ||||||
|       && local.ftCreationTime.dwHighDateTime == 0) |       && ftCreationTime.dwHighDateTime == 0) | ||||||
|     local.ftCreationTime = local.ftLastWriteTime; |     ftCreationTime = ftLastWriteTime; | ||||||
|  |  | ||||||
|   buf->st_atime   = to_time_t (&local.ftLastAccessTime); |   buf->st_atime   = to_time_t (&ftLastAccessTime); | ||||||
|   buf->st_mtime   = to_time_t (&local.ftLastWriteTime); |   buf->st_mtime   = to_time_t (&ftLastWriteTime); | ||||||
|   buf->st_ctime   = to_time_t (&local.ftCreationTime); |   buf->st_ctime   = to_time_t (&ftCreationTime); | ||||||
|   buf->st_nlink   = local.nNumberOfLinks; |   buf->st_nlink   = nNumberOfLinks; | ||||||
|   buf->st_dev     = local.dwVolumeSerialNumber; |   buf->st_dev     = pc->volser (); | ||||||
|   buf->st_size    = ((__off64_t)local.nFileSizeHigh << 32) |   buf->st_size    = ((__off64_t)nFileSizeHigh << 32) + nFileSizeLow; | ||||||
| 		    + local.nFileSizeLow; |  | ||||||
|  |  | ||||||
|   /* Allocate some place to determine the root directory. Need to allocate |  | ||||||
|      enough so that rootdir can add a trailing slash if path starts with \\. */ |  | ||||||
|   char root[strlen (get_win32_name ()) + 3]; |  | ||||||
|   strcpy (root, get_win32_name ()); |  | ||||||
|  |  | ||||||
|   /* Assume that if a drive has ACL support it MAY have valid "inodes". |   /* 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 |      It definitely does not have valid inodes if it does not have ACL | ||||||
|      support. */ |      support. */ | ||||||
|   switch (has_acls () ? GetDriveType (rootdir (root)) : DRIVE_UNKNOWN) |   switch (pc->has_acls () && (nFileIndexHigh || nFileIndexLow) | ||||||
|  | 	  ? pc->drive_type () : DRIVE_UNKNOWN) | ||||||
|     { |     { | ||||||
|     case DRIVE_FIXED: |     case DRIVE_FIXED: | ||||||
|     case DRIVE_REMOVABLE: |     case DRIVE_REMOVABLE: | ||||||
| @@ -247,7 +217,7 @@ fhandler_disk_file::fstat_helper (struct __stat64 *buf) | |||||||
|     case DRIVE_RAMDISK: |     case DRIVE_RAMDISK: | ||||||
|       /* Although the documentation indicates otherwise, it seems like |       /* Although the documentation indicates otherwise, it seems like | ||||||
| 	 "inodes" on these devices are persistent, at least across reboots. */ | 	 "inodes" on these devices are persistent, at least across reboots. */ | ||||||
|       buf->st_ino = local.nFileIndexHigh | local.nFileIndexLow; |       buf->st_ino = nFileIndexHigh | nFileIndexLow; | ||||||
|       break; |       break; | ||||||
|     default: |     default: | ||||||
|       /* Either the nFileIndex* fields are unreliable or unavailable.  Use the |       /* Either the nFileIndex* fields are unreliable or unavailable.  Use the | ||||||
| @@ -262,20 +232,20 @@ fhandler_disk_file::fstat_helper (struct __stat64 *buf) | |||||||
|   buf->st_mode = 0; |   buf->st_mode = 0; | ||||||
|   /* Using a side effect: get_file_attibutes checks for |   /* Using a side effect: get_file_attibutes checks for | ||||||
|      directory. This is used, to set S_ISVTX, if needed.  */ |      directory. This is used, to set S_ISVTX, if needed.  */ | ||||||
|   if (local.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) |   if (pc->fileattr & FILE_ATTRIBUTE_DIRECTORY) | ||||||
|     buf->st_mode = S_IFDIR; |     buf->st_mode = S_IFDIR; | ||||||
|   else if (get_symlink_p ()) |   else if (pc->issymlink ()) | ||||||
|     buf->st_mode = S_IFLNK; |     buf->st_mode = S_IFLNK; | ||||||
|   else if (get_socket_p ()) |   else if (pc->issocket ()) | ||||||
|     buf->st_mode = S_IFSOCK; |     buf->st_mode = S_IFSOCK; | ||||||
|  |  | ||||||
|   __uid16_t uid; |   __uid16_t uid; | ||||||
|   __gid16_t gid; |   __gid16_t gid; | ||||||
|   if (get_file_attribute (has_acls (), get_win32_name (), &buf->st_mode, |   if (get_file_attribute (pc->has_acls (), get_win32_name (), &buf->st_mode, | ||||||
| 			  &uid, &gid) == 0) | 			  &uid, &gid) == 0) | ||||||
|     { |     { | ||||||
|       /* If read-only attribute is set, modify ntsec return value */ |       /* If read-only attribute is set, modify ntsec return value */ | ||||||
|       if ((local.dwFileAttributes & FILE_ATTRIBUTE_READONLY) |       if ((pc->fileattr & FILE_ATTRIBUTE_READONLY) && !get_symlink_p ()) | ||||||
| 	  && !get_symlink_p ()) |  | ||||||
| 	buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); | 	buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); | ||||||
|  |  | ||||||
|       if (!(buf->st_mode & S_IFMT)) |       if (!(buf->st_mode & S_IFMT)) | ||||||
| @@ -285,7 +255,7 @@ fhandler_disk_file::fstat_helper (struct __stat64 *buf) | |||||||
|     { |     { | ||||||
|       buf->st_mode |= STD_RBITS; |       buf->st_mode |= STD_RBITS; | ||||||
|  |  | ||||||
|       if (!(local.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) |       if (!(pc->fileattr & FILE_ATTRIBUTE_READONLY)) | ||||||
| 	buf->st_mode |= STD_WBITS; | 	buf->st_mode |= STD_WBITS; | ||||||
|       /* | S_IWGRP | S_IWOTH; we don't give write to group etc */ |       /* | S_IWGRP | S_IWOTH; we don't give write to group etc */ | ||||||
|  |  | ||||||
| @@ -293,18 +263,12 @@ fhandler_disk_file::fstat_helper (struct __stat64 *buf) | |||||||
| 	buf->st_mode |= S_IFDIR | STD_XBITS; | 	buf->st_mode |= S_IFDIR | STD_XBITS; | ||||||
|       else if (buf->st_mode & S_IFMT) |       else if (buf->st_mode & S_IFMT) | ||||||
| 	/* nothing */; | 	/* nothing */; | ||||||
|       else if (get_socket_p ()) |       else if (pc->issocket ()) | ||||||
| 	buf->st_mode |= S_IFSOCK; | 	buf->st_mode |= S_IFSOCK; | ||||||
|       else |       else | ||||||
| 	switch (GetFileType (get_handle ())) |  | ||||||
| 	{ | 	{ | ||||||
| 	  case FILE_TYPE_CHAR: |  | ||||||
| 	  case FILE_TYPE_UNKNOWN: |  | ||||||
| 	    buf->st_mode |= S_IFCHR; |  | ||||||
| 	    break; |  | ||||||
| 	  case FILE_TYPE_DISK: |  | ||||||
| 	  buf->st_mode |= S_IFREG; | 	  buf->st_mode |= S_IFREG; | ||||||
| 	    if (!dont_care_if_execable () && !get_execable_p ()) | 	  if (!pc->exec_state () == dont_know_if_executable) | ||||||
| 	    { | 	    { | ||||||
| 	      DWORD cur, done; | 	      DWORD cur, done; | ||||||
| 	      char magic[3]; | 	      char magic[3]; | ||||||
| @@ -325,22 +289,27 @@ fhandler_disk_file::fstat_helper (struct __stat64 *buf) | |||||||
| 		  SetFilePointer (get_handle(), cur, NULL, FILE_BEGIN); | 		  SetFilePointer (get_handle(), cur, NULL, FILE_BEGIN); | ||||||
| 		} | 		} | ||||||
| 	    } | 	    } | ||||||
| 	    if (get_execable_p ()) | 	  if (pc->exec_state () == is_executable) | ||||||
| 	    buf->st_mode |= STD_XBITS; | 	    buf->st_mode |= STD_XBITS; | ||||||
| 	    break; |  | ||||||
| 	  case FILE_TYPE_PIPE: |  | ||||||
| 	    buf->st_mode |= S_IFSOCK; |  | ||||||
| 	    break; |  | ||||||
| 	} | 	} | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   buf->st_uid = uid; |   buf->st_uid = uid; | ||||||
|   buf->st_gid = gid; |   buf->st_gid = gid; | ||||||
|  |  | ||||||
|  |   /* The number of links to a directory includes the | ||||||
|  |      number of subdirectories in the directory, since all | ||||||
|  |      those subdirectories point to it. | ||||||
|  |      This is too slow on remote drives, so we do without it and | ||||||
|  |      set the number of links to 2. */ | ||||||
|  |   /* Unfortunately the count of 2 confuses `find (1)' command. So | ||||||
|  |      let's try it with `1' as link count. */ | ||||||
|  |   if (pc->isdir () && !buf->st_nlink) | ||||||
|  |     buf->st_nlink = pc->isremote () ? 1 : num_entries (pc->get_win32 ()); | ||||||
|  |  | ||||||
|   syscall_printf ("0 = fstat (, %p) st_atime=%x st_size=%D, st_mode=%p, st_ino=%d, sizeof=%d", |   syscall_printf ("0 = fstat (, %p) st_atime=%x st_size=%D, st_mode=%p, st_ino=%d, sizeof=%d", | ||||||
| 		  buf, buf->st_atime, buf->st_size, buf->st_mode, | 		  buf, buf->st_atime, buf->st_size, buf->st_mode, | ||||||
| 		  (int) buf->st_ino, sizeof (*buf)); | 		  (int) buf->st_ino, sizeof (*buf)); | ||||||
|  |  | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -391,8 +360,7 @@ fhandler_disk_file::open (path_conv *real_path, int flags, mode_t mode) | |||||||
|      The only known file system to date is the SUN NFS Solstice Client 3.1 |      The only known file system to date is the SUN NFS Solstice Client 3.1 | ||||||
|      which returns a valid handle when trying to open a file in a nonexistent |      which returns a valid handle when trying to open a file in a nonexistent | ||||||
|      directory. */ |      directory. */ | ||||||
|   if (real_path->has_buggy_open () |   if (real_path->has_buggy_open () && !real_path->exists ()) | ||||||
|       && GetFileAttributes (win32_path_name) == INVALID_FILE_ATTRIBUTES) |  | ||||||
|     { |     { | ||||||
|       debug_printf ("Buggy open detected."); |       debug_printf ("Buggy open detected."); | ||||||
|       close (); |       close (); | ||||||
|   | |||||||
| @@ -336,11 +336,31 @@ typedef enum _MEMORY_INFORMATION_CLASS | |||||||
|   MemoryBaiscVlmInformation |   MemoryBaiscVlmInformation | ||||||
| } MEMORY_INFORMATION_CLASS; | } MEMORY_INFORMATION_CLASS; | ||||||
|  |  | ||||||
| typedef struct _MEMORY_WORKING_SET_LIST { | typedef struct _MEMORY_WORKING_SET_LIST | ||||||
|  | { | ||||||
|   ULONG NumberOfPages; |   ULONG NumberOfPages; | ||||||
|   ULONG WorkingSetList[1]; |   ULONG WorkingSetList[1]; | ||||||
| } MEMORY_WORKING_SET_LIST, *PMEMORY_WORKING_SET_LIST; | } MEMORY_WORKING_SET_LIST, *PMEMORY_WORKING_SET_LIST; | ||||||
|  |  | ||||||
|  | typedef struct _FILE_NAME_INFORMATION | ||||||
|  | { | ||||||
|  |   DWORD FileNameLength; | ||||||
|  |   WCHAR FileName[MAX_PATH + 100]; | ||||||
|  | } FILE_NAME_INFORMATION; | ||||||
|  |  | ||||||
|  | typedef enum _OBJECT_INFORMATION_CLASS | ||||||
|  | { | ||||||
|  |    ObjectBasicInformation = 0, | ||||||
|  |    ObjectNameInformation = 1, | ||||||
|  |    ObjectHandleInformation = 4 | ||||||
|  |    // and many more | ||||||
|  | } OBJECT_INFORMATION_CLASS; | ||||||
|  |  | ||||||
|  | typedef struct _OBJECT_NAME_INFORMATION | ||||||
|  | { | ||||||
|  |   UNICODE_STRING Name; | ||||||
|  | } OBJECT_NAME_INFORMATION; | ||||||
|  |  | ||||||
| /* Function declarations for ntdll.dll.  These don't appear in any | /* Function declarations for ntdll.dll.  These don't appear in any | ||||||
|    standard Win32 header.  */ |    standard Win32 header.  */ | ||||||
| extern "C" | extern "C" | ||||||
| @@ -368,4 +388,7 @@ extern "C" | |||||||
|                                             OUT PVOID, IN ULONG, OUT PULONG); |                                             OUT PVOID, IN ULONG, OUT PULONG); | ||||||
|   NTSTATUS NTAPI ZwQueryVirtualMemory (IN HANDLE, IN PVOID, IN MEMORY_INFORMATION_CLASS, |   NTSTATUS NTAPI ZwQueryVirtualMemory (IN HANDLE, IN PVOID, IN MEMORY_INFORMATION_CLASS, | ||||||
|                                        OUT PVOID, IN ULONG, OUT PULONG); |                                        OUT PVOID, IN ULONG, OUT PULONG); | ||||||
|  |   NTSTATUS NTAPI NtQueryInformationFile (HANDLE, IO_STATUS_BLOCK *, VOID *, | ||||||
|  | 					 DWORD, DWORD); | ||||||
|  |   NTSTATUS NTAPI NtQueryObject (HANDLE, OBJECT_INFORMATION_CLASS, VOID *, ULONG, ULONG *); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -373,6 +373,23 @@ path_conv::return_and_clear_normalized_path () | |||||||
|   return s; |   return s; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void | ||||||
|  | path_conv::fillin (HANDLE h) | ||||||
|  | { | ||||||
|  |   BY_HANDLE_FILE_INFORMATION local; | ||||||
|  |   if (!GetFileInformationByHandle (h, &local)) | ||||||
|  |     { | ||||||
|  |       fileattr = INVALID_FILE_ATTRIBUTES; | ||||||
|  |       fs.serial = 0; | ||||||
|  |     } | ||||||
|  |   else | ||||||
|  |     { | ||||||
|  |       fileattr = local.dwFileAttributes; | ||||||
|  |       fs.serial = local.dwVolumeSerialNumber; | ||||||
|  |     } | ||||||
|  |     fs.drive_type = DRIVE_UNKNOWN; | ||||||
|  | }  | ||||||
|  |  | ||||||
| /* Convert an arbitrary path SRC to a pure Win32 path, suitable for | /* Convert an arbitrary path SRC to a pure Win32 path, suitable for | ||||||
|    passing to Win32 API routines. |    passing to Win32 API routines. | ||||||
|  |  | ||||||
|   | |||||||
| @@ -143,10 +143,14 @@ class path_conv | |||||||
|   DWORD get_devn () {return devn == FH_BAD ? (DWORD) FH_DISK : devn;} |   DWORD get_devn () {return devn == FH_BAD ? (DWORD) FH_DISK : devn;} | ||||||
|   short get_unitn () {return devn == FH_BAD ? 0 : unit;} |   short get_unitn () {return devn == FH_BAD ? 0 : unit;} | ||||||
|   DWORD file_attributes () {return fileattr;} |   DWORD file_attributes () {return fileattr;} | ||||||
|   DWORD get_drive_type () {return fs.drive_type;} |   DWORD drive_type () {return fs.drive_type;} | ||||||
|   BOOL fs_fast_ea () {return fs.sym_opt & PC_CHECK_EA;} |   BOOL fs_fast_ea () {return fs.sym_opt & PC_CHECK_EA;} | ||||||
|   void set_path (const char *p) {strcpy (path, p);} |   void set_path (const char *p) {strcpy (path, p);} | ||||||
|   char *return_and_clear_normalized_path (); |   char *return_and_clear_normalized_path (); | ||||||
|  |   const char * root_dir () { return fs.root_dir; } | ||||||
|  |   DWORD volser () { return fs.serial; } | ||||||
|  |   const char *volname () {return fs.name; } | ||||||
|  |   void fillin (HANDLE h); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* Symlink marker */ | /* Symlink marker */ | ||||||
|   | |||||||
| @@ -991,8 +991,9 @@ fstat64 (int fd, struct __stat64 *buf) | |||||||
|     res = -1; |     res = -1; | ||||||
|   else |   else | ||||||
|     { |     { | ||||||
|  |       path_conv pc (cfd->get_win32_name ()); | ||||||
|       memset (buf, 0, sizeof (struct __stat64)); |       memset (buf, 0, sizeof (struct __stat64)); | ||||||
|       res = cfd->fstat (buf, NULL); |       res = cfd->fstat (buf, &pc); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   syscall_printf ("%d = fstat (%d, %p)", res, fd, buf); |   syscall_printf ("%d = fstat (%d, %p)", res, fd, buf); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user