本网站(662p.com)打包出售,且带程序代码数据,662p.com域名,程序内核采用TP框架开发,需要联系扣扣:2360248666 /wx:lianweikj
精品域名一口价出售:1y1m.com(350元) ,6b7b.com(400元) , 5k5j.com(380元) , yayj.com(1800元), jiongzhun.com(1000元) , niuzen.com(2800元) , zennei.com(5000元)
需要联系扣扣:2360248666 /wx:lianweikj
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
使用Nginx反向代理到go-fastdfs

iamitnan · 724浏览 · 2019-05-23 13:42:00
利用VLC搭建组播流服务器

追忆似水年华 · 2691浏览 · 2019-06-14 11:27:06
用Bash脚本监控Linux上的内存使用情况

吴振华 · 972浏览 · 2019-06-24 11:27:02
加载中

0评论

评论
我从事编程工作,现在在一家网络公司上班,偶尔也是发布博客,逛论坛等,希望可以在这里交到志同道合的朋友。
分类专栏
小鸟云服务器
扫码进入手机网页