summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/path.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/path.cc')
-rw-r--r--winsup/cygwin/path.cc151
1 files changed, 77 insertions, 74 deletions
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 ();