【问题标题】:readdir()->d_name giving weird valuesreaddir()->d_name 给出奇怪的值
【发布时间】:2012-12-07 14:25:38
【问题描述】:

我正在尝试使用以下代码获取父目录的名称:

dirp=opendir(cur_spot);
printf("parent name: %s\n", readdir(dirp)->d_name);
closedir(dirp);

cur_spot 持有'..'。

我在一个循环中执行此操作,它会不断爬上目录到根目录,即我输出的顺序:

.
.bash_logout
.
.
srv

我知道它正在正确遍历,因为我正在检查沿途的 inode。

我需要使用不同于 d_name 的东西吗?

谢谢

【问题讨论】:

  • 绝对不能保证 readdir 将返回目录条目的顺序。所以预期的 '.'或“..”成为第一是错误的。

标签: c readdir


【解决方案1】:

我是根据sjs'回答下的cmets中的想法想出这个的:

#include <dirent.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <sys/stat.h>
#include <limits.h>
#include <errno.h>

int LookupName(const char* parent, ino_t ino, char *name, size_t size)
{
  DIR *dp = opendir(parent);
  if (!dp) return -1;

  int ret = -1;
  struct dirent *de;
  while (de = readdir(dp))
  {
    if (de->d_ino == ino)
    {
      strncpy(name, de->d_name, size);
      ret = 0;
      break;
    }
  }

  closedir(dp);
  if (ret == -1) errno = ENOENT;
  return ret;
}

int GetWorkdir(char *workdir, size_t size)
{
  struct stat st;
  if (stat(".", &st)) return -1;

  char path[PATH_MAX];
  strncpy(path, "..", sizeof(path));

  memset(workdir, '\0', sizeof(workdir));

  char name[PATH_MAX];
  while (1)
  {
    if (LookupName(path, st.st_ino, name, sizeof(name))) return -1;
    if (!strcmp(name, "..") || !strcmp(name, "."))
    {
      strncpy(name, "/", sizeof(name));
      strncat(name, workdir, sizeof(name));
      strncpy(workdir, name, size);
      break;
    }

    if (workdir[0] != '\0')
    {
      strncat(name, "/", sizeof(name));
    }

    strncat(name, workdir, sizeof(name));
    strncpy(workdir, name, size);

    if (stat(path, &st)) return -1;

    strncat(path, "/..", sizeof(path));
  }

  return 0;
}

int main(int argc, char **argv)
{
  char workDir[PATH_MAX];

  assert(!GetWorkdir(workDir, sizeof(workDir)));
  printf("%s\n", workDir);
}

【讨论】:

  • 我得到:a.out: pwd1.c:73: main: Assertion `!GetWorkdir(workDir, sizeof(workDir))' 失败。中止
  • 拿了!超出断言,现在它正在工作,但在实际密码之前有 './' 重复了大约 600 次
  • 是的,我什至找不到一个可以一遍又一遍地添加“./”的地方
  • 也许查找名称返回 '.',自从 caf 进行更新添加附加检查后,您是否对其进行了测试?
【解决方案2】:

readdir 正在读取目录,所以当你说

printf("parent name: %s\n", readdir(dirp)->d_name);

您实际上是要求为您打印.. 中的第一个条目的名称,而不是.. 目录的名称。

根据您要执行的操作,也许解析 getcwd 的输出可能是更好的方法?

【讨论】:

  • 不幸的是,我实际上是在尝试在不使用 getcwd 的情况下实现它
  • @TroyCosentino 啊,好的。想到这里我的头顶。如果你使用readdir获取当前目录的inode号(即.)然后打开父目录..,并搜索直到找到具有相同inode号的项目。然后您将获得当前工作目录的基本名称,您可以重复此过程以获取父目录的名称。
  • 抱歉,按照您所说的进行操作。所以我目前正在按照您的描述进行操作,我不断在我正在检查的内容中​​添加“/..”,以便它不断攀升,直到我找到父 inode 和当前 inode 相同,表示它是根。从那里我如何将 inode 转换为正确的名称?或者这如何给我一个基本名称?
  • 想通了,我想我会在我向上遍历然后返回时跟踪索引节点,我可以检查它们是否匹配.. 应该像魅力一样工作
  • @TroyCosentino 听起来你已经明白了,但只是为了澄清我的意思:首先在. 上调用opendir。反复调用readdir,直到你得到一个名称为.的项目。现在您有了当前目录的 inode 编号。下一次拨打opendir..。反复调用readdir,直到找到具有之前找到的inode 编号的项目。现在您有了当前目录的名称。重复此过程以获取父目录的名称……依此类推,直到获得每个父目录的名称,直到文件系统的根目录为止。
猜你喜欢
  • 2020-12-23
  • 2021-06-18
  • 2010-10-25
  • 2021-05-16
  • 2021-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多