mirror of
https://github.com/Cisco-Talos/clamav.git
synced 2026-05-07 15:15:40 -04:00
win32: globbing
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
Sun Oct 18 02:30:14 CEST 2009 (acab)
|
||||
------------------------------------
|
||||
* win32: glob() before main (WIP)
|
||||
|
||||
Fri Oct 16 20:08:51 CEST 2009 (acab)
|
||||
------------------------------------
|
||||
* win32: stat added, dirent updated
|
||||
|
||||
@@ -196,6 +196,10 @@
|
||||
RelativePath=".\compat\libgen.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\compat\setargv.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="shared"
|
||||
|
||||
@@ -28,18 +28,19 @@
|
||||
#define _DIRENT_HAVE_D_TYPE
|
||||
typedef unsigned short ino_t; /* WTF?!? */
|
||||
|
||||
struct dirent {
|
||||
ino_t d_ino; /* inode number */
|
||||
unsigned char d_type; /* type of file */
|
||||
char d_name[MAX_PATH]; /* filename */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
HANDLE dh;
|
||||
WIN32_FIND_DATAW wfd;
|
||||
struct dirent {
|
||||
ino_t d_ino; /* inode number */
|
||||
unsigned char d_type; /* type of file */
|
||||
char d_name[MAX_PATH]; /* filename */
|
||||
} ent;
|
||||
struct dirent ent;
|
||||
wchar_t entry[PATH_MAX];
|
||||
} DIR;
|
||||
|
||||
|
||||
enum {
|
||||
DT_BLOCK,
|
||||
DT_CHR,
|
||||
|
||||
226
win32/compat/setargv.c
Normal file
226
win32/compat/setargv.c
Normal file
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Sourcefire, Inc.
|
||||
*
|
||||
* Authors: aCaB <acab@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 "dirent.h"
|
||||
#include "libgen.h"
|
||||
|
||||
/* THIS IS A HACK ! */
|
||||
/* _setargv is the designed way to customize command line parsing which we use here
|
||||
for globbing reasons (incidentally the globbing in setargv.obj is badly broken)
|
||||
|
||||
The crt first calls OUR _setargv from pre_c_init but later, from within pre_cpp_init,
|
||||
it also calls ITS OWN BUILTIN NATIVE CRAP, which re-parses the command line and
|
||||
eventually overrides our override.
|
||||
|
||||
So, we additionally replace the command line global pointer _acmdln with a
|
||||
crafted set of arguments in order to fool buggy CRT's.
|
||||
*/
|
||||
#define _MY_CRT_INSISTS_ON_PARSING_THE_COMMAND_LINE_TWICE_FOR_NO_REASONS_
|
||||
#ifdef _MY_CRT_INSISTS_ON_PARSING_THE_COMMAND_LINE_TWICE_FOR_NO_REASONS_
|
||||
extern char ** __p__acmdln(void);
|
||||
#endif
|
||||
|
||||
void glob_add(const char *path, int *argc, char ***argv);
|
||||
|
||||
int _setargv() {
|
||||
char *cur = GetCommandLineA(), *begparm = NULL, *endparm = NULL;
|
||||
char **argv = NULL, c;
|
||||
int argc = 0, i, in_sq = 0, in_dq = 0, need_glob = 0;
|
||||
int *g_argc = __p___argc();
|
||||
char ***g_argv = __p___argv();
|
||||
|
||||
do {
|
||||
c = *cur;
|
||||
switch(c) {
|
||||
case '\0':
|
||||
endparm = cur;
|
||||
break;
|
||||
case ' ':
|
||||
if(begparm && !(in_sq | in_dq))
|
||||
endparm = cur;
|
||||
break;
|
||||
case '\'':
|
||||
if(!in_dq) {
|
||||
in_sq = !in_sq;
|
||||
if(!in_sq)
|
||||
endparm = cur;
|
||||
}
|
||||
break;
|
||||
case '"':
|
||||
if(!in_sq) {
|
||||
in_dq = !in_dq;
|
||||
if(!in_dq)
|
||||
endparm = cur;
|
||||
}
|
||||
break;
|
||||
case '*':
|
||||
// case '?':
|
||||
if(!in_sq)
|
||||
need_glob = 1;
|
||||
default:
|
||||
if(!begparm) {
|
||||
begparm = cur;
|
||||
endparm = NULL;
|
||||
}
|
||||
}
|
||||
if (begparm && endparm) {
|
||||
if(begparm < endparm) {
|
||||
char *path = malloc(endparm - begparm + 1);
|
||||
|
||||
memcpy(path, begparm, endparm - begparm);
|
||||
path[endparm - begparm] = '\0';
|
||||
if(argc || need_glob)
|
||||
glob_add(path, &argc, &argv);
|
||||
else {
|
||||
argv = realloc(argv, sizeof(*argv) * (argc + 1));
|
||||
argv[argc] = path;
|
||||
argc++;
|
||||
}
|
||||
}
|
||||
need_glob = 0;
|
||||
in_sq = 0;
|
||||
in_dq = 0;
|
||||
begparm = NULL;
|
||||
endparm = NULL;
|
||||
}
|
||||
cur++;
|
||||
} while (c);
|
||||
|
||||
if(argc) {
|
||||
int i, argvlen = sizeof(*argv) * (argc + 1), argclen = 0;
|
||||
argv = realloc(argv, argvlen);
|
||||
argv[argc] = NULL;
|
||||
for(i=0; i<argc; i++) {
|
||||
int curlen = strlen(argv[i]) + 1;
|
||||
char *curarg;
|
||||
argv = realloc(argv, argvlen + argclen + curlen);
|
||||
curarg = (char *)argv + argvlen + argclen;
|
||||
memcpy(curarg, argv[i], curlen);
|
||||
argclen += curlen;
|
||||
free(argv[i]);
|
||||
argv[i] = curarg;
|
||||
}
|
||||
#ifdef _MY_CRT_INSISTS_ON_PARSING_THE_COMMAND_LINE_TWICE_FOR_NO_REASONS_
|
||||
{
|
||||
char *fake_cmdl = malloc(argclen + 1 + 2*argc);
|
||||
char *curarg = fake_cmdl;
|
||||
char **g_cmdl = __p__acmdln();
|
||||
for(i=0; i<argc; i++)
|
||||
curarg += sprintf(curarg, "\"%s\" ", argv[i]);
|
||||
curarg--;
|
||||
*curarg = '\0';
|
||||
*g_cmdl = fake_cmdl;
|
||||
}
|
||||
#endif
|
||||
*g_argc = argc;
|
||||
*g_argv = argv;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void glob_add(const char *path, int *argc, char ***argv) {
|
||||
char *tail = strchr(path, '*');
|
||||
char *dup1, *dup2, *dir, *base, *taildirsep, *tailwldsep;
|
||||
struct dirent *de;
|
||||
int baselen, taillen, dirlen, mergedir = 0;
|
||||
DIR *d;
|
||||
|
||||
if(!tail) {
|
||||
MessageBox(0, path, 0, MB_ICONINFORMATION);
|
||||
*argv = realloc(*argv, sizeof(**argv) * (*argc + 1));
|
||||
(*argv)[*argc] = path;
|
||||
(*argc)++;
|
||||
return;
|
||||
}
|
||||
|
||||
if(tail!=path && tail[-1] == '\\') {
|
||||
tail[-1] = '\0';
|
||||
mergedir = 1;
|
||||
}
|
||||
*tail = '\0';
|
||||
tail++;
|
||||
taillen = strlen(tail);
|
||||
taildirsep = strchr(tail, '\\');
|
||||
if(taildirsep && taildirsep - tail == taillen - 1) {
|
||||
*taildirsep = '\0';
|
||||
taildirsep = NULL;
|
||||
taillen--;
|
||||
}
|
||||
if(!taildirsep)
|
||||
taildirsep = tail + taillen;
|
||||
if(!(tailwldsep = strchr(tail, '*')))
|
||||
tailwldsep = tail + taillen;
|
||||
|
||||
dup1 = strdup(path);
|
||||
dup2 = strdup(path);
|
||||
|
||||
if(!mergedir) {
|
||||
dir = dirname(dup1);
|
||||
base = basename(dup2);
|
||||
} else {
|
||||
dir = dup1;
|
||||
base = dup2;
|
||||
*dup2 = '\0';
|
||||
}
|
||||
|
||||
dirlen = strlen(dir);
|
||||
baselen = strlen(base);
|
||||
|
||||
d = opendir(dir);
|
||||
while(d && (de = readdir(d))) {
|
||||
int namelen = strlen(de->d_name);
|
||||
char *newpath;
|
||||
|
||||
if(namelen < baselen) continue;
|
||||
if(strncasecmp(base, de->d_name, baselen)) continue;
|
||||
if(de->d_type == DT_DIR && taildirsep <= tailwldsep) {
|
||||
int d_taillen = taildirsep - tail;
|
||||
if(namelen < baselen + d_taillen) continue;
|
||||
if(strncasecmp(tail, &de->d_name[namelen - d_taillen], d_taillen)) continue;
|
||||
newpath = malloc(dirlen + namelen + taillen - d_taillen + 3);
|
||||
sprintf(newpath, "%s\\%s\\%s", dir, de->d_name, &tail[d_taillen+1]);
|
||||
glob_add(newpath, argc, argv);
|
||||
} else {
|
||||
int d_taillen = tailwldsep - tail;
|
||||
char *start;
|
||||
if(namelen < baselen + d_taillen) continue;
|
||||
|
||||
start = &de->d_name[baselen];
|
||||
namelen -= baselen;
|
||||
|
||||
for(; namelen >= d_taillen; start++, namelen--) {
|
||||
if(strncasecmp(start, tail, d_taillen)) continue;
|
||||
newpath = malloc(dirlen + (start - de->d_name) + taillen + 2);
|
||||
sprintf(newpath, "%s\\", dir);
|
||||
memcpy(&newpath[dirlen + 1], de->d_name, start - de->d_name);
|
||||
strcpy(&newpath[dirlen + 1 + start - de->d_name], tail);
|
||||
glob_add(newpath, argc, argv);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(d) closedir(d);
|
||||
free(dup1);
|
||||
free(dup2);
|
||||
free(path);
|
||||
}
|
||||
Reference in New Issue
Block a user