问题引入

判断某个目录字符串是否是根目录,咋一听很简单,只要判断字符串是否是"/"即可,但是,很多情况下使用的路径是相对路径,那么如何判断相对路径是根目录呢?

思路分析

熟悉Linux的同学应该知道,每个目录下都有.和..两个目录,分别指代当前目录和父目录,考虑从这个点下手,根目录的当前目录和父目录指向相同,也就是说这两个文件的描述符是一样的。

大体思路有了之后,来看下Linux中常用的目录操作的函数:

1 DIR *opendir(const char *)
2 struct dirent *readdir(DIR *)
3 int closedir(DIR *)

它们位于dirent.h头文件中。

再来看一下dirent的结构

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 }

编译

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 *) 

修改代码后如下:

 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慢慢进行熟悉。

Linux程序开发中如何判断目录是否为根目录?的更多相关文章

  1. IOS开发中如何判断程序第一次启动(根据判断结果决定是否显示新手操作引导)

    IOS开发中如何判断程序第一次启动 在软件下载安装完成后,第一次启动往往需要显示一个新手操作引导,来告诉用户怎么操作这个app,这就需要在程序一开始运行就判断程序是否第一次启动,如果是,则显示新手操作 ...

  2. 在C#/.NET应用程序开发中创建一个基于Topshelf的应用程序守护进程(服务)

    本文首发于:码友网--一个专注.NET/.NET Core开发的编程爱好者社区. 文章目录 C#/.NET基于Topshelf创建Windows服务的系列文章目录: C#/.NET基于Topshelf ...

  3. 微信小程序开发教程 #043 - 在小程序开发中使用 npm

    本文介绍了如何在微信小程序开发中使用 npm 中包的功能,大大提高微信小程序的开发效率,同时也是微信小程序系列教程的视频版更新. 微信小程序在发布之初没有对 npm 的支持功能,这也是目前很多前端开发 ...

  4. 总结微信小程序开发中遇到的坑

    总结微信小程序开发中遇到的坑,一些坑你得一个一个的跳啊,/(ㄒoㄒ)/~~ 1,页面跳转和参数传递实例 首先说一下我遇到的需求有一个我的消息页面,里面的数据都是后端返回的,返回的数据大致如下,有一个是 ...

  5. IOS程序开发中-跳转到 发送短信界面 实现发短信

    前言:我发现我标题取的不好,谁帮我取个承接上下文的标题?评论一下,我改 项目需求:在程序开发中,我们需要在某个程序里面发送一些短信验证(不是接收短信验证,关于短信验证,传送门:http://www.c ...

  6. AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题

    AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子. 一 AOP的基本概念 (1)Asp ...

  7. Delphi 10.2 Linux 程序开发环境部署的基本步骤(网络连接方式要选择桥接或者是Host Only)

    Delphi 10.2 Linux 程序开发环境部署的基本步骤 http://blog.qdac.cc/?p=4477 升級到 Delphi 10.2 Tokyo 笔记http://www.cnblo ...

  8. 解决微信小程序开发中wxss中不能用本地图片

    微信小程序开发中wxss中不能用本地图片,我们可以用将我们的图片传到服务器上,然后直接引用在线地址.但是当我们没有服务器时,我们可以用"图床",这个具体可以百度.这里我们用第二种方 ...

  9. 程序开发中的术语,如IDE,OOP等等

    我们在开发程序过程中,会用到一些与编译有关的术语,比如:[编辑器.编译器.调试器.连接器,链接器.解释器,集成开发环境(Integrated Development Environment,IDE). ...

随机推荐

  1. day30 Pyhton 复习模块

    一.模块 什么是模块. 模块就是我们把装有特定功能的代码进行归类的结果. 从代码编写的单位来看我们的程序, 从小到大的顺序: 一条代码 < 语句句块 < 代码块(函数, 类) < 模 ...

  2. pytest文档46-关于https请求警告问题(InsecureRequestWarning: Unverified HTTPS request is being made)

    前言 使用 pytest 执行 https 请求用例的时候,控制台会出现警告:InsecureRequestWarning: Unverified HTTPS request is being mad ...

  3. 通过jQuery来获取DropDownList的Text/Value属性值

    脚本代码: <script src="Scripts/jquery-1.4.1-vsdoc.js" type="text/javascript">& ...

  4. MySQL数据库基础-3

    SQL语言 结构化的查询云烟 有国际标准. 非常容易学习的,关注数据本身,类似于shell SQL解释器 命令行效率比较高 应用编程接口 ODBC:Open Database Connectivity ...

  5. Linux配置阿里epl源

    去阿里云 有源仓库 阿里云镜像官方站点 https://developer.aliyun.com/mirror/ 先备份本机上的源 mv /etc/yum.repos.d/CentOS-Base.re ...

  6. SELECT INTO与INSERT INTO SELECT用法

    SELECT INTO SELECT INTO 语句从一个表复制数据,然后把数据插入到另一个新表中: -- 创建 Websites 的备份,这种写法没走索引导致全表扫描 SELECT * INTO W ...

  7. 支持向量机SVM基本问题

    1.SVM的原理是什么? SVM是一种二类分类模型.它的基本模型是在特征空间中寻找间隔最大化的分离超平面的线性分类器.(间隔最大是它有别于感知机) 试图寻找一个超平面来对样本分割,把样本中的正例和反例 ...

  8. 隐马尔科夫模型 HMM(Hidden Markov Model)

    本科阶段学了三四遍的HMM,机器学习课,自然语言处理课,中文信息处理课:如今学研究生的自然语言处理,又碰见了这个老熟人: 虽多次碰到,但总觉得一知半解,对其了解不够全面,借着这次的机会,我想要直接搞定 ...

  9. shell脚本之整数二次元比较操作符

    1.常用二次元比较操作符知识 我们也可以通过man test查看 提示: (1) ">"和"<"符号,在单括中需要转义,在双中括号中不需要转义,因为 ...

  10. 【新阁教育】基于ModbusTCP实现西门子1200PLC定位控制案例

    1. 引言 今天新阁教育给大家分享一个<基于ModbusTCP实现西门子1200PLC定位控制案例>,从PLC输入输出及步进电机接线开始,到PLC运动控制程序编写,再到后续的ModbusT ...