0

I have a linux based device that runs c++ code using QT framework. Using QProcess is not an option, since we don't have the QT compiled to support it.

I can't create a tar.gz archive using execl().

It returns -1(fail) and error is "No such file or directory"

Code sample:

std::string applicationPathWithName = "/bin/busybox";
QString dataDirectory("/opt/appl/data/");
QString archiveName = QString("AswLogs.tar.gz");
char* applName;
applName = new char [applicationPathWithName.size() + 1];
strcpy(applName, applicationPathWithName.c_str());

itsFlmFileManagerPtr->writeInFile(eFlmFileTypes_LogFile, data); //This creates logs.txt successfully

pid_t pid = fork();

QString command = QString("tar -czvf %1%2 %3logs.txt").arg(dataDirectory).arg(archiveName).arg(dataDirectory);

if(0 == pid)
{
    INFO("Pid is 0");
    int execStatus = 0;
    execStatus = execl(applName, applName, command.toStdString().c_str(), (char*)NULL);
    INFO("Execl is done, execStatus= " << execStatus);
    std::string errorStr = strerror(errno);
    INFO("Error: " << errorStr);

    _exit(EXIT_FAILURE);
}
else if (pid < 0)
{
    INFO("Failed to fork");
}
else
{
    INFO("pid=" << pid);
    int status;
    if(wait(&status) == -1)
    {
        INFO("Wait child error");
    }
    INFO("Resume from fork");
}

Output:

pid=877

Pid is 0

Execl is done, execStatus= -1

Error: No such file or directory

Resume from fork

Permissions:

logs.txt 666 | busybox 755

How can I get more error details or what is wrong here?

Edit: So, after a while, I tried to do just the .tar archive and it worked. Then I tried just to do the .gz compression and it also worked.

Solution: So, at least in my case, the solution was to do the tar.gz in two steps(Two processes required):

execl("/bin/busybox", "/bin/busybox", "tar", "-cvf", "/opt/appl/data/logs.tar", "/opt/appl/data/logs.txt", (char*) NULL);

execl("/bin/busybox", "/bin/busybox", "gzip", "/opt/appl/data/logs.tar", (char*) NULL);

ionutCb
  • 13
  • 6

1 Answers1

0

I don't know what platform or compiler this is, but it generally isn't possible to pass whole command lines to execl(). If I understanding correctly, you are running something like this:

execl ("/bin/busybox", "/bin/busybox", "tar -czvf blah blah", null);

but in general you need

execl ("/bin/busybox", "/bin/busybox", "tar", "-czvf", "blah", "blah", null);

That is, you need to parse the command line down to its individual arguments. That should be easy enough in the case you described, since you already know what the individual arguments are.

I think the problem is that /bin/busybox starts, but chokes when it tries to interpret "tar -czvf blah blah" as the name of an applet to run.

Incidentally -- and probably not related -- busybox "tar" won't handle gzip compression internally by default, unless you have enabled this feature at build time.

Kevin Boone
  • 4,092
  • 1
  • 11
  • 15
  • You understood correctly. I tried your version separating the arguments but still, I got the same "No such file or directory" error. Also, I replaced "-czvf" with "-cvf", respectively "AswLogs.tar.gz" with "AswLogs.tar" but no success. Do you have any other suggestions? – ionutCb Aug 27 '17 at 12:21
  • Have you checked that your Busybox tar command works correctly when invoked from a command prompt? What is the value of errno after the execl() call? – Kevin Boone Aug 28 '17 at 13:18
  • Yes, I checked. Invoked from terminal works fine. The value of errorStr is "No such file or directory" – ionutCb Aug 28 '17 at 14:59
  • The value of errno is 2 – ionutCb Aug 28 '17 at 15:20
  • Finally, I was able to run the command and now I'm into another problem: after calling the execl, i get this: "tar: can't execute 'gzip': Permission denied" – ionutCb Aug 29 '17 at 21:35