Qt copy file with sudo right - qt

I handle the normal copying of files with Qt like this:
QFile::copy("/path/file", "/path/copy-of-file");
How can I now copy a file for which Sudo rights are required.

You can use QProcess and pkexec to execute a command as another user
pkexec allows an authorized user to execute PROGRAM as another user. If username is not specified, then the program will be executed as the administrative super user, root.
https://www.freedesktop.org/software/polkit/docs/0.105/pkexec.1.html
QProcess *proc = new QProcess(this);
proc->waitForFinished();
QString cmd = "pkexec /bin/cp /path/file /path/copy-of-file";
proc->start(cmd);
if(!proc->waitForStarted()) //default wait time 30 sec
{
qDebug() << "Cannot execute:" << cmd;
}
proc->waitForFinished();
proc->setProcessChannelMode(QProcess::MergedChannels);
if(proc->exitStatus() == QProcess::NormalExit
&& proc->exitCode() == QProcess::NormalExit){
qDebug() << "Success";
} else {
qDebug() << "Cannot copy file" << cmd;
}

run shell command, like this
sudo cp /path/file /path/copy-of-file
Set a password if necessary.:
$echo <password> | sudo -S <command>

Related

Listing Directory Entries with Qt on Remote Windows Server

I am on a Windows Server which is in the same network as the Server with the computer name service.
I got this simple code which tries to list the content
QFileInfoList fiList = QDir("\\service\\Documents").entryInfoList(QDir::Files);
qDebug() << "sizeof filist: " << fiList.size();
for (const QFileInfo& fi : fiList)
{
qDebug() << fi.absoluteFilePath();
}
The output is the following:
sizeof filist: 0
I make sure that the folder is shared on the network by checking the properties and also using the windows explorer. I can access the folder via Windows Explorer.
Is the functionality I am trying to achieve not possible with QDir?
It turns out there are 2 backslashes more needed because \ needs to be escaped.
So the right code would be:
QFileInfoList fiList = QDir("\\\\service\\Documents").entryInfoList(QDir::Files);
qDebug() << "sizeof filist: " << fiList.size();
for (const QFileInfo& fi : fiList)
{
qDebug() << fi.absoluteFilePath();
}

arp command with grep argument in QProcess [duplicate]

I'm using Qt and bash over it, need to execute something like:
bash: cat file | grep string
in Qt:
QString cmd = "cat file | grep string";
QProcess *process = new QProcess;
process->start(cmd);
process->waitForBytesWritten();
process->waitForFinished();
qDebug() << process->readAll();
The problem is in pipe ("|"), and process returs nothing. If there is no ("|"), like
"cat file"
everything is ok.
I tried smth. like
"cat file \\| grep string",
"cat file \| grep string"
but result is the same. If I copy the command and run it in bash everything is ok.
QString::toAscii().data()
and other transforms also have bad result.
The problem is you cannot run a system command with QProcess, but only a single process. So the workaround will be to pass your command as an argument to bash:
process.start("bash", QStringList() << "-c" << "cat file | grep string");
The quick and dirty hack would be this:
QString cmd = "/bin/sh -c \"cat file | grep string\"";
You could also avoid the escaping in there with C++11's R"", but the point is that do not use bash in there because that will make it only work with bash. It will not work on embedded with busybox without bash, just ash, or any other common desktop shell.
/bin/sh is usually a symlink to the shell interpreter used, so that will eventually work.
BUT!
I think you are thinking a bit too low-level when using a high-level C++/OOP framework such as Qt. I would not recommend to invoke the commands in the low-level way when you run it from bash. There is some dedicated high-level convenience API for this use case.
Based on the official documentation, QProcess is supposed to work for pipe'd commands:
void QProcess::setStandardOutputProcess(QProcess * destination)
Pipes the standard output stream of this process to the destination process' standard input.
In other words, the command1 | command2 shell command command can be achieved in the following way:
QProcess process1;
QProcess process2;
process1.setStandardOutputProcess(&process2);
process1.start("cat file");
process2.start("grep string");
process2.setProcessChannelMode(QProcess::ForwardedChannels);
// Wait for it to start
if(!process1.waitForStarted())
return 0;
bool retval = false;
QByteArray buffer;
while ((retval = process2.waitForFinished()));
buffer.append(process2.readAll());
if (!retval) {
qDebug() << "Process 2 error:" << process2.errorString();
return 1;
}
qDebug() << "Buffer data" << buffer;
This is not the main point, but a useful suggestion: do not use QString::toAscii(). That API has been deprecated in Qt 5.
The problem is that when you call process->start(cmd), the commands following the the call to cat are all interpreted as arguments to cat, so the pipe is not doing what you're expecting. If you start with a call to bash with a parameter of a string, you should get what you want: -
QString cmd = "bash -c \"cat file | grep string\"";
Alternatively, you could just call "cat file" and do the search on the returned QString when you read the output from the QProcess
how about this :
QString program = "program";
QStringList arguments;
download = new QProcess(this);
download->start(program, arguments);
If Google brought you here and you are using PyQt5 or PySide2
process1 = QProcess()
process2 = QProcess()
process1.setStandardOutputProcess(process2)
process1.start(cat, [file])
process2.start(grep, [string])

SCP always returns the same error code

I have a problem copying files with scp. I use Qt and copy my files with scp using QProcess. And when something bad happens I always get exitCode=1. It always returns 1. I tried copying files with a terminal. The first time I got the error "Permission denied" and the exit code was 1. Then I unplugged my Ethernet cable and got the error "Network is unreachable". And the return code was still 1. It confuses me very much cause in my application I have to distinct these types of errors.
Any help is appreciated. Thank you so much!
See this code as a working example:
bool Utility::untarScript(QString filename, QString& statusMessages)
{
// Untar tar-bzip2 file, only extract script to temp-folder
QProcess tar;
QStringList arguments;
arguments << "-xvjf";
arguments << filename;
arguments << "-C";
arguments << QDir::tempPath();
arguments << "--strip-components=1";
arguments << "--wildcards";
arguments << "*/folder.*";
// tar -xjf $file -C $tmpDir --strip-components=1 --wildcards
tar.start("tar", arguments);
// Wait for tar to finish
if (tar.waitForFinished(10000) == true)
{
if (tar.exitCode() == 0)
{
statusMessages.append(tar.readAllStandardError());
return true;
}
}
statusMessages.append(tar.readAllStandardError());
statusMessages.append(tar.readAllStandardOutput());
statusMessages.append(QString("Exitcode = %1\n").arg(tar.exitCode()));
return false;
}
It gathers all available process output for you to analyse. Especially look at readAllStandardError().

Qt can't kill process

In my Qt app i run a process under a push-button click.The process run gnome-terminal.My problem is when i kill qt process that run but push-button click from another button by pid,its shows error."kill: sending signal to 19771 failed: No such process" but still terminal running.And if i kill my app,but still terminal running.
QProcess *p = new QProcess(this);
if (p)
{
p->setEnvironment( QProcess::systemEnvironment() );
p->setProcessChannelMode( QProcess::MergedChannels );
QString program = "gnome-terminal";
QStringList arguments;
arguments << "-x" << "bash" << "--rcfile" << "./auto.sh";
p->start(program, arguments);
pid= p->pid();
}
Button2 cod is:
QProcess::startDetached("kill -9 "+QString(pid));
how can kill process and also terminal by click another push-button?

Remove too deep folders in bash on OSX

a program created folders recursively. it is too deep, the full path string length is longer than the MAX (getconf ARG_MAX), for example:
/A/B/C/A/B/C/A/B/C//A/B/C/A/B/C/A/B/C/A/B/C/A/B/C/A/B/C/A/B/C/A/B/C/A/B/C/A/B/C/A/B/C/A/B/C/A/B/C/A/B/C/A/B/C
……
so "sudo rm -fr /A" says "Bad address".
How to create a script to deal with it?
Thanks,
Interesting problem.
I guess you could create a command line tool with Xcode (file -> new project -> command line tool, insert code, then click the "run" toolbar button).
int main(int argc, const char * argv[])
{
#autoreleasepool {
NSURL *url = [NSURL fileURLWithPath:#"/a/b/c/d/..."];
NSError *error = nil;
[[NSFileManager defaultManager] removeItemAtURL:url error:&error];
if (error) {
NSLog(#"%#", error);
}
}
return 0;
}
If it's a separate disk with its own filesystem mounted at /A, unmount it and reformat it.
If not, run something like this (very untested):
cd /A
then
cd A || cd B || cd C && rm -rf A* B* C*
and keep executing it, hitting up arrow to repeat and executing again till it works...
Good luck!

Resources