0

Hello guys i want to create tar.gz file from a c program

I tried system("tar -zcvf file.tar.gz file") but it didn't work. Is there any better alternative you could do. This is my code

int make_tar() {
    char buff[100];
    DIR *d;
    struct dirent *dir;
    d = opendir(".");

    if (d) {
        while ((dir = readdir(d)) != NULL) {
          if (dir->d_type == DT_REG) {
             sprintf(buff,"%s",dir->d_name);
             system("tar -zxvf buff.tar.xz buff");
         }
    }
    closedir(d);

    return(0);
}
msw
  • 42,753
  • 9
  • 87
  • 112
Jagdish
  • 160
  • 3
  • 13

2 Answers2

2

Replacing

        sprintf(buff,"%s",dir->d_name);
        system("tar -zxvf buff.tar.xz buff");

with

if (snprintf(buff, sizeof(buff), "tar -czvf %s.tar.gz %s", 
         dir->name, dir->name) /// possible code injection!
    >= sizeof(buff)) 
   exit(EXIT_FAILURE);

fflush(NULL);
int err = system(buff);
if (err) {
   fprintf(stderr, "command failed: %s (%d)\n", buff, err);
   exit(EXIT_FAILURE);
}
else printf ("did %s\n", buff);

might be helpful. You should use snprintf(3) (avoid sprintf !!) to avoid buffer overflow, and you need to put the actual name of the file in the command (not buff).

You'll better declare buff to contain more characters, e.g. char buff[512]; or even static char buff[2*PATH_MAX+25]; (that could be more than 8 kilobytes) or char buff[2*NAME_MAX+30]; or use asprintf(3)

Read also about code injection, this will make you be scared of your code. Imagine a malicious user of your program having a file named foo ; rm -rf .. (since file names can contain spaces, semicolons, dashes and dots)..

You should consider using libtar ...

You should read more about tar(1) and might also consider passing the -T i.e. --files-from=FILE option to it (and have your program construct a temporary textual file listing each file to backup, one per line; this won't be good for filenames with a newline in them).

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
1

Change your sprintf and your system call

sprintf(buff,"tar -zcvf buff.tar.xz %s",dir->d_name);
system(buff);

I'm guessing you want to tar the directory which has been found.

cup
  • 7,589
  • 4
  • 19
  • 42