【问题标题】:Multiple issues with mkdir()mkdir() 的多个问题
【发布时间】:2024-05-09 03:30:02
【问题描述】:

在一个 C 项目中,我试图在特定目录中创建一个目录。

// Find the user's home directory.
// Code from https://*.com/a/2910392/14602523
struct passwd * pw = getpwuid(getuid());
char * home = pw->pw_dir;

// Test if the ".junk" directory exists in the home directory.
// If not, create it.
if (opendir(strcat(home, "/.junk/")) == NULL) {
    printf(" - no junk directory\n");
    if (mkdir(strcat(home, "/.junk/"), 0777) < 0) {
        fprintf(stderr, "Error: Cannot create junk directory.\n");
        perror(" - errno");
        exit(1);
    }
}

opendir() 正常工作:如果~/ 中存在名为.junk/ 的目录,那么我不会收到任何打印消息,如果该目录不存在,那么我会得到一些输出。但是mkdir() 真的很笨拙并引起了很多问题。如果~/.junk/ 不存在,那么我会得到这个输出:

 - no junk directory
Error: Cannot create junk directory.
 - errno: No such file or directory

但如果我尝试在当前目录下创建目录,例如mkdir("./.junk/", 0777),则目录创建正确。这是怎么回事?为什么它在 ~/ 中的行为不同,我怎样才能让它工作?

【问题讨论】:

  • 您的第一个strcat 使用".junk",但mkdir 使用“/.junk/”``。你的错误都没有说Cannot empty junk directory。所以你的输出与你的代码不匹配。
  • @DavidCullen 不,我能够使用getpwuid() 正确找到该文件夹​​,并且该部分适用于opendir()。但由于某种原因,它不适用于mkdir()
  • @root 哎呀,这些都是我的错。我正在尝试不同的格式,看看是否有区别,但我忘了复制最新的格式。此外,“空”错误来自代码的不同部分,所以这并不重要。编辑问题以解决这些问题。但我还是不明白为什么opendir() 可以访问该文件夹而mkdir() 不能。
  • 这与您的问题无关,但不要使用pw-&gt;pw_dir 获取当前主目录。 pw-&gt;pw_dir 应该是登录时的初始主目录。用户可能希望在运行程序时更改当前目录,因此您应该使用getenv("HOME") 而不是pw-&gt;pw_dir。详情请见man getpwuid
  • @HAL9000 很高兴知道,我改变了它。谢谢!

标签: c mkdir


【解决方案1】:
  1. strcat 附加到适当的字符串。从getpwuid 返回的字符串根本不打算写。

  2. 当然不能保证它后面有任何可用空间,所以你不能安全地追加它。

  3. 即使你可以调用strcat 两次,所以传递给mkdir 的字符串类似于/home/zach/.junk//.junk/,当你试图在/home/zach/.junk 中创建一个目录时,它会失败。刚刚确定不存在。

这段代码的编写好像您认为字符串是 C 中的“第一类”对象,可以像在许多其他语言中一样纯粹作为值进行操作。好吧,它们不是 - 它们是字符数组,与所有其他数组一样,内存管理取决于您。

【讨论】:

  • strcat() 是问题所在。我一直忘记如何使用&lt;string.h&gt; 函数...我更改了代码,它现在可以工作了。太感谢了!另外,其他人提到我不应该使用getpwuid(),我也更改了它。
【解决方案2】:

您已将home 设置为pw-&gt;pw_dir,它被定义为char * 类型,并且您正在尝试附加到它。无法保证 pw-&gt;pw_dir 指向的内容有足够的空间来附加其他字符。您很有可能正在写入超出缓冲区的末尾。

即使您没有覆盖缓冲区,您也会附加“/.junk”两次,因此您传递给mkdir 的字符串是“home/.junk//.junk”

您需要为完整目录名称创建一个单独的字符串,该字符串足够大以容纳并在那里构建它。

struct passwd * pw = getpwuid(getuid());
char * home = pw->pw_dir;
char junk_dir[strlen(pw->pw_dir) + strlen("/.junk/") + 1];
sprintf(junk_dir, "%s/.junk/", home);

// Test if the ".junk" directory exists in the home directory.
// If not, create it.
if (opendir(junk_dir) == NULL) {
    printf(" - no junk directory\n");
    if (mkdir(junk_dir), 0777) < 0) {
        fprintf(stderr, "Error: Cannot create junk directory.\n");
        perror(" - errno");
        exit(1);
    }
}

【讨论】: