Tcl Source Code

View Ticket
Login
Ticket UUID: 972c35d41d10fa76718dfd67bf8db3ef10b85789
Title: file copy "permission denied" for Windows symlinks
Type: Bug Version: 8.6.2
Submitter: twylite Created on: 2015-11-23 09:50:11
Subsystem: 37. File System Assigned To: jan.nijtmans
Priority: 5 Medium Severity: Important
Status: Open Last Modified: 2015-11-23 10:54:31
Resolution: None Closed By: nobody
    Closed on:
Description:
The documented behavior of 'file copy' is "When copying within a single filesystem, file copy will copy soft links (i.e. the links themselves are copied, not the things they point to)."  On Windows 'file copy' fails to copy symlink directories, and copies the content (not the link) of symlink files.

Note: I am talking about Symbolic Links (https://msdn.microsoft.com/en-us/library/windows/desktop/aa365680(v=vs.85).aspx); not Hard Links, Junctions, or Shortcuts (.lnk).

Summary:
- file copy file-symlink dest -> copies content
- file copy dir-symlink dest -> illegal operation on a directory
- file copy dir-containing-file-symlink dest -> permission denied
- file copy dir-containing-dir-symlink dest -> permission denied

Expected behavior:
- Copy symlinks as documented in the man page

Environment:
- Windows 7 Enterprise, 64-bit on Intel
- NTFS ('fsutil fsinfo ntfsinfo c:' identifies version 3.1)
- tcl_patchLevel = 8.6.2

Steps to reproduce:

1. Open a command prompt using "Run As Administrator" (elevated privileges are required to create a symlink)
2. In a new folder:
  2.a. Create a folder 'res' : mkdir res
  2.b. In 'res' create a file 'foo.txt' : echo Hello > res\foo.txt
  2.c. Create a file symlink 'bar.txt' -> 'res\foo.txt' : mklink bar.txt res\foo.txt
  2.d. Create a folder 'src' : mkdir src
  2.e. Create a directory symlink 'src/myres' -> 'res' : mklink /D src\myres ..\res
  2.f. You should have the layout given by the 'dir /s' command below
3. Run wish/tclsh using "Run As Administrator"
  3.a. exec fsutil dirty query -> Should get a 'Usage' message if you have elevated permissions
  3.b. file copy bar.txt baz.txt -> succeeds, copies content not link
  3.c. file copy src/myres dest -> ERROR: error copying "src/myres" to "dest": illegal operation on a directory 
  3.d. file copy src dest -> ERROR: error copying "src" to "dest": "C:/Temp/tcllink/dest\myres": permission denied
  3.e. file copy src/myres dest -> ERROR: error copying "src/myres" to "dest/myres": illegal operation on a directory
"C:/Temp/tcllink/dest\myres": permission denied
4. Run wish/tclsh *not as Administrator* (so not from your open command prompt!)
  4.a. exec fsutil dirty query -> "The FSUTIL utility requires that you have administrative privileges"
  4.b. file copy bar.txt baz.txt -> succeeds, copies content not link
  4.c. file copy src/myres dest -> ERROR: error copying "src/myres" to "dest": illegal operation on a directory
  4.d. file copy src dest -> ERROR: error copying "src" to "dest/src": "C:/Temp/tcllink/dest/src\myres": permission denied
  4.e. file copy src/myres dest -> ERROR: error copying "src/myres" to "dest/myres": illegal operation on a directory


----- dir /s --------------------------------------------------
 Volume in drive C has no label.
 Volume Serial Number is EA57-23EF

 Directory of C:\Temp\tcllink

2015/11/23  11:27 AM    <DIR>          .
2015/11/23  11:27 AM    <DIR>          ..
2015/11/23  11:27 AM    <SYMLINK>      bar.txt [res\foo.txt]
2015/11/23  11:27 AM    <DIR>          res
2015/11/23  11:28 AM    <DIR>          src
               1 File(s)              0 bytes

 Directory of C:\Temp\tcllink\res

2015/11/23  11:27 AM    <DIR>          .
2015/11/23  11:27 AM    <DIR>          ..
2015/11/23  11:27 AM                 8 foo.txt
               1 File(s)              8 bytes

 Directory of C:\Temp\tcllink\src

2015/11/23  11:28 AM    <DIR>          .
2015/11/23  11:28 AM    <DIR>          ..
2015/11/23  11:28 AM    <SYMLINKD>     myres [..\res]
               0 File(s)              0 bytes

 Directory of C:\Temp\tcllink\src\myres

2015/11/23  11:27 AM    <DIR>          .
2015/11/23  11:27 AM    <DIR>          ..
2015/11/23  11:27 AM                 8 foo.txt
               1 File(s)              8 bytes
User Comments: jan.nijtmans added on 2015-11-23 10:54:31:
Since (as you are noting as well) using symlinks needs Administrator rights, not many people encounter this. Since Tcl doesn't use _wstat, it will require some careful investigation where in the Tcl code it actually goes wrong.

Thanks for the use-case! That really helps to devise a fix. No promise when I will take some time to have a look, supplying a patch will certainly help to speed up the process ;-)

twylite (claiming to be Twylite) added on 2015-11-23 10:14:26:

Related bug [3c13c4ed3149202f546a874457823389ba484be9]. That bug reported that: 'file delete $file' on a symbolic link to a directory fails with: "illegal operation on a directory"...

The bug was *incorrectly closed as invalid*. Steps to reproduce:

    1. Run As Administrator: command prompt
    1.a. mkdir res
    1.b. mklink /D src res
    2. tclsh
    2.a. exec fsutil dirty query -> Usage... (=> we have elevated permissions)
    2.b. file delete src -> error deleting "src": illegal operation on a directory

I suspect that (part of) the problem is that Windows/NTFS distinguishes between a symlink to a file (<SYMLINK>) and a symlink to a directory (<SYMLINKD>) (see https://en.wikipedia.org/wiki/NTFS_symbolic_link).

I see that the MSDN page on '_stat' claims that "_wstat does not work with Windows Vista symbolic links. In these cases, _wstat will always report a file size of 0. _stat does work correctly with symbolic links." (https://msdn.microsoft.com/en-us/library/14h5k7ff.aspx). The same page notes that st_mode is a bit mask, so it may be possible that a directory link sets both the ISDIR and ISLINK bits, but that's just a guess.