/* * Copyright (C) 2006 Tony Sin(x) '76 * All rights reserved. * */ /* * GNU GENERAL PUBLIC LICENSE * Version 2, June 1991 * * Copyright (C) 1989, 1991 Free Software Foundation, Inc. * 675 Mass Ave, Cambridge, MA 02139, USA * Everyone is permitted to copy and distribute verbatim copies * of this license document, but changing it is not allowed. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifdef HAVE_CONFIG_H #ifndef __main_config_h__ #define __main_config_h__ #include "../config.h" #endif #include #include #ifdef HAVE_BZ2 #include #endif #ifdef HAVE_ZLIB #include #endif #include #include #include #include #include #include #ifdef TIME_WITH_SYS_TIME #include #include #else #ifdef HAVE_SYS_TIME_H #include #else #include #endif #endif #endif #include "quarantine.h" #include "exception.h" #include "util.h" char *cQuarantine::path = NULL; compression_type cQuarantine::compression = _c_none; int cQuarantine::counter = 0; cQuarantine::cQuarantine(const char *quarantine_path, compression_type ctype) { int len; struct stat temp_stat; try { if (!(counter++)) { if (quarantine_path != NULL) { len = strlen(quarantine_path); if (len > 1) trimEndingSlashes((char *) quarantine_path); if (stat((const char *) quarantine_path,&temp_stat) == -1) throw cException(QUARANTINE_CLASS_NAME,QUARANTINE_CLASS_NAME,"stat",errno); else if (!S_ISDIR(temp_stat.st_mode)) throw cException(QUARANTINE_CLASS_NAME,QUARANTINE_CLASS_NAME,"stat",ENOTDIR); else if (access((const char *) quarantine_path,W_OK | X_OK)) throw cException(QUARANTINE_CLASS_NAME,QUARANTINE_CLASS_NAME,"access",errno); else { path = new char[strlen(quarantine_path)+1]; strcpy(path,quarantine_path); syslog(LOG_INFO,"Quarantine enabled"); } } else path = NULL; compression = _c_none; #ifdef HAVE_BZ2 if (ctype == _c_bzip2) { compression = _c_bzip2; syslog(LOG_INFO,"BZip2 compression for quarantine enabled"); } #endif #ifdef HAVE_ZLIB if (ctype == _c_gzip) { compression = _c_gzip; syslog(LOG_INFO,"GZip compression for quarantine enabled"); } #endif } } catch (cException c_e) { syslog(LOG_ERR,"%s",c_e.str); } } cQuarantine::~cQuarantine() { if (!(--counter)) { if (path != NULL) delete [] path; path = NULL; compression = _c_none; } } void cQuarantine::doQuarantine(const char *source) { char tempFileName[256]; char *bigBuffer = NULL; FILE *fp_in = NULL, *fp_out = NULL; size_t b_read; struct stat fStat; struct tm fTime; #ifdef HAVE_BZ2 unsigned int nbytes_in = 0, nbytes_out = 0; int bzerror = BZ_OK; BZFILE *bzfp_out = NULL; #endif #ifdef HAVE_ZLIB int gzErr; gzFile gzfp_out = NULL; #endif try { if (path != NULL) { bigBuffer = new char[BIG_BUFFER_SIZE]; if (stat(source,&fStat) == -1) throw cException(QUARANTINE_CLASS_NAME,"doQuarantine","stat",errno); if (localtime_r(&(fStat.st_ctime),&fTime) == NULL) throw cException(QUARANTINE_CLASS_NAME,"doQuarantine","localtime_r",errno); sprintf(tempFileName,"%s/%d%02d%02d%02d%02d%02d-%s%s",path,fTime.tm_year+1900, fTime.tm_mon+1,fTime.tm_mday,fTime.tm_hour,fTime.tm_min, fTime.tm_sec,basename((char *) source), ((compression == _c_bzip2)? ".bz2" : ((compression == _c_gzip)? ".gz" : ""))); if ((fp_in = fopen(source,"rb")) == NULL) throw cException(QUARANTINE_CLASS_NAME,"doQuarantine","fopen(source)",errno,1); switch (compression) { case _c_bzip2: #ifdef HAVE_BZ2 if ((fp_out = fopen(tempFileName,"wb")) == NULL) throw cException(QUARANTINE_CLASS_NAME,"doQuarantine","fopen(dest)",errno,2); if ((bzfp_out = BZ2_bzWriteOpen(&bzerror,fp_out,BZIP2_100K_BLOCKS,0,0)) == NULL) throw cException(QUARANTINE_CLASS_NAME,"doQuarantine","bzWriteOpen",bzerror,2); #endif break; case _c_gzip: #ifdef HAVE_ZLIB if ((gzfp_out = gzopen(tempFileName,"w")) == NULL) throw cException(QUARANTINE_CLASS_NAME,"doQuarantine","gzopen",((errno)? errno : Z_MEM_ERROR),2); #endif break; case _c_none: if ((fp_out = fopen(tempFileName,"wb")) == NULL) throw cException(QUARANTINE_CLASS_NAME,"doQuarantine","fopen(dest)",errno,2); break; } do { clearerr(fp_in); b_read = fread((void *) bigBuffer,sizeof(char),BIG_BUFFER_SIZE,fp_in); if (ferror(fp_in)) throw cException(QUARANTINE_CLASS_NAME,"doQuarantine","fread",ferror(fp_in),2); switch (compression) { case _c_bzip2: #ifdef HAVE_BZ2 BZ2_bzWrite(&bzerror,bzfp_out,bigBuffer,b_read); if (bzerror != BZ_OK) throw cException(QUARANTINE_CLASS_NAME,"doQuarantine","bzWrite",bzerror,2); #endif break; case _c_gzip: #ifdef HAVE_ZLIB if (!gzwrite(gzfp_out,bigBuffer,b_read)) { gzerror(gzfp_out,&gzErr); throw cException(QUARANTINE_CLASS_NAME,"doQuarantine","gzwrite",((gzErr == Z_ERRNO)? errno : gzErr),2); } #endif break; case _c_none: if (fwrite((void *) bigBuffer,sizeof(char),b_read,fp_out) != b_read) throw cException(QUARANTINE_CLASS_NAME,"doQuarantine","fwrite",ferror(fp_out),2); break; } } while (b_read == BIG_BUFFER_SIZE); if (fclose(fp_in)) throw cException(QUARANTINE_CLASS_NAME,"doQuarantine","fclose(source)",errno,2); switch (compression) { case _c_bzip2: #ifdef HAVE_BZ2 BZ2_bzWriteClose(&bzerror,bzfp_out,0,&nbytes_in,&nbytes_out); if (bzerror != BZ_OK) throw cException(QUARANTINE_CLASS_NAME,"doQuarantine","bzWriteClose",bzerror,2); if (fclose(fp_out)) throw cException(QUARANTINE_CLASS_NAME,"doQuarantine","fclose(dest)",errno,2); #endif break; case _c_gzip: #ifdef HAVE_ZLIB if (gzErr = gzclose(gzfp_out)) throw cException(QUARANTINE_CLASS_NAME,"doQuarantine","gzclose",gzErr,2); #endif break; case _c_none: if (fclose(fp_out)) throw cException(QUARANTINE_CLASS_NAME,"doQuarantine","fclose(dest)",errno,2); break; } sprintf(bigBuffer,"%s file written in quarantine folder",tempFileName); syslog(LOG_INFO,"%s",bigBuffer); delete [] bigBuffer; bigBuffer = NULL; } } catch (cException c_e) { syslog(LOG_ERR,"%s",c_e.str); switch (c_e.err_depth) { case 2: switch (compression) { case _c_bzip2: #ifdef HAVE_BZ2 BZ2_bzWriteClose(&bzerror,bzfp_out,0,&nbytes_in,&nbytes_out); #endif fclose(fp_out); break; case _c_gzip: #ifdef HAVE_ZLIB gzclose(gzfp_out); #endif break; case _c_none: fclose(fp_out); break; } /* Do not put break here! */ case 1: fclose(fp_in); break; default: break; } delete [] bigBuffer; bigBuffer = NULL; } }