使用 rmdir() 删除目录后 opendir() 的行为

发布于 2025-01-15 22:53:48 字数 2147 浏览 1 评论 0原文

我试图了解如何从 C 程序中删除当前工作目录。我使用《Unix 环境中的高级编程》一书作为参考。首先,我进行以下调用序列(/tmp 是一个现有目录):

//  1. Create a test directory
if (mkdir("/tmp/foo", DIR_PERM) < 0){
    printf("mkdir error\n");
}
else 
    printf("mkdir succeeded\n");

// 2. Change cwd to the test directory
if (chdir("/tmp/foo") < 0)
    printf("chdir error\n");
else
    printf("chdir succeeded\n");

// (2.5) Check the cwd
if (getcwd(cwd, sizeof(cwd)) != NULL)
    printf("Current working directory: %s\n", cwd);
else
    printf("getcwd error\n");

// 3. Remove the test directory
if (rmdir("/tmp/foo") < 0)
    printf("rmdir error\n");
else
    printf("rmdir succeeded\n");

// (3.5) Check current working directory
if (getcwd(cwd, sizeof(cwd)) != NULL)
    printf("Current working directory: %s\n", cwd);
else
    printf("getcwd error\n");

这正如我所期望的那样。 mkdirchdirrmdir 成功,(2.5) 中的 getcwd 返回 /tmp/foo (3.5) 中的 路径名和 getcwd 失败。

我不明白的是随后使用 ".", " 在 /tmp/foo 目录上使用 opendir 的行为../foo""/tmp/foo" 作为路径名:

// 4. Open the removed directory using "." 
if ((dp = opendir(".")) == NULL)
    printf("1. opendir error\n");
else{
    printf("1. opendir succeeded\n");
    while((dirp = readdir(dp)) != NULL)
        printf("%s\n", dirp->d_name);
}

// 5. Open the removed directory using "../foo"
if ((dp = opendir("../foo")) == NULL)
    printf("2. opendir error\n");
else
    printf("2. opendir succeeded\n");

// 6. Open the removed directory using "/tmp/foo"
if ((dp=opendir("/tmp/foo")) == NULL)
    printf("3. error\n");
else
    printf("3. opendir succeeded\n");

上述代码片段的输出是

  1. opendir 成功
  2. 打开目录错误
  3. 打开目录错误

为什么 opendir(".") 可以工作,而 opendir("../foo") 却不能?据我了解,/tmp/foo目录的链接计数在rmdir之后变为0。点和点-点条目在该函数返回之前被删除,并且在成功调用 opendir 后读取 4. 中的目录不会打印任何内容。如果在 rmdir 期间删除了该条目,opendir 如何知道点代表什么?如果它可以解析点,为什么它不能解析点呢?

I'm trying to understand how removing the current working directory works from a C program. I'm using the Advanced Programming in Unix Enviroment book as a reference. First, I make the following sequence of calls (/tmp is an existing directory):

//  1. Create a test directory
if (mkdir("/tmp/foo", DIR_PERM) < 0){
    printf("mkdir error\n");
}
else 
    printf("mkdir succeeded\n");

// 2. Change cwd to the test directory
if (chdir("/tmp/foo") < 0)
    printf("chdir error\n");
else
    printf("chdir succeeded\n");

// (2.5) Check the cwd
if (getcwd(cwd, sizeof(cwd)) != NULL)
    printf("Current working directory: %s\n", cwd);
else
    printf("getcwd error\n");

// 3. Remove the test directory
if (rmdir("/tmp/foo") < 0)
    printf("rmdir error\n");
else
    printf("rmdir succeeded\n");

// (3.5) Check current working directory
if (getcwd(cwd, sizeof(cwd)) != NULL)
    printf("Current working directory: %s\n", cwd);
else
    printf("getcwd error\n");

This works as I would expect. mkdir, chdir, and rmdir succeed, getcwd in (2.5) returns the /tmp/foo pathname and getcwd in (3.5) fails.

What I don't understand is the behavior of using opendir afterward on the /tmp/foo directory using ".", "../foo", and "/tmp/foo" as pathnames:

// 4. Open the removed directory using "." 
if ((dp = opendir(".")) == NULL)
    printf("1. opendir error\n");
else{
    printf("1. opendir succeeded\n");
    while((dirp = readdir(dp)) != NULL)
        printf("%s\n", dirp->d_name);
}

// 5. Open the removed directory using "../foo"
if ((dp = opendir("../foo")) == NULL)
    printf("2. opendir error\n");
else
    printf("2. opendir succeeded\n");

// 6. Open the removed directory using "/tmp/foo"
if ((dp=opendir("/tmp/foo")) == NULL)
    printf("3. error\n");
else
    printf("3. opendir succeeded\n");

The output of the above code snippet is

  1. opendir succeeded
  2. opendir error
  3. opendir error

Why does opendir(".") work but opendir("../foo") doesn't? As I understand it, the link count of the /tmp/foo directory becomes 0 after rmdir. The dot and dot-dot entries are removed before that function returns and reading the directory in 4. after the successful opendir call doesn't print anything. How does opendir know what dot stands for if that entry was removed during rmdir? And why wouldn't it resolve dot-dot if it can resolve dot?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

蘸点软妹酱 2025-01-22 22:53:48

为什么 opendir(".") 可以工作,而 opendir("../foo") 却不能?

rmdir后/tmp/foo目录的链接数变为0

不,程序的当前工作目录仍然指向那里。它就像一个开放的索引节点。

$ mkdir -p /tmp/foo/abc
$ cd /tmp/foo
$ ls -la /proc/self/cwd
lrwxrwxrwx 1 kamil kamil 0 mar 22 18:35 /proc/self/cwd -> /tmp/foo/
$ rmdir /tmp/foo
$ ls -la /proc/self/cwd
lrwxrwxrwx 1 kamil kamil 0 mar 22 18:36 /proc/self/cwd -> '/tmp/foo (deleted)'

如果在 rmdir 期间删除了该条目,opendir 如何知道点代表什么?

内核跟踪进程并跟踪进程当前工作目录,并且它知道什么是.

如果可以解析点,为什么不能解析点-点?

它解析..。它不解析../foo,删除后..处没有fooopendir('..') 应该仍然可以工作。

Why does opendir(".") work but opendir("../foo") doesn't?

the link count of the /tmp/foo directory becomes 0 after rmdir

No, your program's current working directory still points there. It's like an open inode.

$ mkdir -p /tmp/foo/abc
$ cd /tmp/foo
$ ls -la /proc/self/cwd
lrwxrwxrwx 1 kamil kamil 0 mar 22 18:35 /proc/self/cwd -> /tmp/foo/
$ rmdir /tmp/foo
$ ls -la /proc/self/cwd
lrwxrwxrwx 1 kamil kamil 0 mar 22 18:36 /proc/self/cwd -> '/tmp/foo (deleted)'

How does opendir know what dot stands for if that entry was removed during rmdir?

Kernel keeps track of processes and keeps track of processes current working directories and it knows what is ..

why wouldn't it resolve dot-dot if it can resolve dot?

It resolves ... It does not resolve ../foo, there is no foo at .. after it was deleted. opendir('..') should still work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文