* 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.
This commit is contained in:
parent
d08d72adff
commit
e03f5f7338
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}}}
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
__small_sprintf (buf, "%s%s", SYMLINK_COOKIE, topath);
|
||||
DWORD len = strlen (buf) + 1;
|
||||
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];
|
||||
|
||||
/* Note that the terminating nul is written. */
|
||||
if (WriteFile (h, buf, len, &written, NULL) || written != len)
|
||||
__small_sprintf (buf, "%s%s", SYMLINK_COOKIE, topath);
|
||||
DWORD len = strlen (buf) + 1;
|
||||
|
||||
/* 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 ();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Reference in New Issue