问题引入

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

思路分析

熟悉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. day31 Pyhton 总结

    # 什么是封装?     # 广义上(大家认为的) :         # 把一类事务的相同的行为和属性归到一个类中 # class Dog: #     def bite(self):pass    ...

  2. 安装ipython

    安装ipython,首先系统上已安装python 在这里,我们已安装python3 在windows下: pip intsall ipython 在linux下: sudo apt install p ...

  3. Java进阶专题(十五) 从电商系统角度研究多线程(下)

    前言 ​ 本章节继上章节继续梳理:线程相关的基础理论和工具.多线程程序下的性能调优和电商场景下多线程的使用. 多线程J·U·C ThreadLocal 概念 ​ ThreadLocal类并不是用来解决 ...

  4. 【认知服务 Azure Cognitive Service】使用认知服务的密钥无法访问语音服务[ErrorCode=AuthenticationFailure] (2020-08时的遇见的问题,2020-09月已解决)

    问题情形 根据微软认知服务的文档介绍,创建认知服务(Cognitive Service)后,可以调用微软的影像(计算机视觉,人脸),语言(LUIS, 文本分析,文本翻译),语音(文本转语音,语音转文本 ...

  5. 预编译 - Js三部曲

    预编译前奏 imply global - 暗示全局变量, window - 全局域 任何变量未经声明即赋值,该变量为全局所有 window 一切声明的 "全局" 变量,归windo ...

  6. Flutter - 自定义Dialog弹窗

    ------------恢复内容开始------------ Flutter - 自定义Dialog弹窗 应用场景:app系统版本升级弹窗,系统退出登录弹窗,首页广告弹窗,消息中心弹窗,删除文件弹窗等 ...

  7. D. The Wu 解析(思維、二進位運算)

    Codeforce 1017 D. The Wu 解析(思維.二進位運算) 今天我們來看看CF1017D 題目連結 題目 略,請直接看原題 前言 官方解答實在看不懂...之後還記得的話再補那個做法吧 ...

  8. SpringBoot连接多数据源(HBASE,KUDU,ORACLE集成和开发库)

    前提:1.连接hadoop需要本地安装 winutils.exe 并在程序指定,不然程序会报错  IOException: HADOOP_HOME or hadoop.home.dir are not ...

  9. 码农会锁,synchronized 对象头结构(mark-word、Klass Pointer)、指针压缩、锁竞争,源码解毒、深度分析!

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 感觉什么都不会,从哪开始呀! 这是最近我总能被问到的问题,也确实是.一个初入编程职场 ...

  10. 想用Nginx代理一切?行!

    Nginx能代理一切吗? 是的,Nginx可以作为一个优秀的http网关,但nginx能代理SSH2,MySQL,Oracle的连接吗?也算行吧,nginx有stream-module,专门处理TCP ...