处理 Windows 文件系统上的 unix 符号链接文件

Dealing with unix symlink files on Windows filesystem

我目前正在开发一个 Java 项目,该项目应该允许用户导出与 Windows 软件 (.exe) 或 OS X 应用程序 (.app) 捆绑的项目将数据分发到其他工作站。 Windows 和 OS X 软件都存储为压缩的 zip 文件,并在项目导出时解压缩。我的问题是,在 Windows 上解压缩 OS X 应用程序会破坏捆绑框架内的符号 link。这反过来会破坏应用程序的签名,并在应用程序在 OS X 上启动时导致问题。

我正在使用 Apache Commons 压缩库来解压缩包,这使我能够检测符号 links 及其目标。使用 OS X,我可以使用 java.nio.file.Files 中的方法重新创建符号 link,但是使用 Windows 这需要管理员权限,我有点犹豫添加为使用该软件的先决条件(即使启用我也不相信这会起作用 - 还没有尝试过)。

我对 link 损坏的原因有一点了解,但如果我理解正确的话 Windows 文件系统不包括对 Unix symbolic [=] 文件类型的支持32=],因此 link 被解压缩为普通文件,在 OS X.

上打开时将不再被识别为 symlink

所以,我的问题是我能否以某种方式将符号 link 文件按位复制到 Windows 文件系统以保留 Unix 特定位,或者完全不可能保留此信息?或者我应该只更改导出方法以将项目文件添加到现有的 zip 文件中,在这种情况下,symlink 信息可能会保留直到在目标机器上提取 zip 文件?

当前循环遍历 ZipFile 的每个 ZipArchiveEntry 的代码如下:

byte data[] = new byte[BUFFER];

Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();

while (entries.hasMoreElements()) {
    ZipArchiveEntry zipEntry = entries.nextElement();
    String destFilename = copyFolder + zipEntry.getName();
    File destFile = new File(destFilename);

    if (zipEntry.isUnixSymlink()) {             
        File target = new File(zipFile.getUnixSymlink(zipEntry));              
        try {   
            // Try to create symbolic link - currently only works with OS X
            Files.createSymbolicLink(destFile.toPath(), target.toPath());
            continue;
        } catch (Exception e) {
            System.out.println("Failed to create symbolic link: " + 
                destFile.getAbsolutePath() + " -> " + 
                target.getAbsolutePath());
        }
    }

    // If file
    int count;
    FileOutputStream fos = new FileOutputStream(destFile);

    try (BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER)) {
        InputStream is = zipFile.getInputStream(zipEntry);
        while ( (count = is.read(data, 0, BUFFER)) != -1) {
            dest.write(data, 0, count);
        }
    }
}

Windows 文件系统使用与 UNIX 类似的方法来定义什么是符号链接(如硬链接或软链接),但它们并非 100% 兼容。您可以在此处阅读更多相关信息:https://msdn.microsoft.com/en-us/library/windows/desktop/aa365680(v=vs.85).aspx 对你问题的简单回答 - 你不能只是按位复制链接以具有相同的 Unix 特定位,因为 Windows NTFS 没有它们。 JAVA 也被设计为在沙箱中工作,因此您无权访问系统低级别 API 以制作 "whatever you want"。我不会使用 JAVA 来完成此类特定于系统的任务。可能你不需要。

根据您在此项目中的角色,您可以重新定义包应包含的内容。你真的需要里面的符号链接吗?拥有某种将不同部分映射在一起的 "property" 文件可能更通用吗?或者将其作为数据库分发?尽量不要依赖于系统特定的实现。

您将需要一个 Windows 特定的和 "non-standard"(至少 Java)的方法来解决这个问题,因为没有标准的跨平台 Java 方式来解决。例如,您可以尝试在调用 "mklink" utility. The "mklink" command allows the creation of hard and soft(symbolic) links and also the creation of junctions- basically it creates the various types of re-parse points available to a Windows filesystem. If you are willing to access native code then you also may be able to use the pre-made JNA mapping to Kernel32.dll or write a custom mapping to Kernel32.dll and call the WinBase.h provided method CreateSymbolicLink(LPTSTR,LPTSTR,DWORD).

的同时使用 Runtime.exec

一般来说,我建议您尽可能避免在 Windows 上使用符号链接和硬链接。

符号链接和硬链接引入 Windows 很晚,对它的支持很差:

  • 大多数 Windows 用户不希望他们的文件系统中有符号链接
  • 符号链接仅在 NTFS 文件系统本地受支持,在其他文件系统(FAT、exFAT、UDF)或通过网络共享不受支持
  • 第三方工具(Zipper、备份工具、云同步软件)以及一些 Microsoft 软件(例如文件版本历史记录,即 Windows' "Time Machine";或 Windows copying/moving 文件夹时的资源管理器)无法处理符号链接或硬链接,要么解决它们,要么 crashing/showing 一条错误消息)。
  • 创建它们所需的权限因 Windows 版本而异(在 Windows 7 上,普通用户可以创建指向他可以访问的目录的符号链接(连接),但在 Windows XP无论如何都需要管理员权限)

因此,由于您只是暂时需要符号链接(如您在评论中所写),稍后再次压缩文件,我建议您在解压缩时创建自己的标记文件来表示符号链接,稍后当压缩您将它们转换回 ZIP 文件中的正确 UNIX 符号链接。