ee6702ab |
/* |
e1cbc270 |
* Copyright (C) 2013-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2009-2013 Sourcefire, Inc. |
ee6702ab |
*
* Author: aCaB
* |
a5b34b87 |
* These functions are actions that may be taken when a sample alerts.
* The user may wish to:
* - move file to destination directory.
* - copy file to destination directory.
* - remove (delete) the file.
* |
ee6702ab |
* 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> |
f235c57a |
#if HAVE_UNISTD_H |
ee6702ab |
#include <unistd.h> |
f235c57a |
#endif |
ee6702ab |
#include <fcntl.h>
#include <errno.h>
#include <libgen.h>
|
a2a004df |
#include "libclamav/clamav.h" |
ee6702ab |
#include "shared/optparser.h"
#include "shared/output.h"
#include "shared/misc.h" |
c71a0353 |
#include "shared/actions.h" |
ee6702ab |
void (*action)(const char *) = NULL;
unsigned int notmoved = 0, notremoved = 0;
static char *actarget;
static int targlen;
|
288057e9 |
static int getdest(const char *fullpath, char **newname)
{ |
ee6702ab |
char *tmps, *filename;
int fd, i;
tmps = strdup(fullpath); |
288057e9 |
if (!tmps) {
*newname = NULL; |
52520dd4 |
return -1;
} |
ee6702ab |
filename = basename(tmps);
|
288057e9 |
if (!(*newname = (char *)malloc(targlen + strlen(filename) + 6))) {
free(tmps);
return -1; |
ee6702ab |
} |
288057e9 |
sprintf(*newname, "%s" PATHSEP "%s", actarget, filename);
for (i = 1; i < 1000; i++) {
fd = open(*newname, O_WRONLY | O_CREAT | O_EXCL, 0600);
if (fd >= 0) {
free(tmps);
return fd;
}
if (errno != EEXIST) break;
sprintf(*newname, "%s" PATHSEP "%s.%03u", actarget, filename, i); |
ee6702ab |
}
free(tmps);
free(*newname);
*newname = NULL;
return -1;
}
|
288057e9 |
static void action_move(const char *filename)
{ |
ee6702ab |
char *nuname; |
52520dd4 |
int fd = getdest(filename, &nuname), copied = 0; |
ee6702ab |
|
a5b34b87 |
if (fd < 0 || (rename(filename, nuname) && ((copied = 1)) && filecopy(filename, nuname))) { |
288057e9 |
logg("!Can't move file %s\n", filename);
notmoved++;
if (nuname) unlink(nuname); |
ee6702ab |
} else { |
288057e9 |
if (copied && unlink(filename))
logg("!Can't unlink '%s': %s\n", filename, strerror(errno));
else
logg("~%s: moved to '%s'\n", filename, nuname); |
ee6702ab |
}
|
288057e9 |
if (fd >= 0) close(fd);
if (nuname) free(nuname); |
ee6702ab |
}
|
288057e9 |
static void action_copy(const char *filename)
{ |
ee6702ab |
char *nuname;
int fd = getdest(filename, &nuname);
|
288057e9 |
if (fd < 0 || filecopy(filename, nuname)) {
logg("!Can't copy file '%s'\n", filename);
notmoved++;
if (nuname) unlink(nuname); |
ee6702ab |
} else |
288057e9 |
logg("~%s: copied to '%s'\n", filename, nuname); |
ee6702ab |
|
288057e9 |
if (fd >= 0) close(fd);
if (nuname) free(nuname); |
ee6702ab |
}
|
288057e9 |
static void action_remove(const char *filename)
{
if (unlink(filename)) {
logg("!Can't remove file '%s'.\n", filename);
notremoved++; |
ee6702ab |
} else { |
288057e9 |
logg("~%s: Removed.\n", filename); |
ee6702ab |
}
}
|
288057e9 |
static int isdir(void)
{ |
a2a004df |
STATBUF sb; |
288057e9 |
if (CLAMSTAT(actarget, &sb) || !S_ISDIR(sb.st_mode)) {
logg("!'%s' doesn't exist or is not a directory\n", actarget);
return 0; |
ee6702ab |
} |
f23454aa |
return 1; |
ee6702ab |
}
|
a5b34b87 |
/*
* Call this function at the beginning to configure the user preference.
* Later, call the "action" callback function to perform the selection action.
*/ |
288057e9 |
int actsetup(const struct optstruct *opts)
{ |
ee6702ab |
int move = optget(opts, "move")->enabled; |
288057e9 |
if (move || optget(opts, "copy")->enabled) {
actarget = optget(opts, move ? "move" : "copy")->strarg;
if (!isdir()) return 1;
action = move ? action_move : action_copy;
targlen = strlen(actarget);
} else if (optget(opts, "remove")->enabled)
action = action_remove; |
ee6702ab |
return 0;
} |