2010-07-22 67 views
0

我看到一些古老的代碼,simplifed Unix的路徑比較通過執行類似下面的僞代碼:Unix的線程安全路徑比較或規範化函數?

  • 剝去最後一個路徑組件獲取目錄僅部分:/富/酒吧 - > /富
  • GETCWD並記住原路徑
  • CHDIR /富
  • GETCWD並記住返回主調
  • CHDIR老原路徑

是否有一個標準的Unix系統函數可以完成所有這些,而不會導致線程不安全的當前目錄操作?

互斥體可能會使該代碼序列線程不安全,但並不是非常理想(您必須知道使用getcwd或依賴於進程cwd的其他函數(包括系統和供應商代碼)保護的所有其他代碼相同的互斥體)。

回答

2

realpath(3)怎麼樣?

由於它將結果返回給您提供的緩衝區,因此線程安全性不應該成爲問題。

+0

很酷,不知道這個庫函數 – eruciform 2010-07-22 16:57:33

+0

我曾經知道realpath()並忘記了它。它沒有用處(因而不值得記住)的原因在於它在某些平臺上也不是線程安全的(基本上使用所描述的被破壞的chdir'ing機制)。 – 2010-07-22 17:47:07

+0

嗯。我現在在我們的代碼中看到了對該函數的調用。也許它現在在我們關心的所有平臺上都是線程安全的(幾年前這絕對不是這種情況,但我不記得具體情況)。 – 2010-07-22 17:55:46

0

哦,親愛的,做你提到的動作不可能是線程安全的,因爲它實際上是chdir的,這會混淆其他線程。我將不得不查找所需的字符串操作部分,但它不可能剝離軟鏈接或執行其他任何操作系統要求的文件信息而不會造成線程不安全的情況。

相關文章:

嘗試使用此方法相對文件路徑轉換,然後將它們的比較結果爲字符串:

#include<stdio.h> 
#include<dirent.h> 
#include<fcntl.h> 
#include<sys/param.h> 
int main(int argc, char **argv) 
{ 
    char buffer[MAXPATHLEN+1]; 
    if(argc <= 1) return 0; 
    DIR*d = opendir(argv[1]); 
    if(!d) return 0; 
    int dfd = dirfd(d); 
    if(!dfd) return 0; 
    int result = fcntl(dfd, F_GETPATH, buffer); 
    if(result == -1) return 0; 
    fprintf(stdout, "path='%s'\n", buffer); 
    return 0; 
} 
+0

我知道這不是線程安全的。如果存在這樣的功能,我相信它必須是一個系統調用,可以以更直接的方式進行查找。 – 2010-07-22 16:39:44

+0

看起來像別人發佈了一個快捷方式,但我懷疑它是這樣做的:-) – eruciform 2010-07-22 16:57:11

2

嘗試realpath()canonicalize_file_name()

如果您的系統支持它(很可能如此),我建議叫realpath(pathname, NULL);這將爲malloc規範化文件名的緩衝區並將其作爲返回值傳回。你必須確定free()的指針。另一種方法是通過輸出緩衝區,存在緩衝區溢出的風險。

canonicalize_file_name()是一個Gnu擴展,相當於realpath(pathname, NULL)

+1

請注意,傳入輸出緩衝區時,只會出現緩衝區溢出的風險,因爲系統中PATH_MAX或者太大, malloc()'或完全無界。 – caf 2010-07-23 00:59:46

0

Unix目錄中沒有「規範」路徑。文件/目錄可能有多個硬鏈接/掛載點。

與文件/目錄的身份最接近的是它的inode。