判斷某個目錄字符串是不是根目錄,咋一聽很簡單,只要判斷字符串是不是"/"便可,可是,不少狀況下使用的路徑是相對路徑,那麼如何判斷相對路徑是根目錄呢?node
熟悉Linux的同窗應該知道,每一個目錄下都有.和..兩個目錄,分別指代當前目錄和父目錄,考慮從這個點下手,根目錄的當前目錄和父目錄指向相同,也就是說這兩個文件的描述符是同樣的。app
大致思路有了以後,來看下Linux中經常使用的目錄操做的函數:函數
1 DIR *opendir(const char *) 2 struct dirent *readdir(DIR *) 3 int closedir(DIR *)
它們位於dirent.h頭文件中。ui
再來看一下dirent的結構this
1 struct dirent { 2 ino_t d_ino; /* file number of entry */ 3 __uint16_t d_reclen; /* length of this record */ 4 __uint8_t d_type; /* file type, see below */ 5 __uint8_t d_namlen; /* length of string in d_name */ 6 char d_name[__DARWIN_MAXNAMLEN + 1]; /* name must be no longer than this */ 7 };
開始動手編碼,以下:編碼
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <dirent.h> 5 6 bool isRoot(const char* path) 7 { 8 if (strcmp(path, "/") == 0) 9 return true; 10 11 char dp[256] = {0}; 12 int l = strlen(path); 13 memcpy(dp, path, l); 14 15 if (dp[l - 1] != '/') 16 { 17 dp[l] = '/'; 18 l += 1; 19 } 20 21 DIR* d = opendir(dp); 22 if (!d) 23 { 24 printf("failed to open dir\n"); 25 return false; 26 } 27 28 uint64_t dino = 0, ddino = 0; 29 while (dirent* ent = readdir(d)) 30 { 31 if (strcmp(ent->d_name, "..") == 0) 32 { 33 ddino = ent->d_ino; 34 } 35 if (strcmp(ent->d_name, ".") == 0) 36 { 37 dino = ent->d_ino; 38 } 39 40 if (dino > 0 && ddino > 0) 41 break; 42 } 43 return dino == ddino && dino != 0; 44 } 45 46 int main(int argc, char* argv[]) 47 { 48 if (argc != 2) 49 { 50 printf("usage : app path\n"); 51 return 0; 52 } 53 54 if (isRoot(argv[1])) 55 printf("this path is root\n"); 56 else 57 printf("this path is not root\n"); 58 return 0; 59 }
編譯spa
g++ -o root root.cpp
下面來驗證一下code
# ./root / this path is root # ./root ./ this path is not root # ./root ./../ this path is not root # ./root ./../../ this path is not root # ./root ./../../../ this path is not root # ./root ./../../../.. #注意,個人機器上這裏其實已是根目錄了 this path is not root
奇怪的問題發生了,本應該經過的內容居然不是根目錄。進入代碼,打印一下isRoot函數中.和..目錄的name和ino。blog
. 2 .. 1
難道是假設錯誤?若是想要取得inode能夠經過stat函數,那麼咱們該用stat函數試一下字符串
int stat(const char *, struct stat *)
修改代碼後以下:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <dirent.h> 5 #include <sys/stat.h> 6 7 bool isRoot(const char* path) 8 { 9 if (strcmp(path, "/") == 0) 10 return true; 11 12 char dp[256] = {0}; 13 int l = strlen(path); 14 memcpy(dp, path, l); 15 16 if (dp[l - 1] != '/') 17 { 18 dp[l] = '/'; 19 l += 1; 20 } 21 22 DIR* d = opendir(dp); 23 if (!d) 24 { 25 printf("failed to open dir\n"); 26 return false; 27 } 28 uint64_t dino = 0, ddino = 0; 29 while (dirent* ent = readdir(d)) 30 { 31 if (strcmp(ent->d_name, "..") == 0) 32 { 33 char pp[256] = {0}; 34 memcpy(pp, dp, l); 35 pp[l] = '.'; 36 pp[l + 1] = '.'; 37 struct stat s; 38 stat(pp, &s); 39 //printf("ddot %s %lld\n", ent->d_name, s.st_ino); 40 ddino = s.st_ino; 41 } 42 if (strcmp(ent->d_name, ".") == 0) 43 { 44 char sp[256] = {0}; 45 memcpy(sp, dp, l); 46 sp[l] = '.'; 47 struct stat s; 48 stat(sp, &s); 49 //printf("dot %s %lld\n", ent->d_name, s.st_ino); 50 dino = s.st_ino; 51 } 52 53 if (dino > 0 && ddino > 0) 54 break; 55 } 56 return dino == ddino && dino != 0; 57 } 58 59 int main(int argc, char* argv[]) 60 { 61 if (argc != 2) 62 { 63 printf("usage : app path\n"); 64 return 0; 65 } 66 67 if (isRoot(argv[1])) 68 printf("this path is root\n"); 69 else 70 printf("this path is not root\n"); 71 return 0; 72 } 73
再次編譯驗證,發現此次的結果是正確的。通過查證後發現,在使用readdir時取得的dirent中的iNode不必定是正確的,還須要從stat中取。
到此就完成了目錄是否爲根目錄的判斷,須要對Linux的API慢慢進行熟悉。