Menu

#318 Improve handling of Windows "backward compatibility" junctions

open
nobody
None
5
2018-01-01
2017-12-28
No

Summary:
The more recent Windows versions (Vista or later) contain "backward compatibility" junctions. When running 7z.exe from the command line with -snl (Store symbolic links as links), I would expect 7zip to store those junctions as links inside the archive along with the link target (if supported by by archive type, e.g. tar).
However, 7zip prints an "Access is denied" warning for those junctions and fails to retrieve the link target.
The attached patch modifies the 7zip code so that retrieving the junction link works properly.
It also fixes a small glitch where 7zip prints a bogus error message "Error: The operation completed successfully" when processing a reparse point neither representing a junction nor a symbolic link.

Background:
From https://msdn.microsoft.com/en-us/library/windows/desktop/bb968829(v=vs.85).aspx :
"In Windows Vista and Windows Server 2008, the default locations for user data and system data have changed. For example, user data that was previously stored in the %SystemDrive%\Documents and Settings directory is now stored in the %SystemDrive%\Users directory. For backward compatibility, the old locations have junction points that point to the new locations. For example, C:\Documents and Settings is now a junction point that points to C:\Users. Backup applications must be capable of backing up and restoring junction points...."

=> These "backward compatibility" junctions are protected by a special ACL that denies "Read" to everyone. However, it's actually possible to retrieve the link target by requesting "zero" permissions when opening the junction file.

1 Attachments

Discussion

  • Igor Pavlov

    Igor Pavlov - 2017-12-30

    About changes in SetLinkInfo()

    "Error: The operation completed successfully" when processing a reparse point neither representing a junction nor a symbolic link.

    what is that reparse point?

    However, it's actually possible to retrieve the link target by requesting "zero" permissions when opening the junction file.

    Can "zero" permissions have some drawbacks in another cases?

     
  • Hartmut Honisch

    Hartmut Honisch - 2017-12-30

    About SetFileLink:
    For example on my Win10 installation, there's a reparse point at C:\Users\SomeUser\AppData\Local\Packages\Microsoft.Microsoft3DViewer_8wekyb3d8bbwe\LocalCache that's neither symlink nor junction. When you look at rhe Microsoft documentation for reparse point tags, there are a lot of different reparse point types, other than symlink or junction.(mount point).
    When 7z processes that reparse point, it currently prints the message:

    WARNING: The operation completed successfully.
    C:\Users\Festo\AppData\Local\Packages\Microsoft.Microsoft3DViewer_8wekyb3d8bbwe\LocalCache
    

    That's because NIO::GetReparseData(...) succeeds but attr.Parse(...) fails since it cannot parse the reparse data of a non-symlink non-junction reparse point. So currently, 7z leaves the reparse data buffer empty and logs a warning based on the last WinAPI error (GetLastError()), only in this case there was no WinAPI error, and GetLastError() returns 0 (Success = The operation completed successfully).
    I think we agree that this warning is quite meaningless to the user. So what should 7z do in that case? IMHO for the time being, it's better to log no warning message at all than a meaningless message. That's what the changes to SetFileLink implement.

    About the possbile drawback of requesting "zero" permissions when retrieving reparse data:
    I'm not aware of any drawbacks. I've done some testing on WIn7 and Win10 with "protected" and regular reparse points, and I couldn't find any problems.

     

    Last edit: Hartmut Honisch 2017-12-30
  • Igor Pavlov

    Igor Pavlov - 2017-12-30

    1) I suppuse we can change only FileIO.h:

      bool OpenReparse(CFSTR fileName)
      {
        // 17.02 fix: to support Windows XP compatibility junctions:
        //   we use Create() with (desiredAccess = 0) instead of Open() with GENERIC_READ
        return
            Create(fileName, 0,
            // Open(fileName,
            FILE_SHARE_READ, OPEN_EXISTING,
            FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS);
      }
    

    Is it OK?

    2) Yes, I want to get examples for such reparse points (other than symlink ot mount point) to test that code.

     
  • Hartmut Honisch

    Hartmut Honisch - 2017-12-30

    Re: 1) Yes, if you prefer that - I've done a quick test and it also worked for me.

    Re: 2) So far, I haven't found any non-symlink non-mount point reparse points other that the one I've mentioned before.

     

    Last edit: Hartmut Honisch 2017-12-30
  • Hartmut Honisch

    Hartmut Honisch - 2018-01-01

    I've played around with Windows 2016 Server's data deduplication, which also uses NTFS reparse points, a different type (IO_REPARSE_TAG_DEDUP).
    As of now, when I add deduped files to an archive using "7z.exe a -snl" , I get lot's of messages of the type WARNING: The operation completed successfully.
    Plus, the files in the 7z archive always end up having the attribute "sL" (symbolik Link) set - no matter whether I use the command line switch -snl (follow symlinks) or not.

    Because of these additional problems, I suggest that we exclude the changes to SetLinkInfo from this patch. I'll open a separate issue for those issues concerning reparse points that are neither symlink nor mount point.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.