问题引入判断某个目录字符串是否是根目录,咋一听很简单,只要判断字符串是否是"/"即可,但是,很多情况下使用的路径是相对路径,那么如何判断相对路径是根目录呢?熟悉Linux的同学应该知道,每个目录下都有.和..两个目录,分别指代当前目录和父
问题引入
判断某个目录字符串是否是根目录,咋一听很简单,只要判断字符串是否是"/"即可,但是,很多情况下使用的路径是相对路径,那么如何判断相对路径是根目录呢?
思路分析
熟悉Linux的同学应该知道,每个目录下都有.和..两个目录,分别指代当前目录和父目录,考虑从这个点下手,根目录的当前目录和父目录指向相同,也就是说这两个文件的描述符是一样的。
大体思路有了之后,来看下Linux中常用的目录操作的函数:
1 DIR *opendir(const char *)2 struct dirent *readdir(DIR *)3 int closedir(DIR *)
它们位于dirent.h头文件中。
再来看一下dirent的结构
1 structdirent {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
2 #include
3 #include
4 #include
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 }
编译
g++ -o root root.cpp
下面来验证一下
# ./root /
this path isroot
# ./root ./
this path isnot root
# ./root ./../
this path isnot root
# ./root ./../../
this path isnot root
# ./root ./../../../
this path isnot root
# ./root ./../../../.. #注意,我的机器上这里其实已经是根目录了this path is not root
奇怪的问题发生了,本应该通过的内容竟然不是根目录。进入代码,打印一下isRoot函数中.和..目录的name和ino。
. 2..1
难道是假设错误?如果想要取得inode可以通过stat函数,那么我们该用stat函数试一下
int stat(const char *, struct stat *)
修改代码后如下:
1 #include
2 #include
3 #include
4 #include
5 #include
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 structstat 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 structstat 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慢慢进行熟悉。
以上信息来源于网络,如有侵权,请联系站长删除。