| 
									
										
										
										
											2009-02-12 15:14:12 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *  Copyright (C) 2009 Sourcefire, Inc. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  Author: aCaB | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  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>
 | 
					
						
							| 
									
										
										
										
											2009-07-26 18:56:13 +02:00
										 |  |  | #if HAVE_UNISTD_H
 | 
					
						
							| 
									
										
										
										
											2009-02-12 15:14:12 +00:00
										 |  |  | #include <unistd.h>
 | 
					
						
							| 
									
										
										
										
											2009-07-26 18:56:13 +02:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-02-12 15:14:12 +00:00
										 |  |  | #include <fcntl.h>
 | 
					
						
							|  |  |  | #include <utime.h>
 | 
					
						
							|  |  |  | #include <errno.h>
 | 
					
						
							|  |  |  | #include <libgen.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "shared/optparser.h"
 | 
					
						
							|  |  |  | #include "shared/output.h"
 | 
					
						
							|  |  |  | #include "shared/misc.h"
 | 
					
						
							| 
									
										
										
										
											2009-05-05 14:31:53 +00:00
										 |  |  | #include "shared/actions.h"
 | 
					
						
							| 
									
										
										
										
											2009-02-12 15:14:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | void (*action)(const char *) = NULL; | 
					
						
							|  |  |  | unsigned int notmoved = 0, notremoved = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char *actarget; | 
					
						
							|  |  |  | static int targlen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-05 14:31:53 +00:00
										 |  |  | static int getdest(const char *fullpath, char **newname) { | 
					
						
							| 
									
										
										
										
											2009-02-12 15:14:12 +00:00
										 |  |  |     char *tmps, *filename; | 
					
						
							|  |  |  |     int fd, i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     tmps = strdup(fullpath); | 
					
						
							| 
									
										
										
										
											2009-03-29 11:41:14 +00:00
										 |  |  |     if(!tmps) { | 
					
						
							|  |  |  |         *newname=NULL; | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-02-12 15:14:12 +00:00
										 |  |  |     filename = basename(tmps); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if(!(*newname = (char *)malloc(targlen + strlen(filename) + 6))) { | 
					
						
							|  |  |  | 	free(tmps); | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     sprintf(*newname, "%s/%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/%s.%03u", actarget, filename, i); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     free(tmps); | 
					
						
							|  |  |  |     free(*newname); | 
					
						
							|  |  |  |     *newname = NULL; | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void action_move(const char *filename) { | 
					
						
							|  |  |  |     char *nuname; | 
					
						
							| 
									
										
										
										
											2009-03-29 11:41:14 +00:00
										 |  |  |     int fd = getdest(filename, &nuname), copied = 0; | 
					
						
							| 
									
										
										
										
											2009-02-12 15:14:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-29 11:48:09 +00:00
										 |  |  |     if(fd<0 || (rename(filename, nuname) && (copied=1) && filecopy(filename, nuname))) { | 
					
						
							| 
									
										
										
										
											2009-02-12 15:14:12 +00:00
										 |  |  | 	logg("!Can't move file %s\n", filename); | 
					
						
							|  |  |  | 	notmoved++; | 
					
						
							|  |  |  | 	if(nuname) unlink(nuname); | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2009-03-29 11:41:14 +00:00
										 |  |  | 	if(copied && unlink(filename)) | 
					
						
							| 
									
										
										
										
											2009-02-12 15:14:12 +00:00
										 |  |  | 	    logg("!Can't unlink '%s': %s\n", filename, strerror(errno)); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	    logg("~%s: moved to '%s'\n", filename, nuname); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if(fd>=0) close(fd); | 
					
						
							|  |  |  |     if(nuname) free(nuname); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void action_copy(const char *filename) { | 
					
						
							|  |  |  |     char *nuname; | 
					
						
							|  |  |  |     int fd = getdest(filename, &nuname); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if(fd < 0 || filecopy(filename, nuname)) { | 
					
						
							|  |  |  | 	logg("!Can't copy file '%s'\n", filename); | 
					
						
							|  |  |  | 	notmoved++; | 
					
						
							|  |  |  | 	if(nuname) unlink(nuname); | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  | 	logg("~%s: copied to '%s'\n", filename, nuname); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if(fd>=0) close(fd); | 
					
						
							|  |  |  |     if(nuname) free(nuname); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void action_remove(const char *filename) { | 
					
						
							|  |  |  |     if(unlink(filename)) { | 
					
						
							| 
									
										
										
										
											2009-02-12 17:54:15 +00:00
										 |  |  | 	logg("!Can't remove file '%s'.\n", filename); | 
					
						
							| 
									
										
										
										
											2009-02-12 15:14:12 +00:00
										 |  |  | 	notremoved++; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  | 	logg("~%s: Removed.\n", filename); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-05 14:31:53 +00:00
										 |  |  | static int isdir(void) { | 
					
						
							| 
									
										
										
										
											2009-02-12 15:14:12 +00:00
										 |  |  |     struct stat sb; | 
					
						
							|  |  |  |     if(stat(actarget, &sb) || !S_ISDIR(sb.st_mode)) { | 
					
						
							|  |  |  | 	logg("!'%s' doesn't exist or is not a directory\n", actarget); | 
					
						
							| 
									
										
										
										
											2009-03-04 01:58:56 +00:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2009-02-12 15:14:12 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-03-04 01:58:56 +00:00
										 |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											2009-02-12 15:14:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int actsetup(const struct optstruct *opts) { | 
					
						
							|  |  |  |     int move = optget(opts, "move")->enabled; | 
					
						
							|  |  |  |     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; | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } |