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
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2001-03-02 14:41:09 +0300
committerCorinna Vinschen <corinna@vinschen.de>2001-03-02 14:41:09 +0300
commite03f5f73381e352469a116d84480427227c04027 (patch)
tree02bffe58a078fc35290478879889dfeb06944569
parentd08d72adff5eb5e2c810494043c7104cd9b3aa6c (diff)
* dir.cc (readdir): Fix shortcut==symlink condition.
* environ.cc: Add extern decl for `allow_winsymlinks'. (struct parse_thing): Add entry for `[no]winsymlinks'. * path.cc (symlink): Change to be able to create both, symlink==shortcut and symlink==systemfile, dependent of the setting of `allow_winsymlinks'. * security.cc (cygwin_logon_user): Add debug output. * shortcut.c: Add defines from path.h. (has_exec_chars): Copy from path.h. (check_shortcut): Check for executable file condition if not a shortcut.
-rw-r--r--winsup/cygwin/ChangeLog14
-rw-r--r--winsup/cygwin/dir.cc11
-rw-r--r--winsup/cygwin/environ.cc2
-rw-r--r--winsup/cygwin/path.cc151
-rw-r--r--winsup/cygwin/security.cc2
-rw-r--r--winsup/cygwin/shortcut.c50
6 files changed, 141 insertions, 89 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index eb5731352..111e0ce54 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,17 @@
+Fri Mar 2 12:33:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * dir.cc (readdir): Fix shortcut==symlink condition.
+ * environ.cc: Add extern decl for `allow_winsymlinks'.
+ (struct parse_thing): Add entry for `[no]winsymlinks'.
+ * path.cc (symlink): Change to be able to create both,
+ symlink==shortcut and symlink==systemfile, dependent of
+ the setting of `allow_winsymlinks'.
+ * security.cc (cygwin_logon_user): Add debug output.
+ * shortcut.c: Add defines from path.h.
+ (has_exec_chars): Copy from path.h.
+ (check_shortcut): Check for executable file condition if not a
+ shortcut.
+
Thu Mar 1 21:06:07 2001 Christopher Faylor <cgf@cygnus.com>
* exceptions.cc (sig_handle_tty_stop): Ignore attempts to suspend a
diff --git a/winsup/cygwin/dir.cc b/winsup/cygwin/dir.cc
index c88fbfc57..29d8084cb 100644
--- a/winsup/cygwin/dir.cc
+++ b/winsup/cygwin/dir.cc
@@ -174,12 +174,21 @@ readdir (DIR * dir)
/* We get here if `buf' contains valid data. */
strcpy (dir->__d_dirent->d_name, buf.cFileName);
+ /* Check for Windows shortcut. If it's a Cygwin or U/WIN
+ symlink, drop the .lnk suffix. */
if (buf.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
{
char *c = dir->__d_dirent->d_name;
int len = strlen (c);
if (!strcasecmp (c + len - 4, ".lnk"))
- c[len - 4] = '\0';
+ {
+ char fbuf[MAX_PATH + 1];
+ strcpy (fbuf, dir->__d_dirname);
+ strcat (fbuf + strlen (fbuf) - 1, dir->__d_dirent->d_name);
+ path_conv fpath (fbuf, PC_SYM_NOFOLLOW);
+ if (fpath.issymlink ())
+ c[len - 4] = '\0';
+ }
}
/* Compute d_ino by combining filename hash with the directory hash
diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc
index 1e160b50e..df4c60fc8 100644
--- a/winsup/cygwin/environ.cc
+++ b/winsup/cygwin/environ.cc
@@ -30,6 +30,7 @@ extern BOOL allow_glob;
extern BOOL ignore_case_with_glob;
extern BOOL allow_ntea;
extern BOOL allow_smbntsec;
+extern BOOL allow_winsymlinks;
extern BOOL strip_title_path;
extern DWORD chunksize;
BOOL reset_com = TRUE;
@@ -454,6 +455,7 @@ struct parse_thing
{"strip_title", {&strip_title_path}, justset, NULL, {{FALSE}, {TRUE}}},
{"title", {&display_title}, justset, NULL, {{FALSE}, {TRUE}}},
{"tty", {NULL}, set_process_state, NULL, {{0}, {PID_USETTY}}},
+ {"winsymlinks", {&allow_winsymlinks}, justset, NULL, {{FALSE}, {TRUE}}},
{NULL, {0}, justset, 0, {{0}, {0}}}
};
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 681664dc0..5355f1982 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -2192,24 +2192,30 @@ endmntent (FILE *)
/* Create a symlink from FROMPATH to TOPATH. */
+/* If TRUE create symlinks as Windows shortcuts, if FALSE create symlinks
+ as normal files with magic number and system bit set. */
+int allow_winsymlinks = TRUE;
+
extern "C"
int
symlink (const char *topath, const char *frompath)
{
HANDLE h;
int res = -1;
-
-#if 0
- path_conv win32_path (frompath, PC_SYM_NOFOLLOW);
-#else
+ path_conv win32_path, win32_topath;
char from[MAX_PATH + 5];
- strcpy (from, frompath);
- strcat (from, ".lnk");
- path_conv win32_path (from, PC_SYM_NOFOLLOW);
- path_conv win32_topath;
char cwd[MAX_PATH + 1], *cp = NULL, c = 0;
char w32topath[MAX_PATH + 1];
-#endif
+ DWORD written;
+
+ if (allow_winsymlinks)
+ {
+ strcpy (from, frompath);
+ strcat (from, ".lnk");
+ win32_path.check (from, PC_SYM_NOFOLLOW);
+ }
+ else
+ win32_path.check (frompath, PC_SYM_NOFOLLOW);
if (win32_path.error)
{
@@ -2237,86 +2243,83 @@ symlink (const char *topath, const char *frompath)
goto done;
}
-#if 0
+ if (allow_winsymlinks)
+ {
+ if (!isabspath (topath))
+ {
+ getcwd (cwd, MAX_PATH + 1);
+ if ((cp = strrchr (from, '/')) || (cp = strrchr (from, '\\')))
+ {
+ c = *cp;
+ *cp = '\0';
+ chdir (from);
+ }
+ backslashify (topath, w32topath, 0);
+ }
+ if (!cp || GetFileAttributes (w32topath) == (DWORD)-1)
+ {
+ win32_topath.check (topath, PC_SYM_NOFOLLOW);
+ if (!cp || win32_topath.error != ENOENT)
+ strcpy (w32topath, win32_topath);
+ }
+ if (cp)
+ {
+ *cp = c;
+ chdir (cwd);
+ }
+ }
+
h = CreateFileA(win32_path, GENERIC_WRITE, 0, &sec_none_nih,
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
if (h == INVALID_HANDLE_VALUE)
__seterrno ();
else
{
- DWORD written;
- /* This is the old technique creating a symlink.
- Preserved to have a fallback. */
- char buf[sizeof (SYMLINK_COOKIE) + MAX_PATH + 10];
+ BOOL success;
+
+ if (allow_winsymlinks)
+ {
+ create_shortcut_header ();
+ /* Don't change the datatypes of `len' and `win_len' since
+ their sizeof is used when writing. */
+ unsigned short len = strlen (topath);
+ unsigned short win_len = strlen (w32topath);
+ success = WriteFile (h, shortcut_header, SHORTCUT_HDR_SIZE,
+ &written, NULL)
+ && written == SHORTCUT_HDR_SIZE
+ && WriteFile (h, &len, sizeof len, &written, NULL)
+ && written == sizeof len
+ && WriteFile (h, topath, len, &written, NULL)
+ && written == len
+ && WriteFile (h, &win_len, sizeof win_len, &written, NULL)
+ && written == sizeof win_len
+ && WriteFile (h, w32topath, win_len, &written, NULL)
+ && written == win_len;
+ }
+ else
+ {
+ /* This is the old technique creating a symlink. */
+ char buf[sizeof (SYMLINK_COOKIE) + MAX_PATH + 10];
- __small_sprintf (buf, "%s%s", SYMLINK_COOKIE, topath);
- DWORD len = strlen (buf) + 1;
+ __small_sprintf (buf, "%s%s", SYMLINK_COOKIE, topath);
+ DWORD len = strlen (buf) + 1;
- /* Note that the terminating nul is written. */
- if (WriteFile (h, buf, len, &written, NULL) || written != len)
+ /* Note that the terminating nul is written. */
+ success = WriteFile (h, buf, len, &written, NULL)
+ || written != len;
+
+ }
+ if (success)
{
CloseHandle (h);
set_file_attribute (win32_path.has_acls (),
win32_path.get_win32 (),
S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
- SetFileAttributesA (win32_path.get_win32 (), FILE_ATTRIBUTE_SYSTEM);
+ SetFileAttributesA (win32_path.get_win32 (),
+ allow_winsymlinks ? FILE_ATTRIBUTE_READONLY
+ : FILE_ATTRIBUTE_SYSTEM);
res = 0;
}
-#else
- if (!isabspath (topath))
- {
- getcwd (cwd, MAX_PATH + 1);
- if ((cp = strrchr (from, '/')) || (cp = strrchr (from, '\\')))
- {
- c = *cp;
- *cp = '\0';
- chdir (from);
- }
- backslashify (topath, w32topath, 0);
- }
- if (!cp || GetFileAttributes (w32topath) == (DWORD)-1)
- {
- win32_topath.check (topath, PC_SYM_NOFOLLOW);
- if (!cp || win32_topath.error != ENOENT)
- strcpy (w32topath, win32_topath);
- }
- if (cp)
- {
- *cp = c;
- chdir (cwd);
- }
-
- h = CreateFileA(win32_path, GENERIC_WRITE, 0, &sec_none_nih,
- CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
- if (h == INVALID_HANDLE_VALUE)
- __seterrno ();
- else
- {
- DWORD written;
- create_shortcut_header ();
- /* Don't change the datatypes of `len' and `win_len' since
- their sizeof is used later. */
- unsigned short len = strlen (topath);
- unsigned short win_len = strlen (w32topath);
- if (WriteFile (h, shortcut_header, SHORTCUT_HDR_SIZE, &written, NULL)
- && written == SHORTCUT_HDR_SIZE
- && WriteFile (h, &len, sizeof len, &written, NULL)
- && written == sizeof len
- && WriteFile (h, topath, len, &written, NULL)
- && written == len
- && WriteFile (h, &win_len, sizeof win_len, &written, NULL)
- && written == sizeof win_len
- && WriteFile (h, w32topath, win_len, &written, NULL)
- && written == win_len)
- {
- CloseHandle (h);
- set_file_attribute (win32_path.has_acls (),
- win32_path.get_win32 (),
- S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
- SetFileAttributesA (win32_path.get_win32 (), FILE_ATTRIBUTE_READONLY);
- res = 0;
- }
-#endif
else
{
__seterrno ();
diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc
index 334c1af60..bef29d2cf 100644
--- a/winsup/cygwin/security.cc
+++ b/winsup/cygwin/security.cc
@@ -457,6 +457,7 @@ cygwin_logon_user (const struct passwd *pw, const char *password)
HANDLE hToken;
strcpy (usernamebuf, pw->pw_name);
+ debug_printf ("pw_gecos = %x (%s)", pw->pw_gecos, pw->pw_gecos);
if (pw->pw_gecos)
{
if ((c = strstr (pw->pw_gecos, "U-")) != NULL &&
@@ -475,6 +476,7 @@ cygwin_logon_user (const struct passwd *pw, const char *password)
*c = '\0';
nt_user = c + 1;
}
+ debug_printf ("LogonUserA (%s, %s, %s, ...)", nt_user, nt_domain, password);
if (!LogonUserA (nt_user, nt_domain, (char *) password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
diff --git a/winsup/cygwin/shortcut.c b/winsup/cygwin/shortcut.c
index 5f632f01c..6851f1274 100644
--- a/winsup/cygwin/shortcut.c
+++ b/winsup/cygwin/shortcut.c
@@ -18,8 +18,24 @@ details. */
#include <errno.h>
#include "shortcut.h"
+/* TODO:
+ Currently duplicated from path.h. Later rearrangement of path.h
+ to allow including from plain C would be better. */
/* This is needed to avoid including path.h which is a pure C++ header. */
-#define PATH_SYMLINK MOUNT_SYMLINK
+#define PATH_SYMLINK MOUNT_SYMLINK
+#define PATH_EXEC MOUNT_EXEC
+#define PATH_CYGWIN_EXEC MOUNT_CYGWIN_EXEC
+#define PATH_ALL_EXEC PATH_CYGWIN_EXEC | PATH_EXEC
+
+/* TODO: Ditto. */
+static BOOL
+has_exec_chars (const char *buf, int len)
+{
+ return len >= 2 &&
+ ((buf[0] == '#' && buf[1] == '!') ||
+ (buf[0] == ':' && buf[1] == '\n') ||
+ (buf[0] == 'M' && buf[1] == 'Z'));
+}
char shortcut_header[SHORTCUT_HDR_SIZE];
BOOL shortcut_initalized = FALSE;
@@ -57,9 +73,11 @@ check_shortcut (const char *path, DWORD fileattr, HANDLE h,
IPersistFile *ppf = NULL;
WCHAR wc_path[MAX_PATH];
char full_path[MAX_PATH];
+ char file_header[SHORTCUT_HDR_SIZE];
WIN32_FIND_DATA wfd;
DWORD len = 0;
int res = 0;
+ DWORD got = 0;
/* Initialize COM library. */
CoInitialize (NULL);
@@ -78,24 +96,22 @@ check_shortcut (const char *path, DWORD fileattr, HANDLE h,
hres = ppf->lpVtbl->Load (ppf, wc_path, STGM_READ);
if (FAILED (hres))
goto close_it;
+ /* Read the files header information. This is used to check for a
+ Cygwin or U/WIN shortcut or later to check for executable files. */
+ if (! ReadFile (h, file_header, SHORTCUT_HDR_SIZE, &got, 0))
+ {
+ *error = EIO;
+ 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))
- {
- *error = EIO;
- goto close_it;
- }
+ /* Check header if the shortcut is really created by Cygwin or U/WIN. */
if (got == SHORTCUT_HDR_SIZE && !cmp_shortcut_header (file_header))
{
hres = psl->lpVtbl->GetDescription (psl, contents, MAX_PATH);
if (FAILED (hres))
- goto close_it;
+ goto file_not_symlink;
len = strlen (contents);
}
}
@@ -119,15 +135,21 @@ check_shortcut (const char *path, DWORD fileattr, HANDLE h,
/* Set relative path inside of IShellLink interface. */
hres = psl->lpVtbl->SetRelativePath (psl, full_path, 0);
if (FAILED (hres))
- goto close_it;
+ goto file_not_symlink;
/* Get the path to the shortcut target. */
hres = psl->lpVtbl->GetPath (psl, contents, MAX_PATH, &wfd, 0);
if (FAILED(hres))
- goto close_it;
+ goto file_not_symlink;
}
res = strlen (contents);
if (res) /* It's a symlink. */
*pflags = PATH_SYMLINK;
+ goto close_it;
+
+file_not_symlink:
+ /* Not a symlink, see if executable. */
+ if (!(*pflags & PATH_ALL_EXEC) && has_exec_chars (file_header, got))
+ *pflags |= PATH_EXEC;
close_it:
/* Release the pointer to IPersistFile. */