mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-03-02 13:05:42 +08:00
* Makefile.in: Add `-lshell32 -luuid' to link pass for new-cygwin1.dll.
* autoload.cc: Add LoadDLLinitfunc for ole32.dll. Add LoadDLLfuncEx statements for CoInitialize@4, CoUninitialize@0 and CoCreateInstance@20. * dir.cc (dir_suffixes): New datastructure. (readdir): Check for R/O *.lnk files to hide the suffix. (opendir): Use `dir_suffixes' in path conversion. (rmdir): Ditto. * fhandler.cc (fhandler_disk_file::fstat): Add S_IFLNK flag before calling `get_file_attribute'. Take FILE_ATTRIBUTE_READONLY into account only if the file is no symlink. * path.cc (inner_suffixes): New datastructure. (SYMLINKATTR): Eliminated. (path_conv::check): Use `inner_suffixes' on inner path components. (shortcut_header): New global static variable. (shortcut_initalized): Ditto. (create_shortcut_header): New function. (cmp_shortcut_header): Ditto. (symlink): Create symlinks by creating windows shortcuts. Preserve the old code. (symlink_info::check_shortcut): New method. (symlink_info::check_sysfile): Ditto. (symlink_info::check): Check for shortcuts. Move code reading old system attribute symlinks into symlink_info::check_sysfile(). (chdir): Use `dir_suffixes' in path conversion. * security.cc (get_file_attribute): Check for S_IFLNK flag. Force 0777 permissions then. * spawn.cc (std_suffixes): Add ".lnk" suffix. * syscalls.cc (_unlink): Use `inner_suffixes' in path conversion. Check for shortcut symlinks to eliminate R/O attribute before calling DeleteFile(). (stat_suffixes): Add ".lnk" suffix. (stat_worker): Force 0777 permissions if file is a symlink.
This commit is contained in:
parent
5b2ea3a436
commit
10b06c5ee0
@ -1,3 +1,39 @@
|
|||||||
|
Wed Feb 21 22:41:00 2001 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* Makefile.in: Add `-lshell32 -luuid' to link pass for new-cygwin1.dll.
|
||||||
|
* autoload.cc: Add LoadDLLinitfunc for ole32.dll.
|
||||||
|
Add LoadDLLfuncEx statements for CoInitialize@4, CoUninitialize@0
|
||||||
|
and CoCreateInstance@20.
|
||||||
|
* dir.cc (dir_suffixes): New datastructure.
|
||||||
|
(readdir): Check for R/O *.lnk files to hide the suffix.
|
||||||
|
(opendir): Use `dir_suffixes' in path conversion.
|
||||||
|
(rmdir): Ditto.
|
||||||
|
* fhandler.cc (fhandler_disk_file::fstat): Add S_IFLNK flag
|
||||||
|
before calling `get_file_attribute'. Take FILE_ATTRIBUTE_READONLY
|
||||||
|
into account only if the file is no symlink.
|
||||||
|
* path.cc (inner_suffixes): New datastructure.
|
||||||
|
(SYMLINKATTR): Eliminated.
|
||||||
|
(path_conv::check): Use `inner_suffixes' on inner path components.
|
||||||
|
(shortcut_header): New global static variable.
|
||||||
|
(shortcut_initalized): Ditto.
|
||||||
|
(create_shortcut_header): New function.
|
||||||
|
(cmp_shortcut_header): Ditto.
|
||||||
|
(symlink): Create symlinks by creating windows shortcuts. Preserve
|
||||||
|
the old code.
|
||||||
|
(symlink_info::check_shortcut): New method.
|
||||||
|
(symlink_info::check_sysfile): Ditto.
|
||||||
|
(symlink_info::check): Check for shortcuts. Move code reading
|
||||||
|
old system attribute symlinks into symlink_info::check_sysfile().
|
||||||
|
(chdir): Use `dir_suffixes' in path conversion.
|
||||||
|
* security.cc (get_file_attribute): Check for S_IFLNK flag.
|
||||||
|
Force 0777 permissions then.
|
||||||
|
* spawn.cc (std_suffixes): Add ".lnk" suffix.
|
||||||
|
* syscalls.cc (_unlink): Use `inner_suffixes' in path conversion.
|
||||||
|
Check for shortcut symlinks to eliminate R/O attribute before
|
||||||
|
calling DeleteFile().
|
||||||
|
(stat_suffixes): Add ".lnk" suffix.
|
||||||
|
(stat_worker): Force 0777 permissions if file is a symlink.
|
||||||
|
|
||||||
2001-02-21 Egor Duda <deo@logos-m.ru>
|
2001-02-21 Egor Duda <deo@logos-m.ru>
|
||||||
|
|
||||||
* sigproc.cc (getsem): Make semaphore always non-inheritable.
|
* sigproc.cc (getsem): Make semaphore always non-inheritable.
|
||||||
|
@ -190,7 +190,7 @@ new-$(LIB_NAME): $(LIB_NAME)
|
|||||||
|
|
||||||
new-$(DLL_NAME): $(DLL_OFILES) $(DEF_FILE) $(DLL_IMPORTS) $(LIBC) $(LIBM) Makefile winver_stamp
|
new-$(DLL_NAME): $(DLL_OFILES) $(DEF_FILE) $(DLL_IMPORTS) $(LIBC) $(LIBM) Makefile winver_stamp
|
||||||
$(CXX) $(CXXFLAGS) -nostdlib -Wl,-shared -o $@ -e $(DLL_ENTRY) $(DEF_FILE) $(DLL_OFILES) version.o \
|
$(CXX) $(CXXFLAGS) -nostdlib -Wl,-shared -o $@ -e $(DLL_ENTRY) $(DEF_FILE) $(DLL_OFILES) version.o \
|
||||||
winver.o $(DLL_IMPORTS) $(MALLOC_OBJ) $(LIBM) $(LIBC) -lgcc -lstdc++
|
winver.o $(DLL_IMPORTS) $(MALLOC_OBJ) $(LIBM) $(LIBC) -lgcc -lstdc++ -lshell32 -luuid
|
||||||
|
|
||||||
dll_ofiles: $(DLL_OFILES)
|
dll_ofiles: $(DLL_OFILES)
|
||||||
|
|
||||||
|
@ -90,6 +90,13 @@ LoadDLLinitfunc (advapi32)
|
|||||||
LoadDLLinitfunc (netapi32)
|
LoadDLLinitfunc (netapi32)
|
||||||
{
|
{
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
|
static NO_COPY LONG here = -1L;
|
||||||
|
|
||||||
|
while (InterlockedIncrement (&here))
|
||||||
|
{
|
||||||
|
InterlockedDecrement (&here);
|
||||||
|
Sleep (0);
|
||||||
|
}
|
||||||
|
|
||||||
if ((h = LoadLibrary ("netapi32.dll")) != NULL)
|
if ((h = LoadLibrary ("netapi32.dll")) != NULL)
|
||||||
netapi32_handle = h;
|
netapi32_handle = h;
|
||||||
@ -197,6 +204,28 @@ LoadDLLinitfunc (iphlpapi)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LoadDLLinitfunc (ole32)
|
||||||
|
{
|
||||||
|
HANDLE h;
|
||||||
|
static NO_COPY LONG here = -1L;
|
||||||
|
|
||||||
|
while (InterlockedIncrement (&here))
|
||||||
|
{
|
||||||
|
InterlockedDecrement (&here);
|
||||||
|
Sleep (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ole32_handle)
|
||||||
|
/* nothing to do */;
|
||||||
|
else if ((h = LoadLibrary ("ole32.dll")) != NULL)
|
||||||
|
ole32_handle = h;
|
||||||
|
else if (!ole32_handle)
|
||||||
|
api_fatal ("could not load ole32.dll, %E");
|
||||||
|
|
||||||
|
InterlockedDecrement (&here);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void __stdcall dummy_autoload (void) __attribute__ ((unused));
|
static void __stdcall dummy_autoload (void) __attribute__ ((unused));
|
||||||
static void __stdcall
|
static void __stdcall
|
||||||
dummy_autoload (void)
|
dummy_autoload (void)
|
||||||
@ -339,5 +368,10 @@ LoadDLLfuncEx (WSASocketA, 24, ws2_32, 1)
|
|||||||
LoadDLLinit (iphlpapi)
|
LoadDLLinit (iphlpapi)
|
||||||
LoadDLLfuncEx (GetIfTable, 12, iphlpapi, 1)
|
LoadDLLfuncEx (GetIfTable, 12, iphlpapi, 1)
|
||||||
LoadDLLfuncEx (GetIpAddrTable, 12, iphlpapi, 1)
|
LoadDLLfuncEx (GetIpAddrTable, 12, iphlpapi, 1)
|
||||||
|
|
||||||
|
LoadDLLinit (ole32)
|
||||||
|
LoadDLLfunc (CoInitialize, 4, ole32)
|
||||||
|
LoadDLLfunc (CoUninitialize, 0, ole32)
|
||||||
|
LoadDLLfunc (CoCreateInstance, 20, ole32)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,13 @@ writable_directory (const char *file)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suffix_info dir_suffixes[] =
|
||||||
|
{
|
||||||
|
suffix_info ("", 1),
|
||||||
|
suffix_info (".lnk", 1),
|
||||||
|
suffix_info (NULL)
|
||||||
|
};
|
||||||
|
|
||||||
/* opendir: POSIX 5.1.2.1 */
|
/* opendir: POSIX 5.1.2.1 */
|
||||||
extern "C" DIR *
|
extern "C" DIR *
|
||||||
opendir (const char *dirname)
|
opendir (const char *dirname)
|
||||||
@ -68,7 +75,7 @@ opendir (const char *dirname)
|
|||||||
DIR *res = 0;
|
DIR *res = 0;
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
|
|
||||||
path_conv real_dirname (dirname, PC_SYM_FOLLOW | PC_FULL);
|
path_conv real_dirname (dirname, PC_SYM_FOLLOW | PC_FULL, dir_suffixes);
|
||||||
|
|
||||||
if (real_dirname.error)
|
if (real_dirname.error)
|
||||||
{
|
{
|
||||||
@ -174,6 +181,14 @@ readdir (DIR * dir)
|
|||||||
/* We get here if `buf' contains valid data. */
|
/* We get here if `buf' contains valid data. */
|
||||||
strcpy (dir->__d_dirent->d_name, buf.cFileName);
|
strcpy (dir->__d_dirent->d_name, buf.cFileName);
|
||||||
|
|
||||||
|
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';
|
||||||
|
}
|
||||||
|
|
||||||
/* Compute d_ino by combining filename hash with the directory hash
|
/* Compute d_ino by combining filename hash with the directory hash
|
||||||
(which was stored in dir->__d_dirhash when opendir was called). */
|
(which was stored in dir->__d_dirhash when opendir was called). */
|
||||||
if (buf.cFileName[0] == '.')
|
if (buf.cFileName[0] == '.')
|
||||||
@ -316,7 +331,7 @@ rmdir (const char *dir)
|
|||||||
{
|
{
|
||||||
int res = -1;
|
int res = -1;
|
||||||
|
|
||||||
path_conv real_dir (dir, PC_SYM_NOFOLLOW);
|
path_conv real_dir (dir, PC_SYM_NOFOLLOW, dir_suffixes);
|
||||||
|
|
||||||
if (real_dir.error)
|
if (real_dir.error)
|
||||||
{
|
{
|
||||||
|
@ -921,6 +921,8 @@ fhandler_disk_file::fstat (struct stat *buf)
|
|||||||
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 (local.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
buf->st_mode |= S_IFDIR;
|
buf->st_mode |= S_IFDIR;
|
||||||
|
if (get_symlink_p ())
|
||||||
|
buf->st_mode |= S_IFLNK;
|
||||||
if (!get_file_attribute (has_acls (),
|
if (!get_file_attribute (has_acls (),
|
||||||
get_win32_name (),
|
get_win32_name (),
|
||||||
&buf->st_mode,
|
&buf->st_mode,
|
||||||
@ -928,7 +930,8 @@ fhandler_disk_file::fstat (struct stat *buf)
|
|||||||
&buf->st_gid))
|
&buf->st_gid))
|
||||||
{
|
{
|
||||||
/* 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 ((local.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
|
||||||
|
&& !get_symlink_p ())
|
||||||
buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
|
buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
|
||||||
|
|
||||||
buf->st_mode &= ~S_IFMT;
|
buf->st_mode &= ~S_IFMT;
|
||||||
|
@ -57,6 +57,10 @@ details. */
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <winioctl.h>
|
#include <winioctl.h>
|
||||||
|
#include <wingdi.h>
|
||||||
|
#include <winuser.h>
|
||||||
|
#include <winnls.h>
|
||||||
|
#include <winnetwk.h>
|
||||||
#include <sys/cygwin.h>
|
#include <sys/cygwin.h>
|
||||||
#include <cygwin/version.h>
|
#include <cygwin/version.h>
|
||||||
#include "cygerrno.h"
|
#include "cygerrno.h"
|
||||||
@ -70,6 +74,9 @@ details. */
|
|||||||
#include "registry.h"
|
#include "registry.h"
|
||||||
#include "security.h"
|
#include "security.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <shlobj.h>
|
||||||
|
#include <objidl.h>
|
||||||
|
#include <objbase.h>
|
||||||
|
|
||||||
static int normalize_win32_path (const char *src, char *dst);
|
static int normalize_win32_path (const char *src, char *dst);
|
||||||
static void slashify (const char *src, char *dst, int trailing_slash_p);
|
static void slashify (const char *src, char *dst, int trailing_slash_p);
|
||||||
@ -87,19 +94,25 @@ struct symlink_info
|
|||||||
int is_symlink;
|
int is_symlink;
|
||||||
int error;
|
int error;
|
||||||
symlink_info (): known_suffix (NULL), contents (buf + MAX_PATH + 1) {}
|
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);
|
int check (const char *path, const suffix_info *suffixes);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* These suffixes are the only ones allowed in inner path components. */
|
||||||
|
suffix_info inner_suffixes[] =
|
||||||
|
{
|
||||||
|
suffix_info ("", 1),
|
||||||
|
suffix_info (".lnk", 1),
|
||||||
|
suffix_info (NULL)
|
||||||
|
};
|
||||||
|
|
||||||
cwdstuff cygcwd; /* The current working directory. */
|
cwdstuff cygcwd; /* The current working directory. */
|
||||||
|
|
||||||
#define path_prefix_p(p1, p2, l1) \
|
#define path_prefix_p(p1, p2, l1) \
|
||||||
((cyg_tolower(*(p1))==cyg_tolower(*(p2))) && \
|
((cyg_tolower(*(p1))==cyg_tolower(*(p2))) && \
|
||||||
path_prefix_p_(p1, p2, l1))
|
path_prefix_p_(p1, p2, l1))
|
||||||
|
|
||||||
#define SYMLINKATTR(x) \
|
|
||||||
(((x) & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY)) == \
|
|
||||||
FILE_ATTRIBUTE_SYSTEM)
|
|
||||||
|
|
||||||
/* Determine if path prefix matches current cygdrive */
|
/* Determine if path prefix matches current cygdrive */
|
||||||
#define iscygdrive(path) \
|
#define iscygdrive(path) \
|
||||||
(path_prefix_p (mount_table->cygdrive, (path), mount_table->cygdrive_len))
|
(path_prefix_p (mount_table->cygdrive, (path), mount_table->cygdrive_len))
|
||||||
@ -264,7 +277,7 @@ path_conv::check (const char *src, unsigned opt,
|
|||||||
class if we're working on an inner component of the path */
|
class if we're working on an inner component of the path */
|
||||||
if (component)
|
if (component)
|
||||||
{
|
{
|
||||||
suff = NULL;
|
suff = inner_suffixes;
|
||||||
sym.pflags = 0;
|
sym.pflags = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2182,6 +2195,35 @@ endmntent (FILE *)
|
|||||||
|
|
||||||
/********************** Symbolic Link Support **************************/
|
/********************** 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. */
|
/* Create a symlink from FROMPATH to TOPATH. */
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
@ -2191,7 +2233,17 @@ symlink (const char *topath, const char *frompath)
|
|||||||
HANDLE h;
|
HANDLE h;
|
||||||
int res = -1;
|
int res = -1;
|
||||||
|
|
||||||
|
#if 0
|
||||||
path_conv win32_path (frompath, PC_SYM_NOFOLLOW);
|
path_conv win32_path (frompath, PC_SYM_NOFOLLOW);
|
||||||
|
#else
|
||||||
|
char from[MAX_PATH];
|
||||||
|
unsigned short len = strlen (frompath);
|
||||||
|
strcpy (from, frompath);
|
||||||
|
if (len <= 4 || strcasecmp (from + len - 4, ".lnk"))
|
||||||
|
strcpy (from + len, ".lnk");
|
||||||
|
path_conv win32_path (from, PC_SYM_NOFOLLOW);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (win32_path.error)
|
if (win32_path.error)
|
||||||
{
|
{
|
||||||
set_errno (win32_path.error);
|
set_errno (win32_path.error);
|
||||||
@ -2224,20 +2276,17 @@ symlink (const char *topath, const char *frompath)
|
|||||||
__seterrno ();
|
__seterrno ();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
DWORD written;
|
||||||
|
#if 0
|
||||||
|
/* This is the old technique creating a symlink.
|
||||||
|
Preserved to have a fallback. */
|
||||||
char buf[sizeof (SYMLINK_COOKIE) + MAX_PATH + 10];
|
char buf[sizeof (SYMLINK_COOKIE) + MAX_PATH + 10];
|
||||||
|
|
||||||
__small_sprintf (buf, "%s%s", SYMLINK_COOKIE, topath);
|
__small_sprintf (buf, "%s%s", SYMLINK_COOKIE, topath);
|
||||||
DWORD len = strlen (buf) + 1;
|
DWORD len = strlen (buf) + 1;
|
||||||
|
|
||||||
/* Note that the terminating nul is written. */
|
/* Note that the terminating nul is written. */
|
||||||
DWORD written;
|
if (WriteFile (h, buf, len, &written, NULL) || written != len)
|
||||||
if (!WriteFile (h, buf, len, &written, NULL) || written != len)
|
|
||||||
{
|
|
||||||
__seterrno ();
|
|
||||||
CloseHandle (h);
|
|
||||||
DeleteFileA (win32_path.get_win32 ());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
CloseHandle (h);
|
CloseHandle (h);
|
||||||
set_file_attribute (win32_path.has_acls (),
|
set_file_attribute (win32_path.has_acls (),
|
||||||
@ -2246,6 +2295,36 @@ symlink (const char *topath, const char *frompath)
|
|||||||
SetFileAttributesA (win32_path.get_win32 (), FILE_ATTRIBUTE_SYSTEM);
|
SetFileAttributesA (win32_path.get_win32 (), FILE_ATTRIBUTE_SYSTEM);
|
||||||
res = 0;
|
res = 0;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
create_shortcut_header ();
|
||||||
|
path_conv win32_topath (topath, PC_SYM_NOFOLLOW);
|
||||||
|
len = strlen (topath);
|
||||||
|
unsigned short win_len = strlen (win32_topath.get_win32 ());
|
||||||
|
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, win32_topath.get_win32 (), 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 ();
|
||||||
|
CloseHandle (h);
|
||||||
|
DeleteFileA (win32_path.get_win32 ());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
@ -2283,6 +2362,177 @@ next_suffix (char *ext_here, const suffix_info *&suffixes)
|
|||||||
return 0;
|
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)
|
||||||
|
{
|
||||||
|
char cookie_buf[sizeof (SYMLINK_COOKIE) - 1];
|
||||||
|
DWORD got;
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
if (! ReadFile (h, cookie_buf, sizeof (cookie_buf), &got, 0))
|
||||||
|
{
|
||||||
|
debug_printf ("ReadFile1 failed");
|
||||||
|
error = EIO;
|
||||||
|
}
|
||||||
|
else if (got == sizeof (cookie_buf)
|
||||||
|
&& memcmp (cookie_buf, SYMLINK_COOKIE, sizeof (cookie_buf)) == 0)
|
||||||
|
{
|
||||||
|
/* It's a symlink. */
|
||||||
|
pflags = PATH_SYMLINK;
|
||||||
|
|
||||||
|
res = ReadFile (h, contents, MAX_PATH + 1, &got, 0);
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
debug_printf ("ReadFile2 failed");
|
||||||
|
error = EIO;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Versions prior to b16 stored several trailing
|
||||||
|
NULs with the path (to fill the path out to 1024
|
||||||
|
chars). Current versions only store one trailing
|
||||||
|
NUL. The length returned is the path without
|
||||||
|
*any* trailing NULs. We also have to handle (or
|
||||||
|
at least not die from) corrupted paths. */
|
||||||
|
if (memchr (contents, 0, got) != NULL)
|
||||||
|
res = strlen (contents);
|
||||||
|
else
|
||||||
|
res = got;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (got == sizeof (cookie_buf)
|
||||||
|
&& memcmp (cookie_buf, SOCKET_COOKIE, sizeof (cookie_buf)) == 0)
|
||||||
|
pflags |= PATH_SOCKET;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Not a symlink, see if executable. */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if PATH is a symlink. PATH must be a valid Win32 path name.
|
/* Check if PATH is a symlink. PATH must be a valid Win32 path name.
|
||||||
|
|
||||||
If PATH is a symlink, put the value of the symlink--the file to
|
If PATH is a symlink, put the value of the symlink--the file to
|
||||||
@ -2340,9 +2590,22 @@ symlink_info::check (const char *in_path, const suffix_info *suffixes)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sym_check = 0;
|
||||||
|
|
||||||
|
if (fileattr & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
|
goto file_not_symlink;
|
||||||
|
|
||||||
|
/* Windows shortcuts are treated as symlinks. */
|
||||||
|
if (!strcasecmp (path + strlen (path) - 4, ".lnk"))
|
||||||
|
sym_check = 1;
|
||||||
|
|
||||||
|
/* The old Cygwin method creating symlinks: */
|
||||||
/* A symlink will have the `system' file attribute. */
|
/* A symlink will have the `system' file attribute. */
|
||||||
/* Only files can be symlinks (which can be symlinks to directories). */
|
/* Only files can be symlinks (which can be symlinks to directories). */
|
||||||
if (!(pflags & PATH_SYMLINK) && !SYMLINKATTR (fileattr))
|
if (fileattr & FILE_ATTRIBUTE_SYSTEM)
|
||||||
|
sym_check = 2;
|
||||||
|
|
||||||
|
if (!sym_check && !(pflags & PATH_SYMLINK))
|
||||||
goto file_not_symlink;
|
goto file_not_symlink;
|
||||||
|
|
||||||
/* Open the file. */
|
/* Open the file. */
|
||||||
@ -2352,54 +2615,15 @@ symlink_info::check (const char *in_path, const suffix_info *suffixes)
|
|||||||
res = -1;
|
res = -1;
|
||||||
if (h == INVALID_HANDLE_VALUE)
|
if (h == INVALID_HANDLE_VALUE)
|
||||||
goto file_not_symlink;
|
goto file_not_symlink;
|
||||||
else
|
else if (sym_check == 1 && !(res = check_shortcut (path, fileattr, h)))
|
||||||
{
|
{
|
||||||
char cookie_buf[sizeof (SYMLINK_COOKIE) - 1];
|
CloseHandle (h);
|
||||||
DWORD got;
|
goto file_not_symlink;
|
||||||
|
}
|
||||||
if (! ReadFile (h, cookie_buf, sizeof (cookie_buf), &got, 0))
|
else if (sym_check == 2 && !(res = check_sysfile (path, fileattr, h)))
|
||||||
error = EIO;
|
{
|
||||||
else if (got == sizeof (cookie_buf)
|
CloseHandle (h);
|
||||||
&& memcmp (cookie_buf, SYMLINK_COOKIE,
|
goto file_not_symlink;
|
||||||
sizeof (cookie_buf)) == 0)
|
|
||||||
{
|
|
||||||
/* It's a symlink. */
|
|
||||||
pflags = PATH_SYMLINK;
|
|
||||||
|
|
||||||
res = ReadFile (h, contents, MAX_PATH + 1, &got, 0);
|
|
||||||
if (!res)
|
|
||||||
error = EIO;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Versions prior to b16 stored several trailing
|
|
||||||
NULs with the path (to fill the path out to 1024
|
|
||||||
chars). Current versions only store one trailing
|
|
||||||
NUL. The length returned is the path without
|
|
||||||
*any* trailing NULs. We also have to handle (or
|
|
||||||
at least not die from) corrupted paths. */
|
|
||||||
if (memchr (contents, 0, got) != NULL)
|
|
||||||
res = strlen (contents);
|
|
||||||
else
|
|
||||||
res = got;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (got == sizeof (cookie_buf)
|
|
||||||
&& memcmp (cookie_buf, SOCKET_COOKIE,
|
|
||||||
sizeof (cookie_buf)) == 0)
|
|
||||||
{
|
|
||||||
pflags |= PATH_SOCKET;
|
|
||||||
goto close_and_return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Not a symlink, see if executable. */
|
|
||||||
if (!(pflags & PATH_ALL_EXEC) &&
|
|
||||||
has_exec_chars (cookie_buf, got))
|
|
||||||
pflags |= PATH_EXEC;
|
|
||||||
close_and_return:
|
|
||||||
CloseHandle (h);
|
|
||||||
goto file_not_symlink;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle (h);
|
CloseHandle (h);
|
||||||
@ -2553,8 +2777,9 @@ int
|
|||||||
chdir (const char *dir)
|
chdir (const char *dir)
|
||||||
{
|
{
|
||||||
MALLOC_CHECK;
|
MALLOC_CHECK;
|
||||||
|
extern suffix_info dir_suffixes[];
|
||||||
syscall_printf ("dir %s", dir);
|
syscall_printf ("dir %s", dir);
|
||||||
path_conv path (dir, PC_FULL | PC_SYM_FOLLOW);
|
path_conv path (dir, PC_FULL | PC_SYM_FOLLOW, dir_suffixes);
|
||||||
|
|
||||||
if (path.error)
|
if (path.error)
|
||||||
{
|
{
|
||||||
|
@ -808,8 +808,15 @@ int
|
|||||||
get_file_attribute (int use_ntsec, const char *file,
|
get_file_attribute (int use_ntsec, const char *file,
|
||||||
int *attribute, uid_t *uidret, gid_t *gidret)
|
int *attribute, uid_t *uidret, gid_t *gidret)
|
||||||
{
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
if (use_ntsec && allow_ntsec)
|
if (use_ntsec && allow_ntsec)
|
||||||
return get_nt_attribute (file, attribute, uidret, gidret);
|
{
|
||||||
|
res = get_nt_attribute (file, attribute, uidret, gidret);
|
||||||
|
if (attribute && (*attribute & S_IFLNK) == S_IFLNK)
|
||||||
|
*attribute |= S_IRWXU | S_IRWXG | S_IRWXO;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
if (uidret)
|
if (uidret)
|
||||||
*uidret = getuid ();
|
*uidret = getuid ();
|
||||||
@ -819,8 +826,7 @@ get_file_attribute (int use_ntsec, const char *file,
|
|||||||
if (!attribute)
|
if (!attribute)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
int res = NTReadEA (file, ".UNIXATTR",
|
res = NTReadEA (file, ".UNIXATTR", (char *) attribute, sizeof (*attribute));
|
||||||
(char *) attribute, sizeof (*attribute));
|
|
||||||
|
|
||||||
/* symlinks are everything for everyone!*/
|
/* symlinks are everything for everyone!*/
|
||||||
if ((*attribute & S_IFLNK) == S_IFLNK)
|
if ((*attribute & S_IFLNK) == S_IFLNK)
|
||||||
|
@ -41,6 +41,7 @@ details. */
|
|||||||
static suffix_info std_suffixes[] =
|
static suffix_info std_suffixes[] =
|
||||||
{
|
{
|
||||||
suffix_info (".exe", 1), suffix_info ("", 1),
|
suffix_info (".exe", 1), suffix_info ("", 1),
|
||||||
|
suffix_info (".lnk", 1),
|
||||||
suffix_info (".com"), suffix_info (".cmd"),
|
suffix_info (".com"), suffix_info (".cmd"),
|
||||||
suffix_info (".bat"), suffix_info (".dll"),
|
suffix_info (".bat"), suffix_info (".dll"),
|
||||||
suffix_info (NULL)
|
suffix_info (NULL)
|
||||||
|
@ -65,10 +65,11 @@ close_all_files (void)
|
|||||||
extern "C" int
|
extern "C" int
|
||||||
_unlink (const char *ourname)
|
_unlink (const char *ourname)
|
||||||
{
|
{
|
||||||
|
extern suffix_info inner_suffixes[];
|
||||||
int res = -1;
|
int res = -1;
|
||||||
sigframe thisframe (mainthread);
|
sigframe thisframe (mainthread);
|
||||||
|
|
||||||
path_conv win32_name (ourname, PC_SYM_NOFOLLOW | PC_FULL);
|
path_conv win32_name (ourname, PC_SYM_NOFOLLOW | PC_FULL, inner_suffixes);
|
||||||
|
|
||||||
if (win32_name.error)
|
if (win32_name.error)
|
||||||
{
|
{
|
||||||
@ -94,6 +95,15 @@ _unlink (const char *ourname)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check for shortcut as symlink condition. */
|
||||||
|
if (atts != 0xffffffff && atts & FILE_ATTRIBUTE_READONLY)
|
||||||
|
{
|
||||||
|
int len = strlen (win32_name.get_win32 ());
|
||||||
|
if (len > 4 && !strcasecmp (win32_name.get_win32 () + len - 4, ".lnk"))
|
||||||
|
SetFileAttributes (win32_name.get_win32 (),
|
||||||
|
win32_name.file_attributes () & ~FILE_ATTRIBUTE_READONLY);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
if (DeleteFile (win32_name))
|
if (DeleteFile (win32_name))
|
||||||
@ -1021,6 +1031,7 @@ suffix_info stat_suffixes[] =
|
|||||||
{
|
{
|
||||||
suffix_info ("", 1),
|
suffix_info ("", 1),
|
||||||
suffix_info (".exe", 1),
|
suffix_info (".exe", 1),
|
||||||
|
suffix_info (".lnk", 1),
|
||||||
suffix_info (NULL)
|
suffix_info (NULL)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1135,6 +1146,8 @@ stat_worker (const char *caller, const char *name, struct stat *buf,
|
|||||||
buf->st_mode |= STD_RBITS | STD_XBITS;
|
buf->st_mode |= STD_RBITS | STD_XBITS;
|
||||||
if ((atts & FILE_ATTRIBUTE_READONLY) == 0)
|
if ((atts & FILE_ATTRIBUTE_READONLY) == 0)
|
||||||
buf->st_mode |= STD_WBITS;
|
buf->st_mode |= STD_WBITS;
|
||||||
|
if (real_path.issymlink ())
|
||||||
|
buf->st_mode |= S_IRWXU | S_IRWXG | S_IRWXO;
|
||||||
get_file_attribute (FALSE, real_path.get_win32 (),
|
get_file_attribute (FALSE, real_path.get_win32 (),
|
||||||
NULL, &buf->st_uid, &buf->st_gid);
|
NULL, &buf->st_uid, &buf->st_gid);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user