如何檢查給定路徑(絕對或相對)是否使用POSIX或標準C運行時調用指定卷的根目錄?理想情況下,代碼可以在Linux和Mac OS X上運行。如何檢查路徑是否指定卷根目錄
回答
首先,如果所提供的路徑是一個掛載點,並且該掛載點可能是也可能不是其文件系統的根目錄,那麼您可以使用標準函數進行真正的檢查。
假設你的系統的唯一f_fsid
值分配給每個安裝點,您可以使用POSIX-stanard statvfs()
function和f_fsid
領域比較與其父路徑組件的相關statvfs
structure的:
#include <stdlib.h>
#include <string.h>
#include <sys/statvfs.h>
int isMountPoint(const char *path)
{
struct statvfs sv1, sv2;
char *realP = realpath(path, NULL);
// if the real path is "/", yeah, it's the root
if (!strcmp(realP, "/"))
{
free(realP);
return(1);
}
statvfs(realP, &sv1);
// find the parent by truncating at the last "/"
char *pp = strrchr(realP, '/');
// if there is no parent, must be root
if (NULL == pp)
{
free(realP);
return(1);
}
// keep the final/(makes handling things like "/mnt"
// much easier)
pp++;
*pp = '\0';
statvfs(realP, &sv2);
free(realP);
// if f_fsid differs, it's the root of
// the mounted filesystem
return(sv1.f_fsid != sv2.f_fsid);
}
所有錯誤檢查留下來作爲練習(這也會讓這個例子變得更長,更難以理解......)。
如果某個路徑的f_fsid
與其父代的f_fsid
不同,或者路徑本身是根目錄,則傳入的路徑必須是其文件系統的掛載點。請注意,這不一定是文件系統的實際根目錄。例如,主機可以通過NFS導出文件系統,NFS客戶機可以將遠程文件系統中的任何子目錄作爲「本地根」掛載,或者回送掛載可以引用另一個文件系統的子目錄。
POSIX有一個realpath
函數,它返回任何給定路徑的規範路徑(從而消除/解決點,點,鏈接等)。
現在POSIX沒有定義卷,只有來自唯一給定根/
的文件名的層次結構。現在,Unix變體能夠在其他環境中安裝文件樹,以在運行時獲得單個樹。沒有標準的方法來「掛載」這些卷,即使mount
是一種非常常見的方式,因爲有很多方法可以實現此功能。因此,您必須閱讀OS變體的文檔,以確定如何獲取所有裝入點的列表。
您也可以閱讀Linux function to get mount points和How to get mount point information from an API on Mac?。
讓,這不回答這個問題,這實際上是問_a路徑實際上是一個安裝point_(根設備目錄只能是根目錄,或有什麼不一樣,安裝設備的根目錄)對不起,但我不得不倒下你的答案。 :/規範路徑不處理根目錄或掛載點,它只消除路徑中嵌入的'/../'和'/./'字符串,並保持其乾淨。 –
那麼,你有幾種方法。歷史上,根inode已經有2
inum,所以只需stat(path, &buf);
和檢查if (buf.st_ino == 2)
。
近年來,隨着不同的文件系統類型的增殖,沒有根inode中不必2
INUM同等的保修,所以你必須遵循一種不同的方法:只要檢查給出的路徑和父目錄(只是追加"/.."
到路徑)駐留在不同設備(場struct stat
信息st_dev
)
下面的代碼說明了這一:
:#include <unistd.h>
#include <limits.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
int is_mount(char *path)
{
struct stat sdir; /* inode info */
struct stat spdir; /* parent inode info */
char buffer[PATH_MAX];
int res = stat(path, &sdir);
if (res < 0) return -1;
if (snprintf(buffer, sizeof buffer, "%s/..", path) >= sizeof buffer) {
errno = ENAMETOOLONG;
return -1;
}
res = stat(buffer, &spdir);
if (res < 0) return -1;
return sdir.st_dev != spdir.st_dev; /* SEE ADDITIONAL NOTE */
}
int main(int argc, char **argv)
{
int i;
for (i = 1; i < argc; i++) {
int res = is_mount(argv[i]);
if (res < 0) {
fprintf(stderr,
"%s: %s (errno = %d)\n",
argv[i], strerror(errno), errno);
continue;
}
printf("%5s\t%s\n", res ? "true" : "false", argv[i]);
} /* for */
} /* main */
FreeBSD系統上執行
$ ismount /home/luis/usr.ports/german/geonext/Makefile /home/luis/usr.ports/german/geonext /home/luis/usr.ports/german /home/luis/usr.ports /home/luis /home//var/run/cups /var/run /var pru3.c
/home/luis/usr.ports/german/geonext/Makefile: Not a directory (errno = 20)
pru3.c: Not a directory (errno = 20)
false /home/luis/usr.ports/german/geonext
false /home/luis/usr.ports/german
true /home/luis/usr.ports
false /home/luis
false /home
true / <-- in the above code, this returns false, see ADDITIONAL NOTE.
false /var/run/cups
true /var/run
false /var
PORTABILITY注意
這應該在任何未* X/Linux上實現了stat(2)
系統調用工作。 UNIX v7已經實現了這個功能,所以它應該可以在所有可用的unices中找到。
附加註釋
這種方法不適用於實際的文件系統的根目錄(/
),因爲工作的父目錄和根目錄都指向相同的inode。這可以通過檢查父節點和子節點的st_ino
是否相等來解決。只要改變測試
return (sdir.st_dev != spdir.st_dev) /* different devices */
|| (/* sdir.st_dev == spdir.st_dev && ---redundant */
sdir.st_ino == spdir.st_ino); /* root dir case */
感謝您的廣泛答覆!我對Linux不太熟悉,所以我不能確定你或Andrew Henle的答案是否是最好的方法。你的答案對安德魯和安德魯的影響有沒有優勢?我沒有足夠的經驗來告訴Linux。 – Andreas
任何方法都不錯。恕我直言,礦區更保守,因爲它只使用舊的unix系統調用,所以它應該更便攜,但其中任何一個都應該同樣有用。我測試過我的,當路徑不是目錄路徑時(文件未找到,例如由於權限導致目錄不能訪問文件),它會正確調度。就我個人而言,我更喜歡追加「/」的方法。 「,而不是在最後一個路徑元素上切割它。在缺少它的系統中,你將無法使用'statvfs(2)'(但它們中很少有) –
- 1. 如何檢查路徑的目標是否是目錄?
- 2. 如何檢查目錄是否在Bash的路徑上?
- 3. c#檢查給定的文件路徑是否包含根目錄
- 4. c#檢查文件路徑是否包含特定目錄
- 5. CLIPS:檢查目錄路徑
- 6. 檢查目錄路徑是相同的
- 7. 如何檢查這是目錄路徑還是任何文件名路徑?
- 8. node.js - TypeError:路徑必須是絕對路徑或指定根目錄res.sendFile
- 9. 檢查路徑是否是Swift2中的目錄?
- 10. 如何檢查字符串是否指定目錄?
- 11. rails應用程序,更改根目錄/指定根路徑
- 12. 檢查根目錄是否凍結
- 13. C#FTP,如何檢查路徑是文件還是目錄?
- 14. .NET如何檢查路徑是文件而不是目錄?
- 15. 檢索WordPress根目錄路徑?
- 16. RequireJS - 檢查路徑是否定義
- 17. 如何檢查給定路徑是否存在路由(ASP.NET MVC)?
- 18. 驗證是否路徑指向另一個路徑給定目錄
- 19. 如何檢查路徑是否指向文件夾或文件?
- 20. 如何檢查路徑是否指向本地文件對象?
- 21. 檢查一個目錄是否存在遞歸反轉路徑
- 22. 檢查目錄是否存在動態路徑
- 23. 檢查一個目錄是否存在絕對路徑
- 24. 檢查是否URL UNC目錄路徑存在
- 25. 如何檢查xml節點是否是asp.net中的根目錄
- 26. 檢查是否有用戶訪問指定的MVC路徑
- 27. 的Python:如何檢查是否路徑的子路徑
- 28. 如何檢查給定的路徑是否指向現有的文件OR目錄?
- 29. 檢測用戶的路徑中是否有特定的目錄
- 30. 如何檢查目錄下是否存在特定目錄?
謝謝,這在Linux和Mac OS上都能正常工作。我已經糾正了代碼中的兩個小錯誤,我想這些錯誤也會作爲練習留給讀者:) – Andreas