Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose the "deep-copy" symlink behavior via a new winsymlinks mode #16

Merged
merged 2 commits into from
Oct 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions winsup/cygwin/environ.cc
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ set_winsymlinks (const char *buf)
else if (ascii_strncasematch (buf, "native", 6))
allow_winsymlinks = ascii_strcasematch (buf + 6, "strict")
? WSYM_nativestrict : WSYM_native;
else if (ascii_strncasematch (buf, "deepcopy", 8))
allow_winsymlinks = WSYM_deepcopy;
else
allow_winsymlinks = WSYM_sysfile;
}

/* The structure below is used to set up an array which is used to
Expand Down
5 changes: 3 additions & 2 deletions winsup/cygwin/globals.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ enum winsym_t
WSYM_lnk,
WSYM_native,
WSYM_nativestrict,
WSYM_nfs
WSYM_nfs,
WSYM_deepcopy
};

exit_states NO_COPY exit_state;
Expand All @@ -69,7 +70,7 @@ bool ignore_case_with_glob;
bool pipe_byte;
bool reset_com;
bool wincmdln = true;
winsym_t allow_winsymlinks = WSYM_sysfile;
winsym_t allow_winsymlinks = WSYM_deepcopy;
bool disable_pcon = true;

bool NO_COPY in_forkee;
Expand Down
141 changes: 70 additions & 71 deletions winsup/cygwin/path.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1958,7 +1958,6 @@ typedef struct _REPARSE_LX_SYMLINK_BUFFER
} LxSymlinkReparseBuffer;
} REPARSE_LX_SYMLINK_BUFFER,*PREPARSE_LX_SYMLINK_BUFFER;

#ifndef __MSYS__
static int
symlink_wsl (const char *oldpath, path_conv &win32_newpath)
{
Expand Down Expand Up @@ -2029,7 +2028,6 @@ symlink_wsl (const char *oldpath, path_conv &win32_newpath)
NtClose (fh);
return 0;
}
#endif

int
symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
Expand Down Expand Up @@ -2114,7 +2112,6 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
}
/* Otherwise, fall back to default symlink type. */
wsym_type = WSYM_sysfile;
#ifndef __MSYS__
fallthrough;
case WSYM_sysfile:
if (win32_newpath.fs_flags () & FILE_SUPPORTS_REPARSE_POINTS)
Expand All @@ -2126,7 +2123,6 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
/* On FSes not supporting reparse points, or in case of an error
creating the WSL symlink, fall back to creating the plain old
SYSTEM file symlink. */
#endif
break;
default:
break;
Expand Down Expand Up @@ -2269,73 +2265,76 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
}
else
{
path_conv src_path;
src_path.check (oldpath, PC_SYM_NOFOLLOW, stat_suffixes);
if (src_path.error)
{
set_errno (src_path.error);
__leave;
}
if (!src_path.isdevice () && !src_path.is_fs_special ())
{
/* MSYS copy file instead make symlink */

char * real_oldpath;
if (isabspath (oldpath))
strcpy (real_oldpath = tp.c_get (), oldpath);
else
/* Find the real source path, relative
to the directory of the destination */
{
/* Determine the character position of the last path component */
const char *newpath = win32_newpath.get_posix();
int pos = strlen (newpath);
while (--pos >= 0)
if (isdirsep (newpath[pos]))
break;
/* Append the source path to the directory
component of the destination */
if (pos+1+strlen(oldpath) >= MAX_PATH)
{
set_errno(ENAMETOOLONG);
__leave;
}
strcpy (real_oldpath = tp.c_get (), newpath);
strcpy (&real_oldpath[pos+1], oldpath);
}

/* As a MSYS limitation, the source path must exist. */
path_conv win32_oldpath;
win32_oldpath.check (real_oldpath, PC_SYM_NOFOLLOW, stat_suffixes);
if (!win32_oldpath.exists ())
{
set_errno (ENOENT);
__leave;
}

char *w_newpath;
char *w_oldpath;
stpcpy (w_newpath = tp.c_get (), win32_newpath.get_win32());
stpcpy (w_oldpath = tp.c_get (), win32_oldpath.get_win32());
if (win32_oldpath.isdir())
{
char *origpath;
strcpy (origpath = tp.c_get (), w_oldpath);
res = recursiveCopy (w_oldpath, w_newpath, origpath);
}
else
{
if (!CopyFile (w_oldpath, w_newpath, FALSE))
{
__seterrno ();
}
else
{
res = 0;
}
}
__leave;
}
if (wsym_type == WSYM_deepcopy)
{
path_conv src_path;
src_path.check (oldpath, PC_SYM_NOFOLLOW, stat_suffixes);
if (src_path.error)
{
set_errno (src_path.error);
__leave;
}
if (!src_path.isdevice () && !src_path.is_fs_special ())
{
/* MSYS copy file instead make symlink */

char * real_oldpath;
if (isabspath (oldpath))
strcpy (real_oldpath = tp.c_get (), oldpath);
else
/* Find the real source path, relative
to the directory of the destination */
{
/* Determine the character position of the last path component */
const char *newpath = win32_newpath.get_posix();
int pos = strlen (newpath);
while (--pos >= 0)
if (isdirsep (newpath[pos]))
break;
/* Append the source path to the directory
component of the destination */
if (pos+1+strlen(oldpath) >= MAX_PATH)
{
set_errno(ENAMETOOLONG);
__leave;
}
strcpy (real_oldpath = tp.c_get (), newpath);
strcpy (&real_oldpath[pos+1], oldpath);
}

/* As a MSYS limitation, the source path must exist. */
path_conv win32_oldpath;
win32_oldpath.check (real_oldpath, PC_SYM_NOFOLLOW, stat_suffixes);
if (!win32_oldpath.exists ())
{
set_errno (ENOENT);
__leave;
}

char *w_newpath;
char *w_oldpath;
stpcpy (w_newpath = tp.c_get (), win32_newpath.get_win32());
stpcpy (w_oldpath = tp.c_get (), win32_oldpath.get_win32());
if (win32_oldpath.isdir())
{
char *origpath;
strcpy (origpath = tp.c_get (), w_oldpath);
res = recursiveCopy (w_oldpath, w_newpath, origpath);
}
else
{
if (!CopyFile (w_oldpath, w_newpath, FALSE))
{
__seterrno ();
}
else
{
res = 0;
}
}
__leave;
}
}

/* Default technique creating a symlink. */
buf = tp.t_get ();
Expand Down