2011-06-11 40 views
1

我需要的,如果不存在,它創建文件夾的mkdir,所以我用:只在程序第一次運行時創建統計VS與EEXIST

bool mkdir_if_not_exist(const char *dir) 
{ 
    bool ret = false; 
    if (dir) { 
    // first check if folder exists 
    struct stat folder_info; 
    if (stat(dir, &folder_info) != 0) { 
    if (errno == ENOENT) { // create folder 
     if (mkdir(dir, S_IRWXU | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH) ?!= 0) // 755 
     perror("mkdir"); 
     else 
     ret = true; 
    } else 
     perror("stat"); 
    } else 
     ret = true; ?// dir exists 
    } 
    return ret; 
} 

文件夾 - 畢竟,這只是一個檢查。 有一個建議,跳過統計調用,並調用mkdir和檢查errno反對EEXIST。 它給了真正的好處嗎?

回答

1

有一點好處。查看'LBYL vs EAFP'或'先看你跳躍'vs'容易要求寬恕而不是權限'。

微小的好處是系統調用必須解析目錄名並進入inode--或者在這種情況下缺少inode - 然後mkdir()必須執行相同的操作。當然,mkdir()所需的數據已經存在於內核緩衝池中,但它仍然涉及指定路徑的兩次遍歷而不是一次。因此,在這種情況下,使用EAFP比使用LBYL稍微高效一些。

但是,這對平均計劃是否真的是一個可衡量的影響是非常值得商榷的。如果你什麼都不做,只是在整個地方創建目錄,那麼你可能會發現一個好處。但是,如果您在程序開始時創建單個目錄,這絕對是一個小小的影響,基本上無法衡量。

您可能需要處理strcmp(dir, "/some/where/or/another") == 0但存在"/some/where"的情況,"/some/where/or"和(必要)"/some/where/or/another"都不存在。您當前的代碼不處理路徑中間缺少的目錄。它只是報告mkdir()將報告的ENOENT。你的代碼看起來並不檢查dir實際上是否是一個目錄,它只是假定它存在就是一個目錄。正確處理這些變化是棘手的。

1

更重要的是,與stat + mkdir的做法,有一個競爭條件:在statmkdir之間的其他程序可以做mkdir,所以你mkdir仍可能會失敗,EEXIST

0

Race condition with stat and mkdir in sequence類似,您的解決方案不僅僅是由於競爭條件(正如其他答案已經指出的那樣)不正確,還因爲您從不檢查現有文件是否爲目錄。

當重新實現UNIX中現有命令行工具中已廣泛使用的功能時,首先了解它是如何在這些工具中實現的,總是很有幫助。

例如,看看mkdir(1)-p option是如何在BSD系統(bin/mkdir/mkdir.c#mkpath in OpenBSDNetBSD),所有這一切,對mkdir(2)'s錯誤,似乎馬上打電話stat(2)隨後運行S_ISDIR宏來實現,以確保現有文件一個目錄,而不僅僅是任何其他類型的文件。