Использование system() для вызова ln из программы cpp
Я пытаюсь вызвать систему из программы cpp с помощью следующей команды
system("ln -s -t \"targetDir[0]\" \"baseDir[0]\"");
И targetDir, и baseDir являются QStringList. Программа компилируется и запускается, но когда я выполняю команду, я получаю сообщение об ошибке ln: targetDir[0] - недопустимая команда. Когда я тестирую путем жесткого кодирования значений вместо использования переменных, это работает просто отлично. Я могу только заключить, что это не экранирование строки для помещения значения переменных в аргумент, передаваемый в ln. По жизни я не могу понять, почему нет.
Есть идеи?
2 ответа
Ты смущен. Функция библиотеки system(3) (это не команда, и, хотя ее имя не является системным вызовом, они перечислены в syscalls (2)) /bin/sh -c
процесс, который, очевидно, не имеет никакого представления о переменных вашей программы на C++ (во время выполнения переменные не существуют; существуют только местоположения).
Кстати, использование системы (3) без осторожности может быть опасным из-за проблем с внедрением кода. Вообразите в своем (неправильном) подходе, что targetDir[0]
содержит что-то вроде foo; rm -rf $HOME
....
Чтобы сделать символическую ссылку, разветвление процесса - это излишне. Просто вызовите системный вызов symlink(2) (который вызовет команда ln(1), если вызывается как ln -s
)
Библиотека Qt предлагает класс QFile с его функцией- членом QFile::link или статический QFile::link (оба будут вызывать symlink(2))
Будущие (или последние) версии C++, начиная с C++17, обеспечат std::filesystem::create_symlink
функция (которая в Linux будет вызывать symlink(2)). Это, вероятно, вдохновлено библиотекой файловой системы Boost.
PS. Если вы пишете код для Linux или POSIX, я рекомендую прочитать http://advancedlinuxprogramming.com/ (который можно загрузить бесплатно). Но если вы хотите переносимую исходную программу Qt, ограничьтесь щедрым Qt API. Или принять C++17 и использовать его std::filesystem
вещь.
C++ ни в коем случае не выполняет интерполяцию строк.
Если вы на самом деле пишете на C++, вы можете (учитывая targetDir
является char **
или что-то похожее)
std::string command = std::string("ln -s -t \"") + targetDir[0] + "\" \"" + baseDir[0] + "\"";
system(command.c_str());