簡體   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