1

This question's been asked a million times on this site with various different solutions, but non of them seems to work for my case.

So far the most promising one is tar -cvf testetest.tar -C folder1 * where folder1 includes:

Folder1
    >txt1.txt
    >folder2
        >txt2.txt

running the code above in the terminal creates testtest.tar which includes along with a bunch of error msgs:

txt1.txt
folder2
    >txt2.txt

However when ran in a function via execv like so:

pid_t archive = fork();
    switch(archive)
    {
        case -1 :
        {
            printf("fork() failed\n");
            break;
        }
        case 0 :
        {
            if( strcmp(getFileExtension(finalArchiveName), "tar") == 0)
            {
                char* args[] = {"/usr/bin/tar","-cvf", finalArchiveName, "-C", "dest", "*", NULL};
                int error = execv("/usr/bin/tar", args);    
                if(error == -1){
                    perror("Error when archiving");
                    exit(EXIT_FAILURE);
                }
                else{
                    exit(EXIT_SUCCESS);
                }
                break;
            }
//... (not including the whole function, only the part i feel is relevant to the question)

it returns with /usr/bin/tar: *: Cannot stat: No such file or directory

Another line I've tired is to replace the * with . however that ends up including the root directory

Sheng
  • 75
  • 7

1 Answers1

1

The shell replaces the * with a list of filenames, as you can see by typing echo * in a shell. But there's no shell in a call to execv, unless you specifically execute a shell:

char* args[] = {"sh", "-c", "tar /usr/bin/tar -cvf testetest.tar -C dest *", NULL};
int error = execv("/bin/sh", args);

In such a case, system() is often a simpler alternative.

If you want to create a list of file names to pass as arguments to a command-line utility, take a look at glob().

rici
  • 234,347
  • 28
  • 237
  • 341
  • I would like to use ```system()``` too but for the sake of this project, any use of ```system()``` is forbidden. I will have a look at ```glob()``` but I guess there really isnt a easy way to do this. – Sheng Oct 16 '20 at 03:47
  • @PapaSheng: glob is pretty easy to use, if you're allowed to use it. It even lets you reserve some empty slots at the beginning of the array it returns, which you can fill in afterwards with the argv entries which precede the `*`. – rici Oct 16 '20 at 03:58
  • I see, I will look into it, on another note, ```char* args[] = {"/bin/sh", "sh", "-c", "tar /usr/bin/tar -cvf testetest.tar -C dest *", NULL};``` how would I ```execv()``` this? If this will work I wan to just patch it on for now for a temporary fix. – Sheng Oct 16 '20 at 04:14
  • @PapaSheng: I made the call to execv more explicit. I left out the part where you use `snprintf` (or `asprintf` if available) to insert the tar filename into the command argument. – rici Oct 16 '20 at 04:19
  • that gives me some ideas with how to fix this actually, thanks – Sheng Oct 16 '20 at 04:27