Linux程序开发中如何判断目录是否为根目录?
mycodes · 642浏览 · 发布于2020-11-19
问题引入
判断某个目录字符串是否是根目录,咋一听很简单,只要判断字符串是否是"/"即可,但是,很多情况下使用的路径是相对路径,那么如何判断相对路径是根目录呢?
思路分析
熟悉Linux的同学应该知道,每个目录下都有.和..两个目录,分别指代当前目录和父目录,考虑从这个点下手,根目录的当前目录和父目录指向相同,也就是说这两个文件的描述符是一样的。
大体思路有了之后,来看下Linux中常用的目录操作的函数:
1 DIR *opendir(const char *)2 struct dirent *readdir(DIR *)3 int closedir(DIR *)
它们位于dirent.h头文件中。
再来看一下dirent的结构
struct dirent { ino_t d_ino; /* file number of entry */ __uint16_t d_reclen; /* length of this record */ __uint8_t d_type; /* file type, see below */ __uint8_t d_namlen; /* length of string in d_name */ char d_name[__DARWIN_MAXNAMLEN + 1]; /* name must be no longer than this */ };
解决方案
开始动手编码,如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <dirent.h> bool isRoot(const char* path) { if (strcmp(path, "/") == 0) return true; char dp[256] = {0}; int l = strlen(path); memcpy(dp, path, l); if (dp[l - 1] != '/') { dp[l] = '/'; l += 1; } DIR* d = opendir(dp); if (!d) { printf("failed to open dir\n"); return false; } uint64_t dino = 0, ddino = 0; while (dirent* ent = readdir(d)) { if (strcmp(ent->d_name, "..") == 0) { ddino = ent->d_ino; } if (strcmp(ent->d_name, ".") == 0) { dino = ent->d_ino; } if (dino > 0 && ddino > 0) break; } return dino == ddino && dino != 0; } int main(int argc, char* argv[]) { if (argc != 2) { printf("usage : app path\n"); return 0; } if (isRoot(argv[1])) printf("this path is root\n"); else printf("this path is not root\n"); return 0; }
编译
g++ -o root root.cpp
下面来验证一下
# ./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。
. 2.. 1
难道是假设错误?如果想要取得inode可以通过stat函数,那么我们该用stat函数试一下
int stat(const char *, struct stat *)
修改代码后如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <dirent.h> #include <sys/stat.h> bool isRoot(const char* path) { if (strcmp(path, "/") == 0) return true; char dp[256] = {0}; int l = strlen(path); memcpy(dp, path, l); if (dp[l - 1] != '/') { dp[l] = '/'; l += 1; } DIR* d = opendir(dp); if (!d) { printf("failed to open dir\n"); return false; } uint64_t dino = 0, ddino = 0; while (dirent* ent = readdir(d)) { if (strcmp(ent->d_name, "..") == 0) { char pp[256] = {0}; memcpy(pp, dp, l); pp[l] = '.'; pp[l + 1] = '.'; struct stat s; stat(pp, &s); //printf("ddot %s %lld\n", ent->d_name, s.st_ino); ddino = s.st_ino; } if (strcmp(ent->d_name, ".") == 0) { char sp[256] = {0}; memcpy(sp, dp, l); sp[l] = '.'; struct stat s; stat(sp, &s); //printf("dot %s %lld\n", ent->d_name, s.st_ino); dino = s.st_ino; } if (dino > 0 && ddino > 0) break; } return dino == ddino && dino != 0; } int main(int argc, char* argv[]) { if (argc != 2) { printf("usage : app path\n"); return 0; } if (isRoot(argv[1])) printf("this path is root\n"); else printf("this path is not root\n"); return 0; }
再次编译验证,发现这次的结果是正确的。经过查证后发现,在使用readdir时取得的dirent中的iNode不一定是正确的,还需要从stat中取。其实在isRoot中没有必要使用dir相关的操作,只需要组织出输入路径的当前路径和父目录,再使用stat判断即可。
总结
到此就完成了目录是否为根目录的判断,需要对Linux的API慢慢进行熟悉。
相关推荐
将Fedora 29升级到Fedora 30
吴振华 · 702浏览 · 2019-05-14 22:00:02
有效避免数据丢失!Redis持久化方案选择详解
manongba · 916浏览 · 2019-05-15 10:58:03
使用Nginx反向代理到go-fastdfs
iamitnan · 724浏览 · 2019-05-23 13:42:00
利用VLC搭建组播流服务器
追忆似水年华 · 2691浏览 · 2019-06-14 11:27:06
如何设计一个优秀的分布式系统?重要因素、工具、策略都在这里
chenguangming9 · 712浏览 · 2019-06-18 11:00:10
用Bash脚本监控Linux上的内存使用情况
吴振华 · 972浏览 · 2019-06-24 11:27:02
分类专栏
最新发布
最热排行
0评论