【问题标题】:Running find from a C program to print file name given inode number?从 C 程序运行 find 以打印给定 inode 编号的文件名?
【发布时间】:2017-11-17 21:52:33
【问题描述】:

我正在尝试打印给定 inode 编号的文件名。我正在使用execlp 系统调用来运行find 命令。我的代码如下所示:

 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>

 int main(int argc,char *argv[])
 {
    char str[8];
    char *ptr;
    ptr=str;
    long x=9306140;
    snprintf(str,8,"%ld", x);
    execlp("find"," ","~"," ","-inum"," ",str,NULL);

 }

但我收到一个错误:-inum 的参数“9306140”无效。 有人可以帮忙吗?

【问题讨论】:

  • 你不想要 ” “ 参数。 shell 使用空格来分隔字符串中的参数,但通常不会将它们传递给命令。 find 命令不会抱怨前两个,因为它只是将它们视为文件/目录名称。它以某种方式将-inum 之后的那个解释为inode 号;那么它对数字没有意义。您还需要确保分配了足够的空间来格式化数字。
  • 当我删除 " " 参数时,即使存在具有该 inode 的文件,它也会编译但不打印任何内容
  • 能否详细说明“分配足够的空间来格式化数字”
  • shell 在运行命令之前扩展~。您需要使用char *home = getenv(“HOME”); 并通过home 代替”~”
  • '足够的空间' - 对于给定的 inode 编号,您是安全的,但概括代码可能会遇到空间不足的问题。您即将拥有一个 8 位数字;如果要增加,您需要更多空间。

标签: c


【解决方案1】:

如 cmets 中所述,您不希望 execlp() 参数列表中的 " "(空格)参数。 shell 接受一个以空格分隔参数的字符串,但它将空格之间的内容视为传递给命令的单词;它通常不会将空格传递给命令。 (这是对本练习的简单而充分的解释;可以添加大量警告和狡猾的话。)

shell 还扩展~ 以匹配$HOME 环境变量中的值(与~user 相比,它从密码文件中获取user 的主目录——它们通常是,但不一定是,一样)。

您为数字分配的字符串大小也几乎没有错误余地。不过,坦率地说,您应该简单地使用字符串。所有这些变化导致:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
    const char *home = getenv("HOME");
    const char inode[] = "9306140";
    execlp("find", "find", home, "-inum", inode, (char *)NULL);
    fprintf(stderr, "failed to execute 'find' command\n");
    return(EXIT_FAILURE);
}

注意重复的"find";第一个是沿路径搜索后要执行的文件的名称;第二个是作为argv[0] 提供的值。您可以将"hypochondriac" 作为第二次出现,find 可能会以相同的方式工作,最坏的情况是报告其错误消息来自程序“hypochondriac”。

下一步是从命令行参数中获取 inode 编号:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    if (argc != 2)
    {
         fprintf(stderr, "Usage: %s inode\n", argv[0]);
         exit(EXIT_FAILURE);
    }
    const char *home = getenv("HOME");
    const char *inode = argv[1];
    execlp("find", "find", home, "-inum", inode, (char *)NULL);
    fprintf(stderr, "%s: failed to execute 'find' command\n", argv[0]);
    return(EXIT_FAILURE);
}

之后的步骤是处理多个 inode 值;那时,您使用execvp() 而不是execlp(),尽管(或者,如果您既绝望又懒惰,您可以循环并fork()execlp() 每个inode 编号一次,但这对您的系统不利原因)。

【讨论】:

  • 非常感谢!它现在起作用了。但我有一个疑问。如果第一个“find”是路径,那么我们不应该像“bin/usr”这样写完整路径
  • 没有。您正在使用execlp(),它采用纯文件名(无斜杠)并在$PATH 中列出的某个目录中搜索具有该名称的可执行文件——在第一次成功时停止。如果您使用了execl("/usr/bin/find", …);,那么它将执行文件/usr/bin/find(并且仅执行该文件,如果它不存在则失败)。如果您按照评论中的建议使用execlp("bin/usr/find", …),那么只有在当前目录中有一个子目录bin,其中包含一个子目录usr,并且该子目录中的文件find(以及文件是可执行的,等等)。
  • 非常清晰的解释!!真的有帮助。谢谢!
  • 请注意,在bin/usr/find 示例中,execlp() 根本不会搜索$PATH 中的目录。它将有效地使用当前目录. 作为唯一要检查的目录。使用execlp("/usr/bin/find", …)(这次注意execlp(),不像之前评论中的execl("/usr/bin/find", …)),它只会尝试执行绝对路径名;它根本不会搜索$PATH
猜你喜欢
  • 1970-01-01
  • 2013-01-27
  • 2012-02-11
  • 2015-11-22
  • 2013-01-24
  • 1970-01-01
  • 1970-01-01
  • 2011-09-16
  • 2013-04-11
相关资源
最近更新 更多