Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2001-02-22 15:56:36 +0300
committerCorinna Vinschen <corinna@vinschen.de>2001-02-22 15:56:36 +0300
commit79e56091c9e4f21ecf1807e0f0f4441ddddc84e6 (patch)
tree323f92d808a31d48a656b112b8cb031aa1fd45b6 /winsup
parent957059c8315fd725db2096ef696e57167d721e31 (diff)
* shortcut.c: New file. Provides a C interface to reading of
Windows shortcuts to avoid compiler flag `-fvtable-thunks'. * shortcut.h: Ditto. * Makefile.in: Add shortcut.o to DLL_OFILES. * cygerrno.h: Provide a C interface to `geterrno_from_win_error' for using in shortcut.c. * errno.cc (geterrno_from_win_error): Define as extern "C". * path.cc (struct symlink_info): Remove methods `check_shortcut' and `check_sysfile'. (shortcut_header): Move to shortcut.c. (shortcut_initalized): Ditto. (create_shortcut_header): Ditto. (cmp_shortcut_header): Ditto. (symlink_info::check_shortcut): Ditto. Reorganize as a plain C function. (symlink_info::check_sysfile): Redefine as a global function using the same parameter list as `check_shortcut' for clearness. (symlink_info::check): Change parameter list for calls to `check_shortcut' and `check_sysfile'.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog21
-rw-r--r--winsup/cygwin/Makefile.in3
-rw-r--r--winsup/cygwin/cygerrno.h15
-rw-r--r--winsup/cygwin/errno.cc2
-rw-r--r--winsup/cygwin/path.cc181
-rw-r--r--winsup/cygwin/shortcut.c171
-rw-r--r--winsup/cygwin/shortcut.h28
7 files changed, 253 insertions, 168 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index c1521a55f..283de14e5 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,24 @@
+Thu Feb 22 13:38:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * shortcut.c: New file. Provides a C interface to reading of
+ Windows shortcuts to avoid compiler flag `-fvtable-thunks'.
+ * shortcut.h: Ditto.
+ * Makefile.in: Add shortcut.o to DLL_OFILES.
+ * cygerrno.h: Provide a C interface to `geterrno_from_win_error' for
+ using in shortcut.c.
+ * errno.cc (geterrno_from_win_error): Define as extern "C".
+ * path.cc (struct symlink_info): Remove methods `check_shortcut' and
+ `check_sysfile'.
+ (shortcut_header): Move to shortcut.c.
+ (shortcut_initalized): Ditto.
+ (create_shortcut_header): Ditto.
+ (cmp_shortcut_header): Ditto.
+ (symlink_info::check_shortcut): Ditto. Reorganize as a plain C function.
+ (symlink_info::check_sysfile): Redefine as a global function using the
+ same parameter list as `check_shortcut' for clearness.
+ (symlink_info::check): Change parameter list for calls to
+ `check_shortcut' and `check_sysfile'.
+
Thu Feb 22 12:04:00 2001 Corinna Vinschen <corinna@vinschen.de>
* fhandler.cc (fhandler_disk_file::open): Use `inner_suffixes' when
diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
index b665bd74c..71f513aba 100644
--- a/winsup/cygwin/Makefile.in
+++ b/winsup/cygwin/Makefile.in
@@ -124,7 +124,8 @@ DLL_OFILES:=assert.o autoload.o cygheap.o dcrt0.o debug.o delqueue.o dir.o \
miscfuncs.o mmap.o \
net.o ntea.o passwd.o path.o pinfo.o pipe.o poll.o pthread.o regexp.o \
regerror.o regsub.o registry.o resource.o scandir.o security.o select.o \
- shared.o signal.o sigproc.o smallprint.o spawn.o strace.o strsep.o \
+ shared.o \
+ shortcut.o signal.o sigproc.o smallprint.o spawn.o strace.o strsep.o \
sync.o syscalls.o sysconf.o syslog.o termios.o thread.o times.o tty.o \
uinfo.o uname.o wait.o window.o \
$(EXTRA_DLL_OFILES) $(EXTRA_OFILES) $(MT_SAFE_OBJECTS)
diff --git a/winsup/cygwin/cygerrno.h b/winsup/cygwin/cygerrno.h
index dd40819b9..ad2fad7a1 100644
--- a/winsup/cygwin/cygerrno.h
+++ b/winsup/cygwin/cygerrno.h
@@ -8,9 +8,20 @@ This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int __stdcall geterrno_from_win_error (DWORD code, int deferrno) __attribute__ ((regparm(2)));
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __cplusplus
+
void __stdcall seterrno_from_win_error (const char *file, int line, DWORD code) __attribute__ ((regparm(3)));
void __stdcall seterrno (const char *, int line) __attribute__ ((regparm(2)));
-int __stdcall geterrno_from_win_error (DWORD code, int deferrno) __attribute__ ((regparm(2)));
#define __seterrno() seterrno (__FILE__, __LINE__)
#define __seterrno_from_win_error(val) seterrno_from_win_error (__FILE__, __LINE__, val)
@@ -32,3 +43,5 @@ class save_errno
extern const char *__sp_fn;
extern int __sp_ln;
+
+#endif /* __cplusplus */
diff --git a/winsup/cygwin/errno.cc b/winsup/cygwin/errno.cc
index 87a37910b..baf2d296e 100644
--- a/winsup/cygwin/errno.cc
+++ b/winsup/cygwin/errno.cc
@@ -110,7 +110,7 @@ errmap[] =
{ 0, NULL, 0}
};
-int __stdcall
+extern "C" int __stdcall
geterrno_from_win_error (DWORD code, int deferrno)
{
for (int i = 0; errmap[i].w != 0; ++i)
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 9183762cc..33ff8435f 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -74,9 +74,7 @@ details. */
#include "registry.h"
#include "security.h"
#include <assert.h>
-#include <shlobj.h>
-#include <objidl.h>
-#include <objbase.h>
+#include "shortcut.h"
static int normalize_win32_path (const char *src, char *dst);
static void slashify (const char *src, char *dst, int trailing_slash_p);
@@ -94,8 +92,6 @@ struct symlink_info
int is_symlink;
int error;
symlink_info (): known_suffix (NULL), contents (buf + MAX_PATH + 1) {}
- int check_shortcut (const char *, DWORD, HANDLE);
- int check_sysfile (const char *, DWORD, HANDLE);
int check (const char *path, const suffix_info *suffixes);
};
@@ -2195,35 +2191,6 @@ endmntent (FILE *)
/********************** Symbolic Link Support **************************/
-/* The header written to a shortcut by Cygwin or U/WIN. */
-#define SHORTCUT_HDR_SIZE 76
-static char shortcut_header[SHORTCUT_HDR_SIZE];
-static BOOL shortcut_initalized = FALSE;
-
-static void
-create_shortcut_header (void)
-{
- if (!shortcut_initalized)
- {
- shortcut_header[0] = 'L';
- shortcut_header[4] = '\001';
- shortcut_header[5] = '\024';
- shortcut_header[6] = '\002';
- shortcut_header[12] = '\300';
- shortcut_header[19] = 'F';
- shortcut_header[20] = '\f';
- shortcut_header[60] = '\001';
- shortcut_initalized = TRUE;
- }
-}
-
-static BOOL
-cmp_shortcut_header (const char *file_header)
-{
- create_shortcut_header ();
- return memcmp (shortcut_header, file_header, SHORTCUT_HDR_SIZE);
-}
-
/* Create a symlink from FROMPATH to TOPATH. */
extern "C"
@@ -2362,127 +2329,9 @@ next_suffix (char *ext_here, const suffix_info *&suffixes)
return 0;
}
-int
-symlink_info::check_shortcut (const char *path, DWORD fileattr, HANDLE h)
-{
- HRESULT hres;
- IShellLink *psl = NULL;
- IPersistFile *ppf = NULL;
- WCHAR wc_path[MAX_PATH];
- char full_path[MAX_PATH];
- WIN32_FIND_DATA wfd;
- DWORD len = 0;
- int res = 0;
-
- /* Initialize COM library. */
- CoInitialize (NULL);
-
- /* Get a pointer to the IShellLink interface. */
- hres = CoCreateInstance (CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
- IID_IShellLink, (void **)&psl);
- if (FAILED (hres))
- {
- debug_printf ("CoCreateInstance failed");
- goto close_it;
- }
- /* Get a pointer to the IPersistFile interface. */
- hres = psl->QueryInterface (IID_IPersistFile, (void **)&ppf);
- if (FAILED (hres))
- {
- debug_printf ("QueryInterface failed");
- goto close_it;
- }
- /* Load the shortcut. */
- MultiByteToWideChar(CP_ACP, 0, path, -1, wc_path, MAX_PATH);
- hres = ppf->Load (wc_path, STGM_READ);
- if (FAILED (hres))
- {
- debug_printf ("Load failed");
- goto close_it;
- }
- /* Try the description (containing a POSIX path) first. */
- if (fileattr & FILE_ATTRIBUTE_READONLY)
- {
- /* An additional check is needed to prove if it's a shortcut
- really created by Cygwin or U/WIN. */
- char file_header[SHORTCUT_HDR_SIZE];
- DWORD got;
-
- if (! ReadFile (h, file_header, SHORTCUT_HDR_SIZE, &got, 0))
- {
- debug_printf ("ReadFile failed");
- error = EIO;
- goto close_it_dont_set_error;
- }
- if (got == SHORTCUT_HDR_SIZE && !cmp_shortcut_header (file_header))
- {
- hres = psl->GetDescription (contents, MAX_PATH);
- if (FAILED (hres))
- {
- debug_printf ("GetDescription failed");
- goto close_it;
- }
- len = strlen (contents);
- }
- }
- /* No description or not R/O: Check the "official" path. */
- if (len == 0)
- {
- /* Convert to full path (easy way) */
- if ((path[0] == '\\' && path[1] == '\\')
- || (_toupper (path[0]) >= 'A' && _toupper (path[0]) <= 'Z'
- && path[1] == ':'))
- len = 0;
- else
- {
- len = GetCurrentDirectory (MAX_PATH, full_path);
- if (path[0] == '\\')
- len = 2;
- else if (full_path[len - 1] != '\\')
- strcpy (full_path + len++, "\\");
- }
- strcpy (full_path + len, path);
- debug_printf ("full_path = <%s>", full_path);
- /* Set relative path inside of IShellLink interface. */
- hres = psl->SetRelativePath (full_path, 0);
- if (FAILED (hres))
- {
- debug_printf ("SetRelativePath failed");
- goto close_it;
- }
- /* Get the path to the shortcut target. */
- hres = psl->GetPath (contents, MAX_PATH, &wfd, 0);
- if (FAILED(hres))
- {
- debug_printf ("GetPath failed");
- goto close_it;
- }
- }
- /* It's a symlink. */
- pflags = PATH_SYMLINK;
- res = strlen (contents);
-
-close_it:
- if (FAILED (hres))
- error = geterrno_from_win_error (HRESULT_CODE (hres), EACCES);
-
-close_it_dont_set_error:
- /* Release the pointer to IPersistFile. */
- if (ppf)
- ppf->Release();
- /* Release the pointer to IShellLink. */
- if (psl)
- psl->Release();
- /* Uninitialize COM library. */
- CoUninitialize ();
-
- syscall_printf ("%d = symlink.check_shortcut (%s, %s) (%p)",
- res, path, contents, pflags);
- return res;
-}
-
-int
-symlink_info::check_sysfile (const char *path, DWORD fileattr, HANDLE h)
+static int
+check_sysfile (const char *path, DWORD fileattr, HANDLE h,
+ char *contents, int *error, unsigned *pflags)
{
char cookie_buf[sizeof (SYMLINK_COOKIE) - 1];
DWORD got;
@@ -2491,19 +2340,19 @@ symlink_info::check_sysfile (const char *path, DWORD fileattr, HANDLE h)
if (! ReadFile (h, cookie_buf, sizeof (cookie_buf), &got, 0))
{
debug_printf ("ReadFile1 failed");
- error = EIO;
+ *error = EIO;
}
else if (got == sizeof (cookie_buf)
&& memcmp (cookie_buf, SYMLINK_COOKIE, sizeof (cookie_buf)) == 0)
{
/* It's a symlink. */
- pflags = PATH_SYMLINK;
+ *pflags = PATH_SYMLINK;
res = ReadFile (h, contents, MAX_PATH + 1, &got, 0);
if (!res)
{
debug_printf ("ReadFile2 failed");
- error = EIO;
+ *error = EIO;
}
else
{
@@ -2521,15 +2370,13 @@ symlink_info::check_sysfile (const char *path, DWORD fileattr, HANDLE h)
}
else if (got == sizeof (cookie_buf)
&& memcmp (cookie_buf, SOCKET_COOKIE, sizeof (cookie_buf)) == 0)
- pflags |= PATH_SOCKET;
+ *pflags |= PATH_SOCKET;
else
{
/* Not a symlink, see if executable. */
- if (!(pflags & PATH_ALL_EXEC) && has_exec_chars (cookie_buf, got))
- pflags |= PATH_EXEC;
+ if (!(*pflags & PATH_ALL_EXEC) && has_exec_chars (cookie_buf, got))
+ *pflags |= PATH_EXEC;
}
- syscall_printf ("%d = symlink.check_sysfile (%s, %s) (%p)",
- res, path, contents, pflags);
return res;
}
@@ -2615,12 +2462,16 @@ symlink_info::check (const char *in_path, const suffix_info *suffixes)
res = -1;
if (h == INVALID_HANDLE_VALUE)
goto file_not_symlink;
- else if (sym_check == 1 && !(res = check_shortcut (path, fileattr, h)))
+ else if (sym_check == 1
+ && !(res = check_shortcut (path, fileattr, h,
+ contents, &error, &pflags)))
{
CloseHandle (h);
goto file_not_symlink;
}
- else if (sym_check == 2 && !(res = check_sysfile (path, fileattr, h)))
+ else if (sym_check == 2 &&
+ !(res = check_sysfile (path, fileattr, h,
+ contents, &error, &pflags)))
{
CloseHandle (h);
goto file_not_symlink;
diff --git a/winsup/cygwin/shortcut.c b/winsup/cygwin/shortcut.c
new file mode 100644
index 000000000..7c05f9db3
--- /dev/null
+++ b/winsup/cygwin/shortcut.c
@@ -0,0 +1,171 @@
+/* shortcut.c: Read shortcuts. This part of the code must be in C because
+ the C++ interface to COM doesn't work without -fvtable-thunk
+ which is too dangerous to use.
+
+ Copyright 2001 Red Hat, Inc.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "winsup.h"
+#include <shlobj.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/mount.h>
+#include <errno.h>
+#include "cygerrno.h"
+#include "shortcut.h"
+
+/* This is needed to avoid including path.h which is a pure C++ header. */
+#define PATH_SYMLINK MOUNT_SYMLINK
+
+#define debug_printf(x) strcpy (contents, x)
+
+char shortcut_header[SHORTCUT_HDR_SIZE];
+BOOL shortcut_initalized = FALSE;
+
+void
+create_shortcut_header (void)
+{
+ if (!shortcut_initalized)
+ {
+ shortcut_header[0] = 'L';
+ shortcut_header[4] = '\001';
+ shortcut_header[5] = '\024';
+ shortcut_header[6] = '\002';
+ shortcut_header[12] = '\300';
+ shortcut_header[19] = 'F';
+ shortcut_header[20] = '\f';
+ shortcut_header[60] = '\001';
+ shortcut_initalized = TRUE;
+ }
+}
+
+static BOOL
+cmp_shortcut_header (const char *file_header)
+{
+ create_shortcut_header ();
+ return memcmp (shortcut_header, file_header, SHORTCUT_HDR_SIZE);
+}
+
+int
+check_shortcut (const char *path, DWORD fileattr, HANDLE h,
+ char *contents, int *error, unsigned *pflags)
+{
+ HRESULT hres;
+ IShellLink *psl = NULL;
+ IPersistFile *ppf = NULL;
+ WCHAR wc_path[MAX_PATH];
+ char full_path[MAX_PATH];
+ WIN32_FIND_DATA wfd;
+ DWORD len = 0;
+ int res = 0;
+
+ /* Initialize COM library. */
+ CoInitialize (NULL);
+
+ /* Get a pointer to the IShellLink interface. */
+ hres = CoCreateInstance (&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IShellLink, (void **)&psl);
+ if (FAILED (hres))
+ {
+ debug_printf ("CoCreateInstance failed");
+ goto close_it;
+ }
+ /* Get a pointer to the IPersistFile interface. */
+ hres = psl->lpVtbl->QueryInterface (psl, &IID_IPersistFile, (void **)&ppf);
+ if (FAILED (hres))
+ {
+ debug_printf ("QueryInterface failed");
+ goto close_it;
+ }
+ /* Load the shortcut. */
+ MultiByteToWideChar(CP_ACP, 0, path, -1, wc_path, MAX_PATH);
+ hres = ppf->lpVtbl->Load (ppf, wc_path, STGM_READ);
+ if (FAILED (hres))
+ {
+ debug_printf ("Load failed");
+ goto close_it;
+ }
+ /* Try the description (containing a POSIX path) first. */
+ if (fileattr & FILE_ATTRIBUTE_READONLY)
+ {
+ /* An additional check is needed to prove if it's a shortcut
+ really created by Cygwin or U/WIN. */
+ char file_header[SHORTCUT_HDR_SIZE];
+ DWORD got;
+
+ if (! ReadFile (h, file_header, SHORTCUT_HDR_SIZE, &got, 0))
+ {
+ debug_printf ("ReadFile failed");
+ *error = EIO;
+ goto close_it_dont_set_error;
+ }
+ if (got == SHORTCUT_HDR_SIZE && !cmp_shortcut_header (file_header))
+ {
+ hres = psl->lpVtbl->GetDescription (psl, contents, MAX_PATH);
+ if (FAILED (hres))
+ {
+ debug_printf ("GetDescription failed");
+ goto close_it;
+ }
+ len = strlen (contents);
+ }
+ }
+ /* No description or not R/O: Check the "official" path. */
+ if (len == 0)
+ {
+ /* Convert to full path (easy way) */
+ if ((path[0] == '\\' && path[1] == '\\')
+ || (_toupper (path[0]) >= 'A' && _toupper (path[0]) <= 'Z'
+ && path[1] == ':'))
+ len = 0;
+ else
+ {
+ len = GetCurrentDirectory (MAX_PATH, full_path);
+ if (path[0] == '\\')
+ len = 2;
+ else if (full_path[len - 1] != '\\')
+ strcpy (full_path + len++, "\\");
+ }
+ strcpy (full_path + len, path);
+ /* Set relative path inside of IShellLink interface. */
+ hres = psl->lpVtbl->SetRelativePath (psl, full_path, 0);
+ if (FAILED (hres))
+ {
+ debug_printf ("SetRelativePath failed");
+ goto close_it;
+ }
+ /* Get the path to the shortcut target. */
+ hres = psl->lpVtbl->GetPath (psl, contents, MAX_PATH, &wfd, 0);
+ if (FAILED(hres))
+ {
+ debug_printf ("GetPath failed");
+ goto close_it;
+ }
+ }
+ /* It's a symlink. */
+ *pflags = PATH_SYMLINK;
+ res = strlen (contents);
+
+close_it:
+ if (FAILED (hres))
+ *error = geterrno_from_win_error (HRESULT_CODE (hres), EACCES);
+
+close_it_dont_set_error:
+ /* Release the pointer to IPersistFile. */
+ if (ppf)
+ ppf->lpVtbl->Release(ppf);
+ /* Release the pointer to IShellLink. */
+ if (psl)
+ psl->lpVtbl->Release(psl);
+ /* Uninitialize COM library. */
+ CoUninitialize ();
+
+ return res;
+}
+
+
diff --git a/winsup/cygwin/shortcut.h b/winsup/cygwin/shortcut.h
new file mode 100644
index 000000000..87e7ff156
--- /dev/null
+++ b/winsup/cygwin/shortcut.h
@@ -0,0 +1,28 @@
+/* shortcut.h: Hader file for shortcut.c
+
+ Copyright 2001 Red Hat, Inc.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The header written to a shortcut by Cygwin or U/WIN. */
+#define SHORTCUT_HDR_SIZE 76
+
+extern char shortcut_header[];
+extern BOOL shortcut_initalized;
+
+extern void create_shortcut_header ();
+
+int check_shortcut (const char *path, DWORD fileattr, HANDLE h,
+ char *contents, int *error, unsigned *pflags);
+
+#ifdef __cplusplus
+};
+#endif