Linux程序开发中如何判断目录是否为根目录?
问题引入
判断某个目录字符串是否是根目录,咋一听很简单,只要判断字符串是否是"/"即可,但是,很多情况下使用的路径是相对路径,那么如何判断相对路径是根目录呢?
思路分析
熟悉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程序开发中如何判断目录是否为根目录?的更多相关文章
- IOS开发中如何判断程序第一次启动(根据判断结果决定是否显示新手操作引导)
IOS开发中如何判断程序第一次启动 在软件下载安装完成后,第一次启动往往需要显示一个新手操作引导,来告诉用户怎么操作这个app,这就需要在程序一开始运行就判断程序是否第一次启动,如果是,则显示新手操作 ...
- 在C#/.NET应用程序开发中创建一个基于Topshelf的应用程序守护进程(服务)
本文首发于:码友网--一个专注.NET/.NET Core开发的编程爱好者社区. 文章目录 C#/.NET基于Topshelf创建Windows服务的系列文章目录: C#/.NET基于Topshelf ...
- 微信小程序开发教程 #043 - 在小程序开发中使用 npm
本文介绍了如何在微信小程序开发中使用 npm 中包的功能,大大提高微信小程序的开发效率,同时也是微信小程序系列教程的视频版更新. 微信小程序在发布之初没有对 npm 的支持功能,这也是目前很多前端开发 ...
- 总结微信小程序开发中遇到的坑
总结微信小程序开发中遇到的坑,一些坑你得一个一个的跳啊,/(ㄒoㄒ)/~~ 1,页面跳转和参数传递实例 首先说一下我遇到的需求有一个我的消息页面,里面的数据都是后端返回的,返回的数据大致如下,有一个是 ...
- IOS程序开发中-跳转到 发送短信界面 实现发短信
前言:我发现我标题取的不好,谁帮我取个承接上下文的标题?评论一下,我改 项目需求:在程序开发中,我们需要在某个程序里面发送一些短信验证(不是接收短信验证,关于短信验证,传送门:http://www.c ...
- AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题
AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子. 一 AOP的基本概念 (1)Asp ...
- Delphi 10.2 Linux 程序开发环境部署的基本步骤(网络连接方式要选择桥接或者是Host Only)
Delphi 10.2 Linux 程序开发环境部署的基本步骤 http://blog.qdac.cc/?p=4477 升級到 Delphi 10.2 Tokyo 笔记http://www.cnblo ...
- 解决微信小程序开发中wxss中不能用本地图片
微信小程序开发中wxss中不能用本地图片,我们可以用将我们的图片传到服务器上,然后直接引用在线地址.但是当我们没有服务器时,我们可以用"图床",这个具体可以百度.这里我们用第二种方 ...
- 程序开发中的术语,如IDE,OOP等等
我们在开发程序过程中,会用到一些与编译有关的术语,比如:[编辑器.编译器.调试器.连接器,链接器.解释器,集成开发环境(Integrated Development Environment,IDE). ...
随机推荐
- Prometheus入门教程(二):Prometheus + Grafana实现可视化、告警
文章首发于[陈树义]公众号,点击跳转到原文:https://mp.weixin.qq.com/s/56S290p4j9KROB5uGRcGkQ Prometheus UI 提供了快速验证 PromQL ...
- Redis 字典结构细谈
Redis 字典底层基于哈希表实现. 一.哈希表结构 1.dictht: typedef struct dictht { dictEntry **table; //哈希表数组,存储具体的键值对元素,对 ...
- 【状态压缩DP】HDU 4352 XHXJ'S LIS
题目大意 Vjudge链接 定义一个数的内部LIS长度表示这个数每个数位构成的序列的LIS长度,给出区间\([l,r]\),求区间内内部LIS长度为\(k\)的数的个数. 输入格式 第一行给出数据组数 ...
- lumen-ioc容器测试 (4)
lumen-ioc容器测试 (1) lumen-ioc容器测试 (2) lumen-ioc容器测试 (3) lumen-ioc容器测试 (4) lumen-ioc容器测试 (5) lumen-ioc容 ...
- centos8平台用ffprobe获取视频文件信息(ffmpeg4.2.2)
一,ffprobe的作用 ffprobe是强大的视频分析工具, 用于从多媒体流中获取相关信息或查看文件格式信息, 并以可读的方式打印 说明:刘宏缔的架构森林是一个专注架构的博客,地址:https:// ...
- lumen中间件 Middleware
app/http 下新建 TestMiddleware.php <?php namespace App\Http\Middleware; use Closure; class TestMiddl ...
- 笔趣阁小说 selenium爬取
import re from time import sleep from lxml import etree from selenium import webdriver options = web ...
- npm install 几种不同后缀安装模式的区别
--save/--save --dev/nothing / -g 区别,及package.json基本目录结构介绍 https://www.jianshu.com/p/e10f981972ff
- Git Push 避免输入用户名和密码方法
1 创建文件存储GIT用户名和密码 在%HOME%目录中,一般为C:\users\Administrator,也可以是你自己创建的系统用户名目录,反正都在C:\users\中.文件名为.git-cre ...
- String题目解析1
Java又不是C++,什么时候字符数组等于字符串了(对这句话我不负责任)? 而常量池中的字符串,只有变量名不同是可以用双等号判断是否相等的,内存都是常量池中的字符串. 但是new出来的字符串,只能用e ...