【问题标题】:using system() to call ln from a cpp program使用 system() 从 cpp 程序调用 ln
【发布时间】:2017-06-02 05:05:57
【问题描述】:

我正在尝试使用以下命令从 cpp 程序调用系统

system("ln -s -t \"targetDir[0]\" \"baseDir[0]\"");

targetDir 和 baseDir 都是 QStringList。程序编译并运行,但是当我执行命令时,我得到错误 ln : targetDir[0] is an invalid command。当我通过对值进行硬编码而不是使用变量进行测试时,它工作得很好。我只能得出结论,将变量的值放入传递给 ln 的参数中并没有转义字符串。对于我的生活,我不知道为什么不。

有什么想法吗?

【问题讨论】:

  • 首先格式化字符串,可以使用std::string append (+) 运算符,也可以使用std::ostringstream(或Qt 等效项)。
  • 为什么?你可以通过系统调用来做到这一点。

标签: c++ ln


【解决方案1】:

你很困惑。 system(3) 库函数(它不是一个命令,尽管它的名字是 not system call,那些在syscalls(2) 中列出)是forking一个 /bin/sh -c 进程,它显然对 C++ 程序的变量一无所知(在运行时,变量不存在;只有位置)。

顺便说一句,由于code injection 问题,不小心使用system(3) 可能会很危险。想象一下,在您的(错误)方法中,targetDir[0] 包含类似 foo; rm -rf $HOME ....


要建立一个符号链接,分叉一个进程是多余的。只需调用symlink(2) 系统调用(如果以ln -s 调用,ln(1) 命令将调用该系统调用)

Qt 库提供QFile 类及其QFile::link 成员函数,或静态QFile::link(两者都将调用symlink(2)

未来(或最近)版本的 C++,从 C++17 开始,将提供 std::filesystem::create_symlink function(在 Linux 上将调用 symlink(2))。它可能是受到Boost filesystem library 的启发。

PS。如果为 Linux 或 POSIX 编码,我建议阅读 Advanced Linux Programming(可免费下载)。但是,如果您想要一个源代码可移植的 Qt 程序,请限制自己使用慷慨的Qt API。或者采用 C++17 并使用它的 std::filesystem 东西。

【讨论】:

  • 哦,很好。有一个静态的 2-arg 版本,因此您甚至不必实例化该类:QFile::link(target, link);
  • 非常感谢。我最终选择了 symlink() 路线。我已经有 15 年没有编程了,刚刚开始使用 linux。
【解决方案2】:

C++ 绝不执行字符串插值。

如果您实际上是用 C++ 编写的,则可以(考虑到 targetDirchar ** 或类似的东西):

std::string command = std::string("ln -s -t \"") + targetDir[0] + "\" \"" + baseDir[0] + "\"";
system(command.c_str());

【讨论】:

  • 不要使用strncpy
  • 等等什么?为什么?
  • 因为这是一个不应该存在的可怕功能。而且不安全。
  • 能否请您赐教我应该使用什么来复制C字符串?
  • strncpymemcpy 之间的唯一区别是 strncpy 在碰到 '\0' 时将停止从源指针读取并继续写入 '\0' 字节:char buf[4]; memcpy(buf, "a\0bc", 4); 产生{ 'a', '\0', 'b', 'c' }strncpy(buf, "a\0bc", 4); 产生{ 'a', '\0', '\0', '\0' }。如果源在前 N 个字节中不包含任何 '\0',它们都不会创建 C 字符串。
猜你喜欢
  • 2011-04-15
  • 2012-01-24
  • 1970-01-01
  • 2017-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多