... | ... |
@@ -119,13 +119,17 @@ typedef struct _CLAM_SCAN_INFO { |
119 | 119 |
const wchar_t *pThreatName; |
120 | 120 |
|
121 | 121 |
/** The handle of the file being processed **/ |
122 |
- /* Note #1: the handle MUST NOT BE CLOSED by the callback |
|
123 |
- * Note #2: the handle has got GENERIC_READ access |
|
122 |
+ /* Note #1: the handle MUST BE CLOSED by the caller, at any point |
|
123 |
+ * Note #2: the has FILE_ATTRIBUTE_TEMPORARY and FILE_FLAG_DELETE_ON_CLOSE attributes |
|
124 | 124 |
* Note #3: the file pointer is guaranteed to be set at the begin of |
125 |
- * the file and its position needs not to be reset |
|
126 |
- * Note #4: the file may already be mapped into memory, entirely or just partially */ |
|
125 |
+ * the file and its position needs not to be reset */ |
|
127 | 126 |
/* Presence: SCAN_PHASE_PRESCAN, SCAN_PHASE_POSTSCAN */ |
128 | 127 |
HANDLE object; |
128 |
+ |
|
129 |
+ /** An unique identifier for the file being processed **/ |
|
130 |
+ /* Provided for mapping purposes (type HANDLE for legacy reasons) */ |
|
131 |
+ /* Presence: SCAN_PHASE_PRESCAN, SCAN_PHASE_POSTSCAN */ |
|
132 |
+ HANDLE objectId; |
|
129 | 133 |
|
130 | 134 |
/** The path of inner file relative to file being scanned **/ |
131 | 135 |
/* This applies only to archive for which internal names can be retrieved and is NULL otherwise */ |
... | ... |
@@ -984,12 +984,14 @@ int CLAMAPI Scan_DeleteScanInfo(CClamAVScanner *pScanner, PCLAM_SCAN_INFO_LIST p |
984 | 984 |
|
985 | 985 |
cl_error_t prescan_cb(int fd, void *context) { |
986 | 986 |
struct scan_ctx *sctx = (struct scan_ctx *)context; |
987 |
+ char tmpf[4096]; |
|
987 | 988 |
instance *inst; |
988 | 989 |
CLAM_SCAN_INFO si; |
989 | 990 |
CLAM_ACTION act; |
990 | 991 |
HANDLE fdhdl; |
991 | 992 |
DWORD perf; |
992 |
- LONG lo = 0, hi = 0, hi2 = 0; |
|
993 |
+ long fpos; |
|
994 |
+ int rsz; |
|
993 | 995 |
|
994 | 996 |
if(!context) { |
995 | 997 |
logg("!prescan_cb called with NULL clamav context\n"); |
... | ... |
@@ -1003,18 +1005,42 @@ cl_error_t prescan_cb(int fd, void *context) { |
1003 | 1003 |
si.errorCode = CLAMAPI_SUCCESS; |
1004 | 1004 |
si.pThreatType = NULL; |
1005 | 1005 |
si.pThreatName = NULL; |
1006 |
- fdhdl = si.object = (HANDLE)_get_osfhandle(fd); |
|
1007 | 1006 |
si.pInnerObjectPath = NULL; |
1008 | 1007 |
|
1009 |
- lo = SetFilePointer(fdhdl, 0, &hi, FILE_CURRENT); |
|
1010 |
- SetFilePointer(fdhdl, 0, &hi2, FILE_BEGIN); |
|
1008 |
+ while(1) { |
|
1009 |
+ static int tmpn; |
|
1010 |
+ snprintf(tmpf, sizeof(tmpf), "%s\\%08x.tmp", tmpdir, ++tmpn); |
|
1011 |
+ tmpf[sizeof(tmpf)-1] = '\0'; |
|
1012 |
+ fdhdl = CreateFile(tmpf, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL); |
|
1013 |
+ if(fdhdl != INVALID_HANDLE_VALUE) break; |
|
1014 |
+ /* FIXME: handle non dup filename errors */ |
|
1015 |
+ } |
|
1016 |
+ |
|
1017 |
+ fpos = lseek(fd, 0, SEEK_CUR); |
|
1018 |
+ lseek(fd, 0, SEEK_SET); |
|
1019 |
+ while((rsz = read(fd, tmpf, sizeof(tmpf))) > 0) { |
|
1020 |
+ int wsz = 0; |
|
1021 |
+ while(wsz != rsz) { |
|
1022 |
+ DWORD rwsz; |
|
1023 |
+ if(!WriteFile(fdhdl, &tmpf[wsz], rsz - wsz, &rwsz, NULL)) { |
|
1024 |
+ /* FIXME: handle write fail here */ |
|
1025 |
+ } |
|
1026 |
+ wsz += rwsz; |
|
1027 |
+ } |
|
1028 |
+ } |
|
1029 |
+ if(rsz) { |
|
1030 |
+ /* FIXME: handle read fail here */ |
|
1031 |
+ } |
|
1032 |
+ lseek(fd, fpos, SEEK_SET); |
|
1033 |
+ SetFilePointer(fdhdl, 0, NULL, FILE_BEGIN); |
|
1034 |
+ si.object = fdhdl; |
|
1035 |
+ si.objectId = (HANDLE)_get_osfhandle(fd); |
|
1011 | 1036 |
logg("*prescan_cb (clamav context %p, instance %p) invoking callback %p with context %p\n", context, inst, inst->scancb, inst->scancb_ctx); |
1012 | 1037 |
perf = GetTickCount(); |
1013 | 1038 |
inst->scancb(&si, &act, inst->scancb_ctx); |
1014 | 1039 |
perf = GetTickCount() - perf; |
1015 | 1040 |
sctx->cb_times += perf; |
1016 | 1041 |
logg("*prescan_cb (clamav context %p, instance %p) callback completed with %u in %u ms\n", context, inst, act, perf); |
1017 |
- SetFilePointer(fdhdl, lo, &hi, FILE_BEGIN); |
|
1018 | 1042 |
switch(act) { |
1019 | 1043 |
case CLAM_ACTION_SKIP: |
1020 | 1044 |
logg("*prescan_cb (clamav context %p, instance %p) cb result: SKIP\n", context, inst); |
... | ... |
@@ -1036,10 +1062,8 @@ cl_error_t postscan_cb(int fd, int result, const char *virname, void *context) { |
1036 | 1036 |
instance *inst; |
1037 | 1037 |
CLAM_SCAN_INFO si; |
1038 | 1038 |
CLAM_ACTION act; |
1039 |
- HANDLE fdhdl; |
|
1040 | 1039 |
DWORD perf; |
1041 | 1040 |
wchar_t wvirname[MAX_VIRNAME_LEN] = L"Clam."; |
1042 |
- LONG lo = 0, hi = 0, hi2 = 0; |
|
1043 | 1041 |
|
1044 | 1042 |
if(!context) { |
1045 | 1043 |
logg("!postscan_cb called with NULL clamav context\n"); |
... | ... |
@@ -1062,17 +1086,15 @@ cl_error_t postscan_cb(int fd, int result, const char *virname, void *context) { |
1062 | 1062 |
si.pThreatName = NULL; |
1063 | 1063 |
logg("*in postscan_cb with clamav context %p, instance %p, fd %d, result %d, virusname %S)\n", context, inst, fd, result, si.pThreatName); |
1064 | 1064 |
si.pThreatType = threat_type(virname); |
1065 |
- fdhdl = si.object = (HANDLE)_get_osfhandle(fd); |
|
1065 |
+ si.objectId = (HANDLE)_get_osfhandle(fd); |
|
1066 |
+ si.object = INVALID_HANDLE_VALUE; |
|
1066 | 1067 |
si.pInnerObjectPath = NULL; |
1067 |
- lo = SetFilePointer(fdhdl, 0, &hi, FILE_CURRENT); |
|
1068 |
- SetFilePointer(fdhdl, 0, &hi2, FILE_BEGIN); |
|
1069 | 1068 |
logg("*postscan_cb (clamav context %p, instance %p) invoking callback %p with context %p\n", context, inst, inst->scancb, inst->scancb_ctx); |
1070 | 1069 |
perf = GetTickCount(); |
1071 | 1070 |
inst->scancb(&si, &act, inst->scancb_ctx); |
1072 | 1071 |
perf = GetTickCount() - perf; |
1073 | 1072 |
sctx->cb_times += perf; |
1074 | 1073 |
logg("*postscan_cb (clamav context %p, instance %p) callback completed with %u in %u ms\n", context, inst, act, perf); |
1075 |
- SetFilePointer(fdhdl, lo, &hi, FILE_BEGIN); |
|
1076 | 1074 |
switch(act) { |
1077 | 1075 |
case CLAM_ACTION_SKIP: |
1078 | 1076 |
logg("*postscan_cb (clamav context %p, instance %p) cb result: SKIP\n", context, inst); |