shared/tar.c
07e7e145
 /*
  *  A minimalistic tar archiver for sigtool and freshclam.
52cddcbc
  *
206dbaef
  *  Copyright (C) 2013-2020 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
52cddcbc
  *  Copyright (C) 2007-2013 Sourcefire, Inc.
  *
07e7e145
  *  Author: Tomasz Kojm <tkojm@clamav.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  *
  *  This program is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  *  MA 02110-1301, USA.
  */
 #if HAVE_CONFIG_H
 #include "clamav-config.h"
 #endif
 
 #include <stdio.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
72fd33c8
 #ifdef HAVE_UNISTD_H
07e7e145
 #include <unistd.h>
 #endif
d8b95725
 #include <zlib.h>
07e7e145
 
9e20cdf6
 // libclamav
 #include "clamav.h"
 
9d193ff2
 #include "tar.h"
 
07e7e145
 struct tar_header {
72fd33c8
     char name[100];  /* File name */
     char mode[8];    /* File mode */
     char uid[8];     /* UID */
     char gid[8];     /* GID */
     char size[12];   /* File size (octal) */
     char mtime[12];  /* Last modification */
     char chksum[8];  /* Header checksum */
     char type[1];    /* File type */
     char lname[100]; /* Linked file name */
07e7e145
     char pad[255];
 };
 #define TARBLK 512
 
3afedd07
 int tar_addfile(int fd, gzFile gzs, const char *file)
07e7e145
 {
72fd33c8
     int s, bytes;
     struct tar_header hdr;
     STATBUF sb;
     unsigned char buff[FILEBUFF], *pt;
     unsigned int i, chksum = 0;
07e7e145
 
72fd33c8
     if ((s = open(file, O_RDONLY | O_BINARY)) == -1)
         return -1;
07e7e145
 
72fd33c8
     if (FSTAT(s, &sb) == -1) {
         close(s);
         return -1;
07e7e145
     }
 
     memset(&hdr, 0, TARBLK);
     strncpy(hdr.name, file, 100);
72fd33c8
     hdr.name[99] = '\0';
     snprintf(hdr.size, 12, "%o", (unsigned int)sb.st_size);
     pt = (unsigned char *)&hdr;
     for (i = 0; i < TARBLK; i++)
         chksum += *pt++;
07e7e145
     snprintf(hdr.chksum, 8, "%06o", chksum + 256);
 
72fd33c8
     if (gzs) {
         if (!gzwrite(gzs, &hdr, TARBLK)) {
             close(s);
             return -1;
         }
d8b95725
     } else {
72fd33c8
         if (write(fd, &hdr, TARBLK) != TARBLK) {
             close(s);
             return -1;
         }
07e7e145
     }
 
72fd33c8
     while ((bytes = read(s, buff, FILEBUFF)) > 0) {
         if (gzs) {
             if (!gzwrite(gzs, buff, bytes)) {
                 close(s);
                 return -1;
             }
         } else {
             if (write(fd, buff, bytes) != bytes) {
                 close(s);
                 return -1;
             }
         }
07e7e145
     }
d8b95725
     close(s);
07e7e145
 
72fd33c8
     if (sb.st_size % TARBLK) {
         memset(&hdr, 0, TARBLK);
         if (gzs) {
             if (!gzwrite(gzs, &hdr, TARBLK - (sb.st_size % TARBLK)))
                 return -1;
         } else {
             if (write(fd, &hdr, TARBLK - (sb.st_size % TARBLK)) == -1)
                 return -1;
         }
07e7e145
     }
 
d8b95725
     return 0;
07e7e145
 }