shared/tar.c
07e7e145
 /*
  *  A minimalistic tar archiver for sigtool and freshclam.
  *  Copyright (C) 2007 Sourcefire, Inc.
  *  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>
 #ifdef  HAVE_UNISTD_H
 #include <unistd.h>
 #endif
d8b95725
 #include <zlib.h>
07e7e145
 
9d193ff2
 #include "tar.h"
 
07e7e145
 struct tar_header {
     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 */
     char pad[255];
 };
 #define TARBLK 512
 
d8b95725
 int tar_addfile(int fd, gzFile *gzs, const char *file)
07e7e145
 {
d8b95725
 	int s, bytes;
07e7e145
 	struct tar_header hdr;
 	struct stat sb;
 	unsigned char buff[FILEBUFF], *pt;
 	unsigned int i, chksum = 0;
 
 
d706617c
     if((s = open(file, O_RDONLY|O_BINARY)) == -1)
07e7e145
 	return -1;
 
     if(fstat(s, &sb) == -1) {
 	close(s);
 	return -1;
     }
 
     memset(&hdr, 0, TARBLK);
     strncpy(hdr.name, file, 100);
72ce4b70
     hdr.name[99]='\0';
07e7e145
     snprintf(hdr.size, 12, "%o", (unsigned int) sb.st_size);
     pt = (unsigned char *) &hdr;
     for(i = 0; i < TARBLK; i++)
 	chksum += *pt++;
     snprintf(hdr.chksum, 8, "%06o", chksum + 256);
 
d8b95725
     if(gzs) {
 	if(!gzwrite(gzs, &hdr, TARBLK)) {
 	    close(s);
 	    return -1;
 	}
     } else {
 	if(write(fd, &hdr, TARBLK) != TARBLK) {
 	    close(s);
 	    return -1;
 	}
07e7e145
     }
 
     while((bytes = read(s, buff, FILEBUFF)) > 0) {
d8b95725
 	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
 
     if(sb.st_size % TARBLK) {
 	memset(&hdr, 0, TARBLK);
d8b95725
 	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
 }