繁体   English   中英

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

[英]Dealing with unix symlink files on Windows filesystem

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

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

我对链接断开的原因有一点了解,但如果我理解正确的话,Windows 文件系统不包括对 Unix 符号链接文件类型的支持,因此链接被解压缩为普通文件,将不再在 OS X 上打开时被识别为符号链接。

所以,我的问题是,我能否以某种方式将符号链接文件按位复制到 Windows 文件系统,保留 Unix 特定位,或者完全不可能保留此信息? 或者我应该只更改导出方法以将项目文件添加到现有的 zip 文件中,在这种情况下,符号链接信息可能会保留到目标机器上提取 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以“制作”您想要的任何内容。 我不会用JAVA去做这样的系统特定任务。 可能你不必。

取决于您在此项目中的角色,您可以重新定义应包含的包。 你真的需要里面的符号链接吗? 可能更普遍的是有一些将不同部分映射在一起的“属性”文件? 或者将其作为数据库分发? 尽量不要依赖于系统特定的实现。

您将需要Windows特定的“非标准”(至少用于Java)方法来解决此问题,因为没有标准的跨平台Java方法来解决它。 例如,您可以尝试使用Runtime.exec以及对“mklink”实用程序的调用。 “mklink”命令允许创建硬和软(符号)链接以及结点的创建 - 基本上它创建了Windows文件系统可用的各种类型的重新解析点。 如果您愿意访问本机代码,那么您也可以使用预先制作的JNA映射到Kernel32.dll编写自定义映射到Kernel32.dll并调用WinBase.h提供的方法CreateSymbolicLink(LPTSTR,LPTSTR,DWORD)

一般来说,如果可能的话,我建议你尽量避免使用Windows上的符号链接和硬链接。

Symlinks和Hardlinks已经很晚才被引入Windows,对它的支持相当差:

  • 大多数Windows用户不希望文件系统中存在符号链接
  • 符号链接仅在NTFS文件系统上本地支持,而不支持在其他文件系统(FAT,exFAT,UDF)上或通过网络共享
  • 第三方工具(拉链,备份工具,云同步软件)以及一些Microsoft软件(例如文件版本历史记录,即Windows“Time Machine”;或复制/移动文件夹时的Windows资源管理器)无法处理符号链接或硬链接,要么解决它们,要么崩溃/显示错误消息)。
  • 创建它们所需的权限因Windows版本而异(在Windows 7上,普通用户可以创建一个符号链接(联结)到他可以访问的目录,但在Windows XP上,您在任何情况下都需要管理员权限)

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

已经 6 年了,如果你在 Windows 上压缩 macOS 应用程序包,然后在 Windows 上解压相同的 ZIP,它会保留 macOS 包中的别名文件(主要在 Frameworks 文件夹中)。

正如您所说,您还可以将 macOS 应用程序保留为 ZIP package,并让用户在需要时将其解压缩(最有可能在 macOS 上),那么它也可以工作。

在 Linux 上压缩 macOS 应用程序包并在 macOS 上解压缩也可以,但在 Windows 上不起作用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM