summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/dtable.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/dtable.cc')
-rw-r--r--winsup/cygwin/dtable.cc103
1 files changed, 96 insertions, 7 deletions
diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc
index f43baea29..b848eabc6 100644
--- a/winsup/cygwin/dtable.cc
+++ b/winsup/cygwin/dtable.cc
@@ -19,6 +19,8 @@ details. */
#include <fcntl.h>
#include <sys/cygwin.h>
#include <assert.h>
+#include <ntdef.h>
+#include <winnls.h>
#define USE_SYS_TYPES_FD_SET
#include <winsock.h>
@@ -31,10 +33,13 @@ details. */
#include "path.h"
#include "dtable.h"
#include "cygheap.h"
+#include "ntdll.h"
static const NO_COPY DWORD std_consts[] = {STD_INPUT_HANDLE, STD_OUTPUT_HANDLE,
STD_ERROR_HANDLE};
+static char *handle_to_fn (HANDLE, char *);
+
/* Set aside space for the table of fds */
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))
name = "/dev/ttyS0"; // FIXME - determine correct device
else
- name = "unknown disk file";
+ name = handle_to_fn (handle, (char *) alloca (MAX_PATH + 100));
path_conv pc;
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;
}
+ if (!pc.exists () && handle)
+ pc.fillin (handle);
+
fhandler_base *fh = build_fhandler (fd, pc.get_devn (),
pc.return_and_clear_normalized_path (),
pc, pc.get_unitn ());
@@ -373,14 +381,14 @@ dtable::build_fhandler (int fd, DWORD dev, char *unix_name,
fh = cnew (fhandler_dev_dsp) ();
break;
case FH_PROC:
- fh = cnew (fhandler_proc) ();
- break;
+ fh = cnew (fhandler_proc) ();
+ break;
case FH_REGISTRY:
- fh = cnew (fhandler_registry) ();
- break;
+ fh = cnew (fhandler_registry) ();
+ break;
case FH_PROCESS:
- fh = cnew (fhandler_process) ();
- break;
+ fh = cnew (fhandler_process) ();
+ break;
default:
system_printf ("internal error -- unknown device - %p", dev);
fh = NULL;
@@ -688,3 +696,84 @@ dtable::vfork_child_fixup ()
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