add support for --move and --remove options in clamdscan

git-svn: trunk@1144
remotes/push_mirror/metadata
Tomasz Kojm 21 years ago
parent 564b3e0796
commit 63abd169c6
  1. 4
      clamav-devel/ChangeLog
  2. 12
      clamav-devel/clamdscan/clamdscan.c
  3. 167
      clamav-devel/clamdscan/client.c
  4. 3
      clamav-devel/clamscan/options.c
  5. 40
      clamav-devel/clamscan/others.c
  6. 1
      clamav-devel/clamscan/others.h
  7. 8
      clamav-devel/docs/man/clamdscan.1
  8. 45
      clamav-devel/shared/misc.c
  9. 1
      clamav-devel/shared/misc.h

@ -1,3 +1,7 @@
Mon Nov 29 00:23:55 CET 2004 (tk)
---------------------------------
* clamdscan: add support for --move and --remove options
Sun Nov 28 21:08:44 GMT 2004 (njh)
----------------------------------
* libclamav: Email headers of only white space are no longer treated as

@ -40,6 +40,8 @@ void help(void);
short printinfected = 0;
extern int notremoved, notmoved;
void clamscan(struct optstruct *opt)
{
int ds, dms, ret, infected;
@ -105,6 +107,14 @@ void clamscan(struct optstruct *opt)
logg("\n-- summary --\n");
mprintf("Infected files: %d\n", infected);
logg("Infected files: %d\n", infected);
if(notremoved) {
mprintf("Not removed: %d\n", notremoved);
logg("Not removed: %d\n", notremoved);
}
if(notmoved) {
mprintf("Not moved: %d\n", notmoved);
logg("Not moved: %d\n", notmoved);
}
mprintf("Time: %d.%3.3d sec (%d m %d s)\n", ds, dms/1000, ds/60, ds%60);
logg("Time: %d.%3.3d sec (%d m %d s)\n", ds, dms/1000, ds/60, ds%60);
}
@ -128,6 +138,8 @@ void help(void)
mprintf(" --stdout Write to stdout instead of stderr\n");
mprintf(" (this help is always written to stdout)\n");
mprintf(" --log=FILE -l FILE Save scan report in FILE\n");
mprintf(" --remove Remove infected files. Be careful!\n");
mprintf(" --move=DIRECTORY Move infected files into DIRECTORY\n");
mprintf(" --config-file=FILE Read configuration from FILE.\n");
mprintf(" --no-summary Disable summary at end of scanning\n");
mprintf("\n");

@ -21,15 +21,17 @@
#endif
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <utime.h>
#include <errno.h>
#include "others.h"
#include "defaults.h"
@ -38,7 +40,9 @@
#include "cfgparser.h"
#include "memory.h"
#include "output.h"
#include "misc.h"
#include "str.h"
#include "strrcpy.h" /* libclamav */
#ifdef PF_INET
# define SOCKET_INET PF_INET
@ -46,11 +50,13 @@
# define SOCKET_INET AF_INET
#endif
void move_infected(const char *filename, const struct optstruct *opt);
int notremoved = 0, notmoved = 0;
int dsfile(int sockd, const char *filename)
int dsfile(int sockd, const char *filename, const struct optstruct *opt)
{
int infected = 0, waserror = 0;
char buff[4096], *scancmd;
char buff[4096], *scancmd, *pt;
FILE *fd;
@ -75,8 +81,25 @@ int dsfile(int sockd, const char *filename)
infected++;
logg("%s", buff);
mprintf("%s", buff);
if(optl(opt, "move")) {
pt = strrchr(buff, ':');
*pt = 0;
move_infected(buff, opt);
} else if(optl(opt, "remove")) {
pt = strrchr(buff, ':');
*pt = 0;
if(unlink(buff)) {
mprintf("%s: Can't remove.\n", buff);
logg("%s: Can't remove.\n", buff);
notremoved++;
} else {
mprintf("%s: Removed.\n", buff);
logg("%s: Removed.\n", buff);
}
}
}
if (strstr(buff, "ERROR\n")) {
if(strstr(buff, "ERROR\n")) {
logg("%s", buff);
mprintf("%s", buff);
waserror = 1;
@ -91,7 +114,7 @@ int dsfile(int sockd, const char *filename)
return infected ? infected : (waserror ? -1 : 0);
}
int dsstream(int sockd)
int dsstream(int sockd, const struct optstruct *opt)
{
int wsockd, loopw = 60, bread, port, infected = 0;
struct sockaddr_in server;
@ -172,6 +195,23 @@ int dsstream(int sockd)
if(strstr(buff, "FOUND\n")) {
infected++;
logg("%s", buff);
if(optl(opt, "move")) {
pt = strrchr(buff, ':');
*pt = 0;
move_infected(buff, opt);
} else if(optl(opt, "remove")) {
pt = strrchr(buff, ':');
*pt = 0;
if(unlink(buff)) {
mprintf("%s: Can't remove.\n", buff);
logg("%s: Can't remove.\n", buff);
notremoved++;
} else {
mprintf("%s: Removed.\n", buff);
logg("%s: Removed.\n", buff);
}
}
}
if(strstr(buff, "ERROR\n")) {
logg("%s", buff);
@ -307,7 +347,7 @@ int client(const struct optstruct *opt, int *infected)
if((sockd = dconnect(opt)) < 0)
return 2;
if((ret = dsfile(sockd, cwd)) >= 0)
if((ret = dsfile(sockd, cwd, opt)) >= 0)
*infected += ret;
else
errors++;
@ -318,7 +358,7 @@ int client(const struct optstruct *opt, int *infected)
if((sockd = dconnect(opt)) < 0)
return 2;
if((ret = dsstream(sockd)) >= 0)
if((ret = dsstream(sockd, opt)) >= 0)
*infected += ret;
else
errors++;
@ -352,7 +392,7 @@ int client(const struct optstruct *opt, int *infected)
if((sockd = dconnect(opt)) < 0)
return 2;
if((ret = dsfile(sockd, fullpath)) >= 0)
if((ret = dsfile(sockd, fullpath, opt)) >= 0)
*infected += ret;
else
errors++;
@ -372,3 +412,112 @@ int client(const struct optstruct *opt, int *infected)
return *infected ? 1 : (errors ? 2 : 0);
}
void move_infected(const char *filename, const struct optstruct *opt)
{
char *movedir, *movefilename, *tmp, numext[4 + 1];
struct stat fstat, mfstat;
int n, len, movefilename_size;
struct utimbuf ubuf;
if(!(movedir = getargl(opt, "move"))) {
/* Should never reach here */
mprintf("@getargc() returned NULL\n", filename);
notmoved++;
return;
}
if(access(movedir, W_OK|X_OK) == -1) {
mprintf("@error moving file '%s': cannot write to '%s': %s\n", filename, movedir, strerror(errno));
notmoved++;
return;
}
if(stat(filename, &fstat) == -1) {
mprintf("@Can't stat file %s\n", movefilename);
mprintf("Try to run clamdscan with clamd privileges\n");
notmoved++;
return;
}
if(!(tmp = strrchr(filename, '/')))
tmp = (char *) filename;
movefilename_size = sizeof(char) * (strlen(movedir) + strlen(tmp) + sizeof(numext) + 2);
if(!(movefilename = mmalloc(movefilename_size))) {
mprintf("@Memory allocation error\n");
exit(2);
}
if(!(strrcpy(movefilename, movedir))) {
mprintf("@strrcpy() returned NULL\n");
notmoved++;
free(movefilename);
return;
}
strcat(movefilename, "/");
if(!(strcat(movefilename, tmp))) {
mprintf("@strcat() returned NULL\n");
notmoved++;
free(movefilename);
return;
}
if(!stat(movefilename, &mfstat)) {
if(fstat.st_ino == mfstat.st_ino) { /* It's the same file*/
mprintf("File excluded '%s'\n", filename);
logg("File excluded '%s'\n", filename);
notmoved++;
free(movefilename);
return;
} else {
/* file exists - try to append an ordinal number to the
* quranatined file in an attempt not to overwrite existing
* files in quarantine
*/
len = strlen(movefilename);
n = 0;
do {
/* reset the movefilename to it's initial value by
* truncating to the original filename length
*/
movefilename[len] = 0;
/* append .XXX */
sprintf(numext, ".%03d", n++);
strcat(movefilename, numext);
} while(!stat(movefilename, &mfstat) && (n < 1000));
}
}
if(rename(filename, movefilename) == -1) {
if(filecopy(filename, movefilename) == -1) {
mprintf("@cannot move '%s' to '%s': %s\n", filename, movefilename, strerror(errno));
notmoved++;
free(movefilename);
return;
}
chmod(movefilename, fstat.st_mode);
chown(movefilename, fstat.st_uid, fstat.st_gid);
ubuf.actime = fstat.st_atime;
ubuf.modtime = fstat.st_mtime;
utime(movefilename, &ubuf);
if(unlink(filename)) {
mprintf("@cannot unlink '%s': %s\n", filename, strerror(errno));
notremoved++;
free(movefilename);
return;
}
}
mprintf("%s: moved to '%s'\n", filename, movefilename);
logg("%s: moved to '%s'\n", filename, movefilename);
free(movefilename);
}

@ -39,7 +39,8 @@
extern int clamscan(struct optstruct *opt);
static char *clamdscan_long[] = { "help", "version", "verbose", "quiet",
"stdout", "log", "config-file", "no-summary",
"stdout", "log", "move", "remove",
"config-file", "no-summary",
"disable-summary", NULL };
static char clamdscan_short[] = { 'h', 'V', 'v', 'l', 0 };

@ -113,46 +113,6 @@ int checkaccess(const char *path, const char *username, int mode)
return ret;
}
int filecopy(const char *src, const char *dest)
{
#ifdef C_DARWIN
/* On Mac OS X use ditto and copy resource fork, too. */
char *ditto = (char *) mcalloc(strlen(src) + strlen(dest) + 30, sizeof(char));
sprintf(ditto, "/usr/bin/ditto --rsrc %s %s", src, dest);
if(system(ditto)) {
free(ditto);
return -1;
}
free(ditto);
return 0;
#else
char buffer[FILEBUFF];
int s, d, bytes;
if((s = open(src, O_RDONLY)) == -1)
return -1;
if((d = open(dest, O_CREAT|O_WRONLY|O_TRUNC)) == -1) {
close(s);
return -1;
}
while((bytes = read(s, buffer, FILEBUFF)) > 0)
write(d, buffer, bytes);
close(s);
/* njh@bandsman.co.uk: check result of close for NFS file */
return close(d);
#endif //__APPLE_CC__
}
int isnumb(const char *str)
{
int i;

@ -21,7 +21,6 @@
int fileinfo(const char *filename, short i);
int checkaccess(const char *path, const char *username, int mode);
int filecopy(const char *src, const char *dest);
int isnumb(const char *str);
#endif

@ -1,5 +1,5 @@
.\" Manual page created by Tomasz Kojm, 20021121
.TH "Clamd client" "1" "February 20, 2004" "Tomasz Kojm" "Clam AntiVirus"
.TH "Clamd client" "1" "November 29, 2004" "Tomasz Kojm" "Clam AntiVirus"
.SH "NAME"
.LP
clamdscan \- scan files and directories against viruses using Clam AntiVirus Daemon
@ -34,6 +34,12 @@ Read clamd settings from FILE.
\fB\-l FILE, \-\-log=FILE\fR
Save the scan report to FILE.
.TP
\fB\-\-remove\fR
Remove infected files. \fBBe careful.\fR
.TP
\fB\-\-move=DIRECTORY\fR
Move infected files into DIRECTORY.
.TP
\fB\-\-no\-summary\fR
Do not display summary at the end of scanning.
.SH "EXAMPLES"

@ -21,8 +21,13 @@
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "clamav.h"
#include "cfgparser.h"
@ -92,3 +97,43 @@ void print_version(void)
free(path);
}
int filecopy(const char *src, const char *dest)
{
#ifdef C_DARWIN
/* On Mac OS X use ditto and copy resource fork, too. */
char *ditto = (char *) mcalloc(strlen(src) + strlen(dest) + 30, sizeof(char));
sprintf(ditto, "/usr/bin/ditto --rsrc %s %s", src, dest);
if(system(ditto)) {
free(ditto);
return -1;
}
free(ditto);
return 0;
#else
char buffer[FILEBUFF];
int s, d, bytes;
if((s = open(src, O_RDONLY)) == -1)
return -1;
if((d = open(dest, O_CREAT|O_WRONLY|O_TRUNC)) == -1) {
close(s);
return -1;
}
while((bytes = read(s, buffer, FILEBUFF)) > 0)
write(d, buffer, bytes);
close(s);
/* njh@bandsman.co.uk: check result of close for NFS file */
return close(d);
#endif
}

@ -23,5 +23,6 @@
const char *freshdbdir(void);
void print_version(void);
int filecopy(const char *src, const char *dest);
#endif

Loading…
Cancel
Save